Chapter 3 - Functional Components of Azure RTOS NetX

This chapter contains a description of the high-performance Azure RTOS NetX TCP/IP stack from a functional perspective.

Execution Overview

There are five types of program execution within a NetX application: initialization, application interface calls, internal IP thread, IP periodic timers, and the network driver.

Important

NetX requires the installation of ThreadX and depends on its thread execution, suspension, periodic timers, and mutual exclusion facilities.

Initialization

The service nx_system_initialize must be called before any other NetX service is called. System initialization can be called either from the ThreadX tx_application_define routine or from application threads.

After nx_system_initialize returns, the system is ready to create packet pools and IP instances. Because creating an IP instance requires a default packet pool, at least one NetX packet pool must exist prior to creating an IP instance. Creating packet pools and IP instances are allowed from the ThreadX initialization function tx_application_define and from application threads.

Internally, creating an IP instance is accomplished in two parts. The first part is done within the context of the caller, either from tx_application_define or from an application thread's context. This includes setting up the IP data structure and creating various IP resources, including the internal IP thread. The second part is performed during the initial execution from the internal IP thread. This is where the network driver, supplied during the first part of IP creation, is first called. Calling the network driver from the internal IP thread enables the driver to perform I/O and suspend during its initialization processing. When the network driver returns from its initialization processing, the IP creation is complete.

Important

The NetX service nx_ip_status_check is available to obtain information on the IP instance and its primary interface status. Such status information includes whether or not the link is initialized, enabled, and IP address is resolved. This information is used to synchronize application threads needing to use a newly created IP instance. For multihome systems, see "Multihome Support" below. nx_ip_interface_status_check is available to obtain information on the specified interface.

Application Interface Calls

Calls from the application are largely made from application threads running under the ThreadX RTOS. However, some initialization, create, and enable services may be called from tx_application_define. The "Allowed From" sections in Chapter 4 indicate from which each NetX service can be called.

For the most part, processing intensive activities such as computing checksums is done within the calling thread's context—without blocking the access of other threads to the IP instance. For example, on transmission, the UDP checksum calculation is performed inside the nx_udp_socket_send service, prior to calling the underlying IP send function. On a received packet, the UDP checksum is calculated in the nx_udp_socket_receive service, executed in the context of the application thread. This helps prevent stalling network requests of higher-priority threads because of processing intensive checksum computation in lower-priority threads.

Values, such as IP addresses and port numbers, are passed to API functions in host byte order. Internally these values are stored in host byte order as well. This enables developers to easily view the values via a debugger. When these values are programmed into a frame for transmission, they are converted to network byte order.

Internal IP Thread

As mentioned, each IP instance in NetX has its own thread. The priority and stack size of the internal IP thread is defined in the nx_ip_create service. The internal IP thread is created in a ready-to-execute mode. If the IP thread has a higher priority than the calling thread, preemption may occur inside the IP create call.

The entry point of the internal IP thread is at the internal function _nx_ip_thread_entry. When started, the internal IP thread first completes network driver initialization, which consists of making three calls to the application-specific network driver. The first call is to attach the network driver to the IP instance, followed by an initialization call, which allows the network driver to go through the initialization process. After the network driver returns from initialization (it may suspend while waiting for the hardware to be properly set up), the internal IP thread calls the network driver again to enable the link.

After the network driver returns from the link enable call, the internal IP thread enters an endless loop checking for various events that need processing for this IP instance. Events processed in this loop include deferred IP packet reception, IP packet fragment assembly, ICMP ping processing, IGMP processing, TCP packet queue processing, TCP periodic processing, IP fragment assembly timeouts, and IGMP periodic processing. Events also include address resolution activities: ARP packet processing and ARP periodic processing in the IP network.

Note

The NetX callback functions, including listen and disconnect callbacks, are called from the internal IP thread—not the original calling thread. The application must take care not to suspend inside any NetX callback function.

IP Periodic Timers

There are two ThreadX periodic timers used for each IP instance. The first one is a one-second timer for ARP, IGMP, TCP timeout, and it also drives IP fragment reassemble processing. The second timer is a 100ms timer to drive the TCP retransmission timeout.

Network Driver

Each IP instance in NetX has a primary interface, which is identified by its device driver specified in the nx_ip_create service. The network driver is responsible for handling various NetX requests, including packet transmission, packet reception, and requests for status and control.

For a multi-home system, the IP instance has multiple interfaces, each with an associated network driver that performs these tasks for the respective interface.

The network driver must also handle asynchronous events occurring on the media. Asynchronous events from the media include packet reception, packet transmission completion, and status changes. NetX provides the network driver with several access functions to handle various events. These functions are designed to be called from the interrupt service routine portion of the network driver. For IP networks, the network driver should forward all ARP packets received to the _nx_arp_packet_deferred_receive internal function. All RARP packets should be forwarded to _nx_rarp_packet_deferred_receive internal function. There are two options for IP packets. If fast dispatch of IP packets is required, incoming IP packets should be forwarded to _nx_ip_packet_receive for immediate processing. This greatly improves NetX performance in handling IP packets. Otherwise, the network driver should forward IP packets to _nx_ip_packet_deferred_receive. This service places the IP packet in the deferred processing queue where it is then handled by the internal IP thread, which results in the least amount of ISR processing time.

The network driver can also defer interrupt processing to run out of the context of the IP thread. In this mode, the ISR shall save the necessary information, call the internal function _nx_ip_driver_deferred_processing, and acknowledge the interrupt controller. This service notifies IP thread to schedule a callback to the device driver to complete the processing of the event that causes the interrupt.

Some network controllers are capable of performing TCP/IP header checksum computation and validation in hardware, without taking up valuable CPU resources. To take advantage of the hardware capability feature, NetX provides options to enable or disable various software checksum computation at compilation time, as well as turning on or off checksum computation at run time. See "Chapter 5 NetX Network Drivers" for more detailed information on writing NetX network drivers.

Multihome Support

NetX supports systems connected to multiple physical devices using a single IP instance. Each physical interface is assigned to an interface control block in the IP instance. Applications wishing to use a multihome system must define the value for NX_MAX_PHSYCIAL_INTERFACES to the number of physical devices attached to the system, and rebuild NetX library. By default NX_MAX_PHYSICAL_INTERFACES is set to one, creating one interface control block in the IP instance.

The NetX application creates a single IP instance for the primary device using the nx_ip_create service. For each additional network devices, the application attaches the device to the IP instance using the nx_ip_interface_attach service.

Each network interface structure contains a subset of network information about the network interface that is contained in the IP control block, including interface IP address, subnet mask, IP MTU size, and MAC-layer address information.

Important

NetX with multihome support is backward compatible with earlier versions of NetX. Services that do not take explicit interface information default to the primary network device.

The primary interface has index zero in the IP instance list. Each subsequent device attached to the IP instance is assigned the next index.

All upper layer protocol services for which the IP instance is enabled, including TCP, UDP, ICMP, and IGMP, are available to all the attached devices.

In most cases, NetX can determine the best source address to use when transmitting a packet. The source address selection is based on the destination address. NetX services are provided to allow applications to specify a specific source address to use, in cases where the most suitable one cannot be determined by the destination address. An example would be in a multihome system, an application needs to send a packet to an IP broadcast or multicast destination addresses.

Services specifically for developing multihome applications include the following:

nx_igmp_multicast_interface_join nx_ip_driver_interface_direct_command nx_ip_interface_address_get nx_ip_interface_address_set nx_ip_interface_attach nx_ip_interface_info_get nx_ip_interface_status_check nx_ip_raw_packet_interface_send nx_udp_socket_interface_send

These services are explained in greater detail in "Chapter 4 - Description of Azure RTOS NetX Services".

Loopback Interface

The loopback interface is a special network interface without an physical link attached to. The loopback interface allows applications to communicate using the IP loopback address 127.0.0.1

To utilize a logical loopback interface, ensure the configurable option NX_DISABLE_LOOPBACK_INTERFACE is not set.

Interface Control Blocks

The number of interface control blocks in the IP instance is the number of physical interfaces (defined by NX_MAX_PHYSICAL_INTERFACES) plus the loopback interface if it is enabled. The total number of interfaces is defined in NX_MAX_IP_INTERFACES.

Protocol Layering

The TCP/IP implemented by NetX is a layered protocol, which means more complex protocols are built on top of simpler underlying protocols. In TCP/ IP, the lowest layer protocol is at the link Layer and is handled by the network driver. This level is typically targeted towards Ethernet, but it could also be fiber, serial, or virtually any physical media.

On top of the link layer is the Network layer. In TCP/IP, this is the IP, which is basically responsible for sending and receiving simple packets, in a best-effort manner, across the network. Management type protocols like ICMP and IGMP are typically also categorized as network layers, even though they rely on IP for sending and receiving.

The Transport layer rests on top of the network layer. This layer is responsible for managing the flow of data between hosts on the network. There are two types of transport services supported by NetX: UDP and TCP. UDP services provide best-effort sending and receiving of data between two hosts in a connectionless manner, while TCP provides reliable connection-oriented service between two host entities.

This layering is reflected in the actual network data packets. Each layer in TCP/IP contains a block of information called a header. This technique of surrounding data (and possibly protocol information) with a header is typically called data encapsulation. Figure 1 shows an example of NetX layering and Figure 2 shows the resulting data encapsulation for UDP data being sent.

Protocol Layering

FIGURE 1. Protocol Layering

UDP Data Encapsulation

FIGURE 2. UDP Data Encapsulation

Packet Pools

Allocating packets in a fast and deterministic manner is always a challenge in real-time networking applications. With this in mind, NetX provides the ability to create and manage multiple pools of fixed-size network packets.

Because NetX packet pools consist of fixed-size memory blocks, there are never any internal fragmentation problems. Of course, fragmentation causes behavior that is inherently nondeterministic.

In addition, the time required to allocate and free a NetX packet amounts to simple linked-list manipulation. Furthermore, packet allocation and deallocation is done at the head of the available list. This provides the fastest possible linked list processing.

Lack of flexibility is typically the main drawback of fixed-size packet pools. Determining the optimal packet payload size that also handles the worst-case incoming packet is a difficult task. NetX packets address this problem with an optional feature called packet chaining. An actual network packet can be made of one or more NetX packets linked together. In addition, the packet header maintains a pointer to the top of the packet. As additional protocols are added, this pointer is simply moved backwards and the new header is written directly in front of the data. Without the flexible packet technology, the stack would have to allocate another buffer and copy the data into a new buffer with the new header, which is processing intensive.

Since each packet payload size is fixed for a given packet pool, application data larger than the payload size requires multiple packets chained together. When filling a packet with user data, the application must use the service nx_packet_data_append. This service moves application data into a packet. In situations where a packet is not enough to hold user data, additional packets are allocated to store user data. To use packet chaining, the driver must be able to receive into or transmit from chained packets.

Each NetX packet memory pool is a public resource. NetX places no constraints on how packet pools are used.

Packet Pool Memory Area

The memory area for the packet pool is specified during creation. Like other memory areas for ThreadX and NetX objects, it can be located anywhere in the target's address space. This is an important feature because of the considerable flexibility it gives the application. For example, suppose that a communication product has a high-speed memory area for network buffers. This memory area is easily utilized by making it into a NetX packet memory pool.

Creating Packet Pools

Packet pools are created either during initialization or during runtime by application threads. There are no limits on the number of packet memory pools in a NetX application.

Packet Header NX_PACKET

By default, NetX places the packet header immediately before the packet payload area. The packet memory pool is basically a series of packets—headers followed immediately by the packet payload. The packet header (NX_PACKET) and the layout of the packet pool are pictured in Figure 3.

For network devices driver that are able to perform zero copy operations, typically the starting address of the packet payload area is programmed into the DMA logic. Certain DMA engines have alignment requirement on the payload area.

Important

The network driver to must call the nx_packet_transmit_release function when the transmission of a packet is complete. This function checks to make sure the packet is not part of a TCP output queue before it is actually placed back in the available pool. Failure to call this function can result in unpredictable behavior.

Packet Header and Packet Pool Layout

FIGURE 3. Packet Header and Packet Pool Layout

The fields of the packet header are defined as shown in the following table. Note that this table is not a comprehensive list of all the members in the NX_PACKET structure.

Packet header Purpose
nx_packet_pool_owner This field points to the packet pool that owns this particular packet. When the packet is released, it is released to this particular pool. With the pool ownership inside each packet, it is possible for a datagram to span multiple packets from multiple packet pools.
nx_packet_next This field points to the next packet within the same frame. If NULL, there are no additional packets that are part of the frame.
nx_packet_last This field points to the last packet within the same network packet. If NULL, this packet represents the entire network packet.
nx_packet_length This field contains the total number of bytes in the entire network packet, including the total of all bytes in all packets chained together by the nx_packet_next member.
nx_packet_ip_interface This field is the interface control block which is assigned to the packet when it is received by the interface driver, and by NetX for outgoing packets. An interface control block describes the interface e.g. network address, MAC address, IP address and interface status such as link enabled and physical mapping required.
nx_packet_data_start This field points to the start of the physical payload area of this packet. It does not have to be immediately following the NX_PACKET header, but that is the default for the nx_packet_pool_create service.
nx_packet_data_end This field points to the end of the physical payload area of this packet. The difference between this field and the nx_packet_data_start field represents the payload size.
nx_packet_prepend_ptr This field points to the location of where packet data, either protocol header or actual data, is added in front of the existing packet data (if any) in the packet payload area. It must be greater than or equal to the nx_packet_data_start pointer location and less than or equal to the nx_packet_append_ptr pointer. For performance reasons, NetX assumes that when the packet is passed into NetX services for transmission, the prepend pointer points to long word aligned address.
nx_packet_append_ptr This field points to the end of the data currently in the packet payload area. It must be in between the memory location pointed to by nx_packet_prepend_ptr and nx_packet_data_end. The difference between this field and the nx_packet_prepend_ptr field represents the amount of data in this packet.
nx_packet_fragment_next This field is used to hold fragmented packets until the entire packet can be re-assembled.
nx_packet_pad This fields defines the length of padding in 4- byte words to achieve the desired alignment requirement. This field is removed if NX_PACKET_HEADER_PAD is not defined.

Packet Header Offsets

Packet header size is defined to allow enough room to accommodate the size of the header. The nx_packet_allocate service is used to allocate a packet and adjusts the prepend pointer in the packet according to the type of packet specified. The packet type tells NetX the offset required for inserting the protocol header (such as UDP, TCP, or ICMP) in front of the protocol data.

The following types are defined in NetX to take into account the IP header and physical layer (Ethernet) header in the packet. In the latter case, it is assumed to be 16 bytes taking the required 4-byte alignment into consideration. IP packets are still defined in NetX for applications to allocate packets for IP networks. The following table shows symbols defined:

Packet Type Value
NX_IP_PACKET 0x24
NX_UDP_PACKET 0x2c
NX_TCP_PACKET 0x38

Pool Capacity

The number of packets in a packet pool is a function of the payload size and the total number of bytes in the memory area supplied to the packet pool create service. The capacity of the pool is calculated by dividing the packet size (including the size of the NX_PACKET header, the payload size, and proper alignment) into the total number of bytes in the supplied memory area.

Thread Suspension

Application threads can suspend while waiting for a packet from an empty pool. When a packet is returned to the pool, the suspended thread is given this packet and resumed.

If multiple threads are suspended on the same packet pool, they are resumed in the order they were suspended (FIFO).

Pool Statistics and Errors

If enabled, the NetX packet management software Errors keeps track of several statistics and errors that may be useful to the application. The following statistics and error reports are maintained for packet pools:

  • Total Packets in Pool
  • Free Packets in Pool
  • Pool Empty Allocation Requests
  • Pool Empty Allocation Suspensions
  • Invalid Packet Releases

All of these statistics and error reports, except for total and free packet count in pool, are built into NetX library unless NX_DISABLE_PACKET_INFO is defined. This data is available to the application with the nx_packet_pool_info_get service.

Packet Pool Control Block NX_PACKET_POOL

The characteristics of each packet memory pool are found in its control block. It contains useful information such as the linked list of free packets, the number of free packets, and the payload size for packets in this pool. This structure is defined in the nx_api.h file.

Packet pool control blocks can be located anywhere in memory, but it is most common to make the control block a global structure by defining it outside the scope of any function.

IP Protocol

The Internet Protocol (IP) component of NetX is responsible for sending and receiving IP packets on the Internet. In NetX, it is the component ultimately responsible for sending and receiving TCP, UDP, ICMP, and IGMP messages, utilizing the underlying network driver.

NetX supports IP protocol (RFC 791)

IP Addresses

Each host on the Internet has a unique 32-bit identifier called an IP address. There are five classes of IP addresses as described in Figure 4. The ranges of the five IP address classes are as follows:

Class Range
A 0.0.0.0 to 127.255.255.255
B 128.0.0.0 to 191.255.255.255
C 192.0.0.0 to 223.255.255.255
D 224.0.0.0 to 239.255.255.255
E 240.0.0.0 to 247.255.255.255

7 bits 24 bits

IP Address Structure

FIGURE 4. IP Address Structure

There are also three types of address specifications: unicast, broadcast, and multicast. Unicast addresses are those IP addresses that identify a specific host on the Internet. Unicast addresses can be either a source or a destination IP address. A broadcast address identifies all hosts on a specific network or sub-network and can only be used as destination addresses. Broadcast addresses are specified by having the host ID portion of the address set to ones. Multicast addresses (Class D) specify a dynamic group of hosts on the Internet. Members of the multicast group may join and leave whenever they wish.

Important

Only connectionless protocols like UDP over IP can utilize broadcast and the limited broadcast capability of the multicast group.

Important

The macro IP_ADDRESS is defined in nx_api.h. It allows easy specification of IP addresses using commas instead of a periods. For example, IP_ADDRESS(128,0,0,0) specifies the first class B address shown in Figure 4.

IP Gateway Address

Network gateways assist hosts on their networks to relay packets destined to destinations outside the local domain. Each node has some knowledge of which next hop to send to, either the destination one of its neighbors, or through a pre-programmed static routing table. However if these approaches fail, the node should forward the packet to its default gateway which has more information on how to route the packet to its destination. Note that the default gateway must be directly accessible through one of the physical interfaces attached to the IP instance. The application calls nx_ip_gateway_address_set to configure IP default gateway address.

IP Header

For any IP packet to be sent on the Internet, it must have an IP header. When higher-level protocols (UDP, TCP, ICMP, or IGMP) call the IP component to send a packet, the IP transmit module places an IP header in front of the data. Conversely, when IP packets are received from the network, the IP component removes the IP header from the packet before delivery to the higher-level protocols. Figure 5 shows the format of the IP header.

IP Header Format

FIGURE 5. IP Header Format

Important

All headers in the TCP/IP implementation are expected to be in big endian format. In this format, the most significant byte of the word resides at the lowest byte address. For example, the 4-bit version and the 4-bit header length of the IP header must be located on the first byte of the header.

The fields of the IP header are defined as follows:

IP Header Field Purpose

4-bit version This field contains the version of IP this header represents. For IP version 4, which is what NetX supports, the value of this field is 4.

4-bit header length This field specifies the number of 32-bit words in the IP header. If no option words are present, the value for this field is 5.

8-bit type of service (TOS) This field specifies the type of service requested for this IP packet. Valid requests are as follows:

TOS Request Value
Normal 0x00
Minimum Delay 0x10
Maximum Data 0x08
Maximum Reliability 0x04
Minimum Cost 0x02

16-bit total length This field contains the total length of the IP datagram in bytes, including the IP header. An IP datagram is the basic unit of information found on a TCP/IP Internet. It contains a destination and source address in addition to data. Because it is a 16-bit field, the maximum size of an IP datagram is 65,535 bytes.

16-bit identification The field is a number used to uniquely identify each IP datagram sent from a host. This number is typically incremented after an IP datagram is sent. It is especially useful in assembling received IP packet fragments.

3-bit flags This field contains IP fragmentation information. Bit 14 is the "don't fragment" bit. If this bit is set, the outgoing IP datagram will not be fragmented. Bit 13 is the "more fragments" bit. If this bit is set, there are more fragments. If this bit is clear, this is the last fragment of the IP packet.

IP Header Field Purpose

13-bit fragment offset This field contains the upper 13-bits of the fragment offset. Because of this, fragment offsets are only allowed on 8-byte boundaries. The first fragment of a fragmented IP datagram will have the “more fragments” bit set and have an offset of 0.

8-bit time to live (TTL) This field contains the number of routers this datagram can pass, which limits the lifetime of the datagram.

8-bit protocol This field specifies which protocol is using the IP datagram. The following is a list of valid protocols and their values:

Protocol Value
ICMP 0x01
IGMP 0x02
TCP 0X06
UDP 0X11

16-bit checksum This field contains the 16-bit checksum that covers the IP header only. There are additional checksums in the higher level protocols that cover the IP payload.

32-bit source IP address This field contains the IP address of the sender and is always a host address.

32-bit destination IP address This field contains the IP address of the receiver or receivers if the address is a broadcast or multicast address.

Creating IP Instances

IP instances are created either during initialization or during runtime by application threads. The initial IP address, network mask, default packet pool, media driver, and memory and priority of the internal IP thread are defined by the nx_ip_create service. If the application initializes the IP instance with its IP address set to an invalid address(0.0.0.0), it is assumed that the interface address is going to resolved by manual configuration later, via RARP, or through DHCP or similar protocols.

For systems with multiple network interfaces, the primary interface is designated when calling nx_ip_create. Each additional interface can be attached to the same IP instance by calling nx_ip_interface_attach. This service stores information about the network interface (such as IP address, network mask) in the interface control block, and associates the driver instance with the interface control block in the IP instance. As the driver receives a data packet, it needs to store the interface information in the NX_PACKET structure before forwarding it to the IP receive logic. Note an IP instance must already be created before attaching any interfaces.

IP Send

The IP send processing in NetX is very streamlined.

The prepend pointer in the packet is moved backwards to accommodate the IP header. The IP header is completed (with all the options specified by the calling protocol layer), the IP checksum is computed in-line, and the packet is dispatched to the associated network driver. In addition, outgoing fragmentation is also coordinated from within the IP send processing.

For IP, NetX initiates ARP requests if physical mapping is needed for the destination IP address.

Important

For IP connectivity, packets that require IP address resolution (i.e., physical mapping) are enqueued on the ARP queue until the number of packets queued exceeds the ARP queue depth (defined by the symbol NX_ARP_MAX_QUEUE_DEPTH). If the queue depth is reached, NetX will remove the oldest packet on the queue and continue waiting for address resolution for the remaining packets enqueued. On the other hand, if an ARP entry is not resolved, the pending packets on the ARP entry are released upon ARP entry timeout.

For systems with multiple network interfaces, NetX chooses an interface based on the destination IP address. The following procedure applies to the selection process:

  1. If a destination address is IP broadcast or multicast, and if a valid outgoing interface is specified, use that interface. Otherwise, the first physical interface is used.

  2. If the destination address is found in the static routing table, the interface associated with the gateway is used.

  3. If the destination is on-link, the on-link interface is used.

  4. If the destination address is a loopback address 127.0.0.1, the loopback interface is used.

  5. If the default gateway is properly configured, use the interface associated with the default gateway to transmit the packet.

  6. The output packet is dropped if all the above fails.

IP Receive

The IP receive processing is either called from the network driver or the internal IP thread (for processing packets on the deferred received packet queue). The IP receive processing examines the protocol field and attempts to dispatch the packet to the proper protocol component. Before the packet is actually dispatched, the IP header is removed by advancing the prepend pointer past the IP header.

IP receive processing also detects fragmented IP packets and performs the necessary steps to reassemble them if fragmentation is enabled. If fragmentation is needed but not enabled, the packet is dropped.

NetX determines the appropriate network interface based on the interface specified in the packet. If the packet interface is NULL, NetX defaults to the primary interface. This is done to guarantee compatibility with legacy NetX Ethernet drivers.

Raw IP Send

A raw IP packet is an IP frame that contains upper layer protocol payload not directly supported (and processed) by NetX. A raw packet allows developers to define their own IP-based applications. An application may send raw IP packets directly using the nx_ip_raw_packet_send service if raw IP packet processing has been enabled with the nx_ip_raw_packet_enabled service. If the destination address is a multicast or broadcast address, however, NetX defaults to the first (primary) interface. Therefore, to send such packets out on secondary interfaces, the application must use the nx_ip_raw_packet_interface_send service to specify the source address to use for the outgoing packet.

Raw IP Receive

If raw IP packet processing is enabled, the application may receive raw IP packets through the nx_ip_raw_packet_receive service. All incoming packets are processed according to the protocol specified in the IP header. If the protocol specifies UDP, TCP, IGMP or ICMP, NetX will process the packet using the appropriate handler for the packet protocol type. If the protocol is not one of these protocols, and raw IP receive is enabled, the incoming packet will be put into the raw packet queue waiting for the application to receive it via the nx_ip_raw_packet_receive service. In addition, application threads may suspend with an optional timeout while waiting for a raw IP packet.

Default Packet Pool

Each IP instance is given a default packet pool during creation. This packet pool is used to allocate packets for ARP, RARP, ICMP, IGMP, various TCP control packets (such as SYN, ACK). If the default packet pool is empty when NetX needs to allocate a packet, NetX may have to abort the particular operation, and will return an error message if possible.

IP Helper Thread

Each IP instance has a helper thread. This thread is responsible for handling all deferred packet processing and all periodic processing. The IP helper thread is created in nx_ip_create. This is where the thread is given its stack and priority. Note that the first processing in the IP helper thread is to finish the network driver initialization associated with the IP create service. After the network driver initialization is complete, the helper thread starts an endless loop to process packet and periodic requests.

Important

If unexplained behavior is seen within the IP helper thread, increasing its stack size during the IP create service is the first debugging step. If the stack is too small, the IP helper thread could possibly be overwriting memory, which may cause unusual problems.

Thread Suspension

Application threads can suspend while attempting to receive raw IP packets. After a raw packet is received, the new packet is given to the first thread suspended and that thread is resumed. NetX services for receiving packets all have an optional suspension timeout. When a packet is received or the timeout expires, the application thread is resumed with the appropriate completion status.

IP Statistics and Errors

If enabled, the NetX keeps track of several statistics and errors that may be useful to the application. The following statistics and error reports are maintained for each IP instance:

  • Total IP Packets Sent
  • Total IP Bytes Sent
  • Total IP Packets Received
  • Total IP Bytes Received
  • Total IP Invalid Packets
  • Total IP Receive Packets Dropped
  • Total IP Receive Checksum Errors
  • Total IP Send Packets Dropped
  • Total IP Fragments Sent
  • Total IP Fragments Received

All of these statistics and error reports are available to the application with the nx_ip_info_get service.

IP Control Block NX_IP

The characteristics of each IP instance are found in its control block. It contains useful information such as the IP addresses and network masks of each network device, and a table of neighbor IP and physical hardware address mapping. This structure is defined in the nx_api.h IP instance control blocks can be located anywhere in memory, but it is most common to make the control block a global structure by defining it outside the scope of any function.

Static IP Routing

The static routing feature allows an application to specify an IP network and next hop address for specific out of network destination IP addresses. If static routing is enabled, NetX searches through the static routing table for an entry matching the destination address of the packet to send. If no match is found, NetX searches through the list of physical interfaces and chooses a source IP address and next hop address based on the destination IP address and the network mask. If the destination does not match any of the IP addresses of the network drivers attached to the IP instance, NetX chooses an interface that is directly connected to the default gateway, and uses the IP address of the interface as source address, and the default gateway as the next hop.

Entries can be added and removed from the static routing table using the nx_ip_static_route_add and nx_ip_static_route_delete services, respectively. To use static routing, the host application must enable this feature by defining NX_ENABLE_IP_STATIC_ROUTING.

Important

When adding an entry to the static routing table, NetX checks for a matching entry for the specified destination address already in the table. If one exists, it gives preference to the entry with the smaller network (longer prefix) in the network mask.

IP Fragmentation

The network device may have limits on the size of outgoing packets. This limit is called the maximum transmission unit (MTU). IP MTU is the largest IP frame size a link layer driver is able to transmit without fragmenting the IP packet. During a device driver initialization phase, the driver module must configure its IP MTU size via the service nx_ip_interface_mtu_set.

Although not recommended, the application may generate datagrams larger than the underlying IP MTU supported by the device. Before transmitting such IP datagram, the IP layer must fragment these packets. On receiving fragmented IP frames, the receiving end must store all fragmented IP frames with the same fragmentation ID, and reassemble them in order. If the IP receive logic is unable to collect all the fragments to restore the original IP frame in time, all the fragments are released. It is up to the upper layer protocol to detect such packet loss and recover from it.

In order to support IP fragmentation and reassembly operation, the system designer must enable the IP fragmentation feature in NetX using the nx_ip_fragment_enable service. If this feature is not enabled, incoming fragmented IP packets are discarded, as well as packets that exceed the network driver's MTU.

Important

The IP Fragmentation logic can be removed completely by defining NX_DISABLE_FRAGMENTATION when building theNetX library. Doing so helps reduce the code size of NetX.

Address Resolution Protocol (ARP) in IP

The Address Resolution Protocol (ARP) is responsible for dynamically mapping 32-bit IP addresses to those of the underlying physical media (RFC 826). Ethernet is the most typical physical media, and it supports 48-bit addresses. The need for ARP is determined by the network driver supplied to the nx_ip_create service. If physical mapping is required, the network driver must set the flag nx_interface_address_mapping_needed in the interface strcuture.

ARP Enable

For ARP to function properly, it must first be enabled by the application with the nx_arp_enable service. This service sets up various data structures for ARP processing, including the creation of an ARP cache area from the memory supplied to the ARP enable service.

ARP Cache

The ARP cache can be viewed as an array of internal ARP mapping data structures. Each internal structure is capable of maintaining the relationship between an IP address and a physical hardware address. In addition, each data structure has link pointers so it can be part of multiple linked lists.

Application can look up an IP address from the ARP cache by supplying hardware MAC address using the service nx_arp_ip_address_find if the mapping exists in the ARP table. Similarly, the service nx_arp_hardware_address_find returns the MAC address for a given IP address.

ARP Dynamic Entries

By default, the ARP enable service places all entries in the ARP cache on the list of available dynamic ARP entries. A dynamic ARP entry is allocated from this list by NetX when a send request to an unmapped IP address is detected. After allocation, the ARP entry is set up and an ARP request is sent to the physical media.

A dynamic entry can also be created by the service nx_arp_dynamic_entry_set.

Important

If all dynamic ARP entries are in use, the least recently used ARP entry is replaced with a new mapping.

ARP Static Entries

The application can also set up static ARP mapping by using the nx_arp_static_entry_create service. This service allocates an ARP entry from the dynamic ARP entry list and places it on the static list with the mapping information supplied by the application. Static ARP entries are not subject to reuse or aging. The application can delete a static entry by using the service nx_arp_static_entry_delete. To remove all static entries in the ARP table, the application may use the service nx_arp_static_entries_delete.

Automatic ARP Entry

NetX records the peer's IP/MAC mapping after the peer responses to the ARP request. NetX also implements the automatic ARP entry feature where it records peer IP/MAC address mapping based on unsolicited ARP requests from the network. This feature allows the ARP table to be populated with peer information, reducing the delay needed to go through the ARP request/response cycle. However the downside with enabling automatic ARP is that the ARP table tend to fill up quickly on a busy network with many nodes on the local link, which would eventually lead to ARP entry replacement.

This feature is enabled by default. To disable it, the NetX library must be compiled with the symbol NX_DISABLE_ARP_AUTO_ENTRY defined.

ARP Messages

As mentioned previously, an ARP request message is sent when the IP task detects that mapping is needed for an IP address. ARP requests are sent periodically (every NX_ARP_UPDATE_RATE seconds) until a corresponding ARP response is received. A total of NX_ARP_MAXIMUM_RETRIES ARP requests are made before the ARP attempt is abandoned. When an ARP response is received, the associated physical address information is stored in the ARP entry that is in the cache.

For multihome systems, NetX determines which interface to send the ARP requests and responses based on destination address specified.

Important

Outgoing IP packets are queued while NetX waits for the ARP response. The number of outgoing IP packets queued is defined by the constant NX_ARP_MAX_QUEUE_DEPTH.

NetX also responds to ARP requests from other nodes on the local IP network. When an external ARP request is made that matches the current IP address of the interface that receives the ARP request, NetX builds an ARP response message that contains the current physical address.

The formats of Ethernet ARP requests and responses are shown in Figure 6 and are described below:

Request/Response Field Purpose
Ethernet Destination Address This 6-byte field contains the destination address for the ARP response and is a broadcast (all ones) for ARP requests. This field is setup by the network driver.
Ethernet Source Address This 6-byte field contains the address of the sender of the ARP request or response and is set up by the network driver.
Frame Type This 2-byte field contains the type of Ethernet frame present and, for ARP requests and responses, this is equal to 0x0806. This is the last field the network driver is responsible for setting up.
Hardware Type This 2-byte field contains the hardware type, which is 0x0001 for Ethernet.
Protocol Type This 2-byte field contains the protocol type, which is 0x0800 for IP addresses.
Hardware Size This 1-byte field contains the hardware address size, which is 6 for Ethernet addresses.

ARP Packet Format

FIGURE 6. ARP Packet Format

Request/Response Field Purpose
Protocol Size This 1-byte field contains the IP address size, which is 4 for IP addresses.
Operation Code This 2-byte field contains the operation for this ARP packet. An ARP request is specified with the value of 0x0001, while an ARP response is represented by a value of 0x0002.
Sender Ethernet Address This 6-byte field contains the sender's Ethernet address.
Sender IP Address This 4-byte field contains the sender's IP address.
Target Ethernet Address This 6-byte field contains the target's Ethernet address.
Target IP Address This 4-byte field contains the target's IP address.

Important

ARP requests and responses are Ethernet-level packets. All other TCP/IP packets are encapsulated by an IP packet header.

Important

All ARP messages in the TCP/IP implementation are expected to be in big endian format. In this format, the most significant byte of the word resides at the lowest byte address.

ARP Aging

NetX supports automatic dynamic ARP entry invalidation. NX_ARP_EXPIRATION_RATEspecifies the number of seconds an established IP address to physical mapping stays valid. After expiration, the ARP entry is removed from the ARP cache. The next attempt to send to the corresponding IP address will result in a new ARP request. Setting NX_ARP_EXPIRATION_RATE to zero disables ARP aging, which is the default configuration.

ARP Defend

When an ARP request or ARP response packet is received and the sender has the same IP address, which conflicts with the IP address of this node, NetX sends an ARP request for that address as a defense. If the conflict ARP packet is received more than once in 10 seconds, NetX does not send more defend packets. The default interval 10 seconds can be redefined by NX_ARP_DEFEND_INTERVAL. This behavior follows the policy specified in 2.4(c) of RFC5227. Since Windows XP ignores ARP announcement as a response for its ARP probe, user can define NX_ARP_DEFEND_BY_REPLYto send ARP response as additional defence.

ARP Statistics and Errors

If enabled, the NetX ARP software keeps track of several statistics and errors that may be useful to the application. The following statistics and error reports are maintained for each IP's ARP processing:

  • Total ARP Requests Sent
  • Total ARP Requests Received
  • Total ARP Responses Sent
  • Total ARP Responses Received
  • Total ARP Dynamic Entries
  • Total ARP Static Entries
  • Total ARP Aged Entries
  • Total ARP Invalid Messages

All these statistics and error reports are available to the application with the nx_arp_info_get service.

Reverse Address Resolution Protocol (RARP) in IP

The Reverse Address Resolution Protocol (RARP) is the protocol for requesting network assignment of the host's 32-bit IP addresses (RFC 903). This is done through an RARP request and continues periodically until a network member assigns an IP address to the host network interface in an RARP response. The application creates an IP instance by the service nx_ip_create with a zero IP address. If RARP is enabled by the application, it can use the RARP protocol to request an IP address from the network server accessible through the interface that has a zero IP address.

RARP Enable

To use RARP, the application must create the IP instance with an IP address of zero, then enable RARP using the service nx_rarp_enable. For multihome systems, at least one network device associated with the IP instance must have an IP address of zero. The RARP processing periodically sends RARP request messages for the NetX system requiring an IP address until a valid RARP reply with the network designated IP address is received. At this point, RARP processing is complete.

After RARP has been enabled, it is disabled automatically after all interface addresses are resolved. The application may force RARP to terminate by using the service nx_rarp_disable.

RARP Request

The format of an RARP request packet is almost identical to the ARP packet shown in Figure 6 in the topic ARP Messages.The only difference is the frame type field is 0x8035 and the Operation Code field is 3, designating an RARP request. As mentioned previously, RARP requests will be sent periodically (every NX_RARP_UPDATE_RATE seconds) until a RARP reply with the network assigned IP address is received.

Important

All RARP messages in the TCP/IP implementation are expected to be in big endian format. In this format, the most significant byte of the word resides at the lowest byte address.

RARP Reply

RARP reply messages are received from the network and contain the network assigned IP address for this host. The format of an RARP reply packet is almost identical to the ARP packet shown in Figure 6. The only difference is the frame type field is 0x8035 and the Operation Code field is 4, which designates an RARP reply. After received, the IP address is setup in the IP instance, the periodic RARP request is disabled, and the IP instance is now ready for normal network operation.

For multihome hosts, the IP address is applied to the requesting network interface. If there are other network interfaces still requesting an IP address assignment, the periodic RARP service continues until all interface IP address requests are resolved.

Important

The application should not use the IP instance until the RARP processing is complete. The nx_ip_status_check may be used by applications to wait for the RARP completion. For multihome systems, the application should not use the requesting interface until the RARP processing is complete on that interface. Status of the IP address on the secondary device can be checked with the nx_ip_interface_status_check service.

RARP Statistics and Errors

If enabled, the NetX RARP software keeps track of several statistics and errors that may be useful to the application. The following statistics and error reports are maintained for each IP's RARP processing:

  • Total RARP Requests Sent
  • Total RARP Responses Received
  • Total RARP Invalid Messages

All these statistics and error reports are available to the application with the nx_rarp_info_get service.

Internet Control Message Protocol (ICMP)

Internet Control Message Protocol for IP (ICMP) is limited to passing error and control information between IP network members.

Like most other application layer (e.g., TCP/IP) messages, ICMP messages are encapsulated by an IP header with the ICMP protocol designation.

ICMP Statistics and Errors

If enabled, NetX keeps track of several ICMP statistics and errors that may be useful to the application. The following statistics and error reports are maintained for each IP's ICMP processing:

  • Total ICMP Pings Sent
  • Total ICMP Ping Timeouts
  • Total ICMP Ping Threads Suspended
  • Total ICMP Ping Responses Received
  • Total ICMP Checksum Errors
  • Total ICMP Unhandled Messages

All these statistics and error reports are available to the application with the nx_icmp_info_get service.

ICMP Enable

Before ICMP messages can be processed by NetX, the application must call the nx_icmp_enable service to enable ICMP processing. After this is done, the application can issue ping requests and field incoming ping packets.

ICMP Echo Request

An echo request is one type of ICMP message that is typically used to check for the existence of a specific node on the network, as identified by its host IP address. The popular ping command is implemented using ICMP echo request/echo reply messages. If the specific host is present, its network stack processes the ping request and responses with a ping response. Figure 7 details the ICMP ping message format.

ICMP Ping Message

FIGURE 7. ICMP Ping Message

Important

All ICMP messages in the TCP/IP implementation are expected to be in big endian format. In this format, the most significant byte of the word resides at the lowest byte address.

The following table describes the ICMP header format:

Header Field Purpose
Type This field specifies the ICMP message (bits 31- 24). The most common are: 0 Echo Reply 8 Echo Request
Code This field is context specific on the type field (bits 23-16). For an echo request or reply the code is set to zero.
Checksum This field contains the 16-bit checksum of the one's complement sum of the ICMP message including the entire the ICMP header starting with the Type field. Before generating the checksum, the checksum field is cleared.
Identification This field contains an ID value identifying the host; a host should use the ID extracted from an ECHO request in the ECHO REPLY (bits 31-16).
Sequence number This field contains an ID value; a host should use the ID extracted from an ECHO request in the ECHO REPLY (bits 31-16). Unlike the identifier field, this value will change in a subsequent Echo request from the same host (bits 15-0).

ICMP Echo Response

A ping response is another type of ICMP message that is generated internally by the ICMP component in response to an external ping request. In addition to acknowledgement, the ping response also contains a copy of the user data supplied in the ping request.

Internet Group Management Protocol (IGMP)

The Internet Group Management Protocol (IGMP) provides a device to communicate with its neighbors and its routers that it intends to receive, or join, an IP multicast group (RFC 1112 and RFC 2236). A multicast group is basically a dynamic collection of network members and is represented by a Class D IP address. Members of the multicast group may leave at any time, and new members may join at any time. The coordination involved in joining and leaving the group is the responsibility of IGMP.

IGMP Enable

Before any multicasting activity can take place in NetX, the application must call the nx_igmp_enable service. This service performs basic IGMP initialization in preparation for multicast requests.

Multicast IP Addressing

As mentioned previously, multicast addresses are actually Class D IP addresses as shown in Figure 4 on page 58. The lower 28-bits of the Class D address correspond to the multicast group ID. There are a series of pre-defined multicast addresses. However, the all hosts address (244.0.0.1) is particularly important to IGMP processing. The all hosts address is used by routers to query all multicast members to report on which multicast groups they belong to.

Physical Address Mapping in IP

Class D multicast addresses map directly to physical Ethernet addresses ranging from 01.00.5e.00.00.00 through 01.00.5e.7f.ff.ff. The lower 23 bits of the IP multicast address map directly to the lower 23 bits of the Ethernet address.

Multicast Group Join

Applications that need to join a particular multicast group may do so by calling the nx_igmp_multicast_join service. This service keeps track of the number of requests to join this multicast group. If this is the first application request to join the multicast group, an IGMP report is sent out on the primary network indicating this host's intention to join the group. Next, the network driver is called to set up for listening for packets with the Ethernet address for this multicast group.

In a multihome system, if the multicast group is accessible via a specific interface, application shall use the service nx_igmp_multicast_interface_join instead of nx_igmp_multicast_join, which is limited to multicast groups on the primary network.

Multicast Group Leave

Applications that need to leave a previously joined multicast group may do so by calling the nx_igmp_multicast_leave service. This service reduces the internal count associated with how many times the group was joined. If there are no outstanding join requests for a group, the network driver is called to disable listening for packets with this multicast group's Ethernet address

Multicast Loopback

An application may wish to receive multicast traffic originated from one of the sources on the same node. This requires the IP multicast component to have loopback enabled by using the service nx_igmp_loopback_enable.

IGMP Report Message

When the application joins a multicast group, an IGMP report message is sent via the network to indicate the host's intention to join a particular multicast group. The format of the IGMP report message is shown in Figure 8. The multicast group address is used for both the group message in the IGMP report message and the destination IP address.

IGMP Report Message

FIGURE 8. IGMP Report Message

In the figure above (Figure 8), the IGMP header contains a version/type field, maximum response time, a checksum field, and a multicast group address field. For IGMPv1 messages, the Maximum Response Time field is always set to zero, as this is not part of the IGMPv1 protocol. The Maximum Response Time field is set when the host receives a Query type IGMP message and cleared when a host receives another host's Report type message as defined by the IGMPv2 protocol.

The following describes the IGMP header format:

Header Field Purpose
Version This field specifies the IGMP version (bits 31- 28).
Type This field specifies the type of IGMP message (bits 27 -24).
Maximum Response Time Not used in IGMPv1. In IGMPv2 this field serves as the maximum response time.
Checksum This field contains the 16-bit checksum of the one's complement sum of the IGMP message starting with the IGMP version (bits 0-15)
Group Address 32-bit class D group IP address

IGMP report messages are also sent in response to IGMP query messages sent by a multicast router. Multicast routers periodically send query messages out to see which hosts still require group membership. Query messages have the same format as the IGMP Report message shown in Figure 8. The only differences are the IGMP type is equal to 1 and the group address field is set to 0. IGMP Query messages are sent to the all hosts IP address by the multicast router. A host that still wishes to maintain group membership responds by sending another IGMP Report message.

Important

All messages in the TCP/IP implementation are expected to be in big endian format. In this format, the most significant byte of the word resides at the lowest byte address.

IGMP Statistics and Errors

If enabled, the NetX IGMP software keeps track of several statistics and errors that may be useful to the application. The following statistics and error reports are maintained for each IP's IGMP processing:

  • Total IGMP Reports Sent
  • Total IGMP Queries Received
  • Total IGMP Checksum Errors
  • Total IGMP Current Groups Joined

All these statistics and error reports are available to the application with the nx_igmp_info_get service.

User Datagram Protocol (UDP)

The User Datagram Protocol (UDP) provides the simplest form of data transfer between network members (RFC 768). UDP data packets are sent from one network member to another in a best effort fashion; i.e., there is no built-in mechanism for acknowledgement by the packet recipient. In addition, sending a UDP packet does not require any connection to be established in advance. Because of this, UDP packet transmission is very efficient.

UDP Header

UDP places a simple packet header in front of the application's data on transmission, and removes a similar UDP header from the packet on reception before delivering a received UDP packet to the application. UDP utilizes the IP protocol for sending and receiving packets, which means there is an IP header in front of the UDP header when the packet is on the network. Figure 9 shows the format of the UDP header.

UDP Header

FIGURE 9. UDP Header

Important

All headers in the UDP/IP implementation are expected to be in big endian format. In this format, the most significant byte of the word resides at the lowest byte address.

The following describes the UDP header format:

Header Field Purpose
16-bit source port number This field contains the port on which the UDP packet is being sent from. Valid UDP ports range from 1 through 0xFFFF.
16-bit destination port number This field contains the UDP port to which the packet is being sent to. Valid UDP ports range from 1 through 0xFFFF.
16-bit UDP length This field contains the number of bytes in the UDP packet, including the size of the UDP header.
16-bit UDP checksum This field contains the 16-bit checksum for the packet, including the UDP header, the packet data area, and the pseudo IP header.

UDP Enable

Before UDP packet transmission is possible, the application must first enable UDP by calling the nx_udp_enable service. After enabled, the application is free to send and receive UDP packets.

UDP Socket Create

UDP sockets are created either during initialization or during runtime by application threads. The initial type of service, time to live, and receive queue depth are defined by the nx_udp_socket_create service. There are no limits on the number of UDP sockets in an application.

UDP Checksum

UDP specifies a one's complement 16-bit checksum that covers the IP pseudo header (consisting of the source IP address, destination IP address, and the protocol/length IP word), the UDP header, and the UDP packet data. If the calculated UDP checksum is 0, it is stored as all ones (0xFFFF). If the sending socket has the UDP checksum logic disabled, a zero is placed in the UDP checksum field to indicate the checksum was not calculated. If the UDP checksum does not match the computed checksum by the receiver, the UDP packet is simply discarded.

On the IP network, UDP checksum is optional. NetX allows an application to enable or disable UDP checksum calculation on a per-socket basis. By default, the UDP socket checksum logic is enabled. The application can disable checksum logic for a particular UDP socket by calling the nx_udp_socket_checksum_disable service.

Certain Ethernet controllers are able to generate the UDP checksum on the fly. If the system is able to use hardware checksum computation feature, the NetX library can be built without the checksum logic. To disable UDP software checksum, the NetX library must be built with the following symbols defined: NX_DISABLE_UDP_TX_CHECKSUM and NX_DISABLE_UDP_RX_CHECKSUM (described in Chapter 2). The configuration options remove UDP checksum logic from NetX entirely, while calling the nx_udp_socket_checksum_disable* service allows the application to disable IP UDP checksum processing on a per socket basis.

UDP Ports and Binding

A UDP port is a logical end point in the UDP protocol. There are 65,535 valid ports in the UDP component of NetX, ranging from 1 through 0xFFFF. To send or receive UDP data, the application must first create a UDP socket, then bind it to a desired port. After binding a UDP socket to a port, the application may send and receive data on that socket.

UDP Fast Path™

The UDP Fast Path™ is the name for a low packet overhead path through the NetX UDP implementation. Sending a UDP packet requires just a few function calls: nx_udp_socket_send, nx_ip_packet_send, and the eventual call to the network driver. nx_udp_socket_send is available in NetX for existing NetX applications and is only applicable for IP packets. The preferred method, however, is to use nx_udp_socket_send service discussed below. On UDP packet reception, the UDP packet is either placed on the appropriate UDP socket receive queue or delivered to a suspended application thread in a single function call from the network driver's receive interrupt processing. This highly optimized logic for sending and receiving UDP packets is the essence of UDP Fast Path technology.

UDP Packet Send

Sending UDP data over IP networks is easily accomplished by calling the nx_udp_socket_send function. The caller must set the IP version in the IP address field. NetX will determine the best source address for transmitted UDP packets based on the destination IP address. This service places a UDP header in front of the packet data and sends it out onto the network using an internal IP send routine. There is no thread suspension on sending UDP packets because all UDP packet transmissions are processed immediately.

For multicast or broadcast destinations, the application should specify the source IP address to use if the NetX device has multiple IP addresses to choose from. This can be done with the services nx_udp_socket_interface_send.

Important

If nx_udp_socket_send is used for transmitting multicast or broadcast packets, the IP address of the first interface is used as source address.

Important

If UDP checksum logic is enabled for this socket, the checksum operation is performed in the context of the calling thread, without blocking access to the UDP or IP data structures.

Note

The UDP payload data residing in the NX_PACKET structure should reside on a long-word boundary. The application needs to leave sufficient space between the prepend pointer and the data start pointer for NetX to place the UDP, IP, and physical media headers.

UDP Packet Receive

Application threads may receive UDP packets from a particular socket by calling nx_udp_socket_receive. The socket receive function delivers the oldest packet on the socket's receive queue. If there are no packets on the receive queue, the calling thread can suspend (with an optional timeout) until a packet arrives.

The UDP receive packet processing (usually called from the network driver's receive interrupt handler) is responsible for either placing the packet on the UDP socket's receive queue or delivering it to the first suspended thread waiting for a packet. If the packet is queued, the receive processing also checks the maximum receive queue depth associated with the socket. If this newly queued packet exceeds the queue depth, the oldest packet in the queue is discarded.

UDP Receive Notify

If the application thread needs to process received data from more than one socket, the nx_udp_socket_receive_notify function should be used. This function registers a receive packet callback function for the socket. Whenever a packet is received on the socket, the callback function is executed.

The contents of the callback function is application-specific. However, it would most likely contain logic to inform the processing thread that a packet is now available on the corresponding socket.

Peer Address and Port

On receiving a UDP packet, application may find the sender's IP address and port number by using the service nx_udp_packet_info_extract. On successful return, this service provides information on the sender's IP address, sender's port number, and the local interface through which the packet was received.

Thread Suspension

As mentioned previously, application threads can suspend while attempting to receive a UDP packet on a particular UDP port. After a packet is received on that port, it is given to the first thread suspended and that thread is then resumed. An optional timeout is available when suspending on a UDP receive packet, a feature available for most NetX services.

UDP Socket Statistics and Errors

If enabled, the NetX UDP socket software keeps track of several statistics and errors that may be useful to the application. The following statistics and error reports are maintained for each IP/UDP instance:

  • Total UDP Packets Sent
  • Total UDP Bytes Sent
  • Total UDP Packets Received
  • Total UDP Bytes Received
  • Total UDP Invalid Packets
  • Total UDP Receive Packets Dropped
  • Total UDP Receive Checksum Errors
  • UDP Socket Packets Sent
  • UDP Socket Bytes Sent
  • UDP Socket Packets Received
  • UDP Socket Bytes Received
  • UDP Socket Packets Queued
  • UDP Socket Receive Packets Dropped
  • UDP Socket Checksum Errors

All these statistics and error reports are available to the application with the nx_udp_info_get service for UDP statistics amassed over all UDP sockets, and the nx_udp_socket_info_get service for UDP statistics on the specified UDP socket.

UDP Socket Control Block NX_UDP_SOCKET

The characteristics of each UDP socket are found in the associated NX_UDP_SOCKET control block. It contains useful information such as the link to the IP data structure, the network interface for the sending and receiving paths, the bound port, and the receive packet queue. This structure is defined in the nx_api.h file.

Transmission Control Protocol (TCP)

The Transmission Control Protocol (TCP) provides reliable stream data transfer between two network members (RFC 793). All data sent from one network member are verified and acknowledged by the receiving member. In addition, the two members must have established a connection prior to any data transfer. All this results in reliable data transfer; however, it does require substantially more overhead than the previously described UDP data transfer.

TCP Header

On transmission, TCP header is placed in front of the data from the user. On reception, TCP header is removed from the incoming packet, leaving only the user data available to the application. TCP utilizes the IP protocol to send and receive packets, which means there is an IP header in front of the TCP header when the packet is on the network. Figure 10 shows the format of the TCP header.

TCP Header

FIGURE 10. TCP Header

The following describes the TCP header format:

Header Field Purpose
16-bit source port number This field contains the port the TCP packet is being sent out on. Valid TCP ports range from 1 through 0xFFFF.
16-bit destination port number This field contains the TCP port the packet is being sent to. Valid TCP ports range from 1 through 0xFFFF.
32-bit sequence number This field contains the sequence number for data sent from this end of the connection. The original sequence is established during the initial connection sequence between two TCP nodes. Every data transfer from that point results in an increment of the sequence number by the amount bytes sent.
32-bit acknowledgement number This field contains the sequence number corresponding to the last byte received by this side of the connection. This is used to determine whether or not data previously sent has successfully been received by the other end of the connection.
4-bit header length This field contains the number of 32-bit words in the TCP header. If no options are present in the TCP header, this field is 5.
6-bit code bits This field contains the six different code bits used to indicate various control information associated with the connection. The control bits are defined as follows:
Name Bit Meaning
URG 21 Urgent data present
ACK 20 Acknowledgement number is valid
PSH 19 Handle this data immediately
RST 18 Reset the connection
SYN 17 Synchronize sequence numbers (used to establish connection)
FIN 16 Sender is finished with transmit (used to close connection)

16-bit window

This field is used for flow control. It contains the amount of bytes the socket can currently receive. This basically is used for flow control. The sender is responsible for making sure the data to send will fit into the receiver’s advertised window.

Header Field Purpose
16-bit TCP checksum This field contains the 16-bit checksum for the packet including the TCP header, the packet data area, and the pseudo IP header.
16-bit urgent pointer This field contains the positive offset of the last byte of the urgent data. This field is only valid if the URG code bit is set in the header.

Important

All headers in the TCP/IP implementation are expected to be in big endian format. In this format, the most significant byte of the word resides at the lowest byte address.

TCP Enable

Before TCP connections and packet transmissions are possible, the application must first enable TCP by calling the nx_tcp_enable service. After enabled, the application is free to access all TCP services.

TCP Socket Create

TCP sockets are created either during initialization or during runtime by application threads. The initial type of service, time to live, and window size are defined by the nx_tcp_socket_create service. There are no limits on the number of TCP sockets in an application.

TCP Checksum

TCP specifies a one’s complement 16-bit checksum that covers the IP pseudo header, (consisting of the source IP address, destination IP address, and the protocol/length IP word), the TCP header, and the TCP packet data.

Certain network controllers are able to perform TCP checksum computation and validation in hardware. For such systems, applications may want to use hardware checksum logic as much as possible to reduce runtime overhead. Applications may disable TCP checksum computation logic from the NetX library altogether at build time by defining NX_DISABLE_TCP_TX_CHECKSUM and NX_DISABLE_TCP_RX_CHECKSUM. This way, the TCP checksum code is not compiled in.

TCP Port

A TCP port is a logical connection point in the TCP protocol. There are 65,535 valid ports in the TCP component of NetX, ranging from 1 through 0xFFFF. Unlike UDP in which data from one port can be sent to any other destination port, a TCP port is connected to another specific TCP port, and only when this connection is established can any data transfer take place—and only between the two ports making up the connection.

Important

TCP ports are completely separate from UDP ports; e.g., UDP port number 1 has no relation to TCP port number 1.

Client-Server Model

To use TCP for data transfer, a connection must first be established between the two TCP sockets. The establishment of the connection is done in a client-server fashion. The client side of the connection is the side that initiates the connection, while the server side simply waits for client connection requests before any processing is done.

Important

For multihome devices, NetX automatically determines the source address to use for the connection, and the next hop address based on the destination IP address of the connection.

TCP Socket State Machine

The connection between two TCP sockets (one client and one server) is complex and is managed in a state machine manner. Each TCP socket starts in a CLOSED state. Through connection events each socket's state machine migrates into the ESTABLISHED state, which is where the bulk of the data transfer in TCP takes place. When one side of the connection no longer wishes to send data, it disconnects. After the other side disconnects, eventually the TCP socket returns to the CLOSED state. This process repeats each time a TCP client and server establish and close a connection. Figure 11 shows the various states of the TCP state machine.

States of the TCP State Machine

FIGURE 11. States of the TCP State Machine

TCP Client Connection

As mentioned previously, the client side of the TCP connection initiates a connection request to a TCP server. Before a connection request can be made, TCP must be enabled on the client IP instance. In addition, the client TCP socket must next be created with the nx_tcp_socket_create service and bound to a port via the nx_tcp_client_socket_bind service. After the client socket is bound, the nx_tcp_client_socket_connect service is used to establish a connection with a TCP server. Note the socket must be in a CLOSED state to initiate a connection attempt. Establishing the connection starts with NetX issuing a SYN packet and then waiting for a SYN ACK packet back from the server, which signifies acceptance of the connection request. After the SYN ACK is received, NetX responds with an ACK packet and promotes the client socket to the ESTABLISHED state.

TCP Client Disconnection

Closing the connection is accomplished by calling nx_tcp_socket_disconnect. If no suspension is specified, the client socket sends a RST packet to the server socket and places the socket in the CLOSED state. Otherwise, if a suspension is requested, the full TCP disconnect protocol is performed, as follows:

  • If the server previously initiated a disconnect request (the client socket has already received a FIN packet, responded with an ACK, and is in the CLOSE WAIT state), NetX promotes the client TCP socket state to the LAST ACK state and sends a FIN packet. It then waits for an ACK from the server before completing the disconnect and entering the CLOSED state.

  • If on the other hand, the client is the first to initiate a disconnect request (the server has not disconnected and the socket is still in the ESTABLISHED state), NetX sends a FIN packet to initiate the disconnect and waits to receive a FIN and an ACK from the server before completing the disconnect and placing the socket in a CLOSED state.

If there are still packets on the socket transmit queue, NetX suspends for the specified timeout to allow the packets to be acknowledged. If the timeout expires, NetX empties the transmit queue of the client socket.

To unbind the port from the client socket, the application calls nx_tcp_client_socket_unbind. The socket must be in a CLOSED state or in the process of disconnecting (i.e., TIMED WAIT state) before the port is released; otherwise, an error is returned.

Finally, if the application no longer needs the client socket, it calls nx_tcp_socket_delete to delete the socket.

TCP Server Connection

The server side of a TCP connection is passive; i.e., the server waits for a client to initiate connection request. To accept a client connection, TCP must first be enabled on the IP instance by calling the service nx_tcp_enable. Next, the application must create a TCP socket using the nx_tcp_socket_create service.

The server socket must also be set up for listening for connection requests. This is achieved by using the nx_tcp_server_socket_listen service. This service places the server socket in the LISTEN state and binds the specified server port to the socket.

Important

To set a socket listen callback routine the application specifies the appropriate callback function for the tcp_listen_callback argument of the nx_tcp_server_socket_listen service. This application callback function is then executed by NetX whenever a new connection is requested on this server port. The processing in the callback is under application control.

To accept client connection requests, the application calls the nx_tcp_server_socket_accept service. The server socket must either be in a LISTEN state or a SYN RECEIVED state (i.e., the server is in the LISTEN state and has received a SYN packet from a client requesting a connection) to call the accept service. A successful return status from nx_tcp_server_socket_accept indicates the connection has been set up and the server socket is in the ESTABLISHED state.

After the server socket has a valid connection, additional client connection requests are queued up to the depth specified by the listen_queue_size, passed into the nx_tcp_server_socket_listen service. In order to process subsequent connections on a server port, the application must call nx_tcp_server_socket_relisten with an available socket (i.e., a socket in a CLOSED state). Note that the same server socket could be used if the previous connection associated with the socket is now finished and the socket is in the CLOSED state.

TCP Server Disconnection

Closing the connection is accomplished by calling nx_tcp_socket_disconnect. If no suspension is specified, the server socket sends a RST packet to the client socket and places the socket in the CLOSED state. Otherwise, if a suspension is requested, the full TCP disconnect protocol is performed, as follows: |

  • If the client previously initiated a disconnect request (the server socket has already received a FIN packet, responded with an ACK, and is in the CLOSE WAIT state), NetX promotes the TCP socket state to the LAST ACK state and sends a FIN packet. It then waits for an ACK from the client before completing the disconnect and entering the CLOSED state.

  • If on the other hand, the server is the first to initiate a disconnect request (the client has not disconnected and the socket is still in the ESTABLISHED state), NetX sends a FIN packet to initiate the disconnect and waits to receive a FIN and an ACK from the client before completing the disconnect and placing the socket in a CLOSED state.

If there are still packets on the socket transmit queue, NetX suspends for the specified timeout to allow those packets to be acknowledged. If the timeout expires, NetX flushes the transmit queue of the server socket.

After the disconnect processing is complete and the server socket is in the CLOSED state, the application must call the nx_tcp_server_socket_unaccept service to end the association of this socket with the server port. Note this service must be called by the application even if nx_tcp_socket_disconnect or nx_tcp_server_socket_accept return an error status. After the nx_tcp_server_socket_unaccept returns, the socket can be used as a client or server socket, or even deleted if it is no longer needed. If accepting another client connection on the same server port is desired, the nx_tcp_server_socket_relisten service should be called on this socket.

The following code segment illustrates the sequence of calls a typical TCP server uses:

/* Set up a previously created TCP socket to listen on port 12 */

nx_tcp_server_socket_listen()

/* Loop to make a (another) connection. */
while(1) {

    /* Wait for a client socket connection request for 100 ticks. */
    nx_tcp_server_socket_accept();

    /* (Send and receive TCP messages with the TCP client) */

    /* Disconnect the server socket. */
    nx_tcp_socket_disconnect();

    /* Remove this server socket from listening on the port. */

    nx_tcp_server_socket_unaccept(&server_socket);

    /* Set up server socket to relisten on the same port for the next
    client. */
    nx_tcp_server_socket_relisten();
}

MSS Validation

The Maximum Segment Size (MSS) is the maximum amount of bytes a TCP host can receive without being fragmented by the underlying IP layer. During TCP connection establishment phase, both ends exchanges its own TCP MSS value, so that the sender does not send a TCP data segment that is larger than the receiver's MSS. NetX TCP module will optionally validate its peer's advertised MSS value before establishing a connection. By default NetX does not enable such a check. Applications wishing to perform MSS validation shall define NX_ENABLE_TCP_MSS_CHECKING when building the NetX library, and the minimum value shall be defined in NX_TCP_MSS_MINIMUM. Incoming TCP connections with MSS values below NX_TCP_MSS_MINIMUM are dropped.

Stop Listening on a Server Port

If the application no longer wishes to listen for client connection requests on a server port that was previously specified by a call to the nx_tcp_server_socket_listen service, the application simply calls the nx_tcp_server_socket_unlisten service. This service places any socket waiting for a connection back in the CLOSED state and releases any queued client connection request packets.

TCP Window Size

During both the setup and data transfer phases of the connection, each port reports the amount of data it can handle, which is called its window size. As data are received and processed, this window size is adjusted dynamically. In TCP, a sender can only send an amount of data that fits into the receiver's window. In essence, the window size provides flow control for data transfer in each direction of the connection.

TCP Packet Send

Sending TCP data is easily accomplished by calling the nx_tcp_socket_send function. If the size of the data being transmitted is larger than the MSS value of the socket or the current peer receive window size, whichever is smaller, TCP internal logic carves off the data that fits into min (MSS, peer receive Window) for transmission. This service then builds a TCP header in front of the packet (including the checksum calculation). If the receiver's window size is not zero, the caller will send as much data as it can to fill up the receiver window size. If the receive window becomes zero, the caller may suspend and wait for the receiver's window size to increase enough for this packet to be sent. At any given time, multiple threads may suspend while trying to send data through the same socket.

Important

The TCP data residing in the NX_PACKET structure should reside on a long-word boundary. In addition, there needs to be sufficient space between the prepend pointer and the data start pointer to place the TCP, IP, and physical media headers.

TCP Packet Retransmit

Previously transmitted TCP packets sent actually stored internally until an ACK is returned from the other side of the connection. If transmitted data is not acknowledged within the timeout period, the stored packet is re-sent and the next timeout period is set. When an ACK is received, all packets covered by the acknowledgement number in the internal transmit queue are finally released.

Important

Application shall not reuse the packet or alter the contents of the packet after the nx_tcp_socket_send function returns with NX_SUCCESS. The transmitted packet is eventually released by NetX internal processing after the data is acknowledged by the other end.

TCP Keepalive

TCP Keepalive feature allows a socket to detect whether or not its peer disconnects without proper termination (for example, the peer crashed), or to prevent certain network monitoring facilities to terminate a connection for long periods of idle. TCP Keepalive works by periodically sending a TCP frame with no data, and the sequence number set to one less than the current sequence number. On receiving such TCP Keepalive frame, the recipient, if still alive, responses with an ACK for its current sequence number. This completes the keepalive transaction.

By default the keepalive feature is not enabled. To use this feature, NetX library must be built with NX_ENABLE_TCP_KEEPALIVE defined. The symbol NX_TCP_KEEPALIVE_INITIAL specifies the number of seconds of inactivity before the keepalive frame is initiated.

TCP Packet Receive

The TCP receive packet processing (called from the IP helper thread) is responsible for handling various connection and disconnection actions as well as transmit acknowledge processing. In addition, the TCP receive packet processing is responsible for placing packets with receive data on the appropriate TCP socket's receive queue or delivering the packet to the first suspended thread waiting for a packet.

TCP Receive Notify

If the application thread needs to process received data from more than one socket, the nx_tcp_socket_receive_notify function should be used. This function registers a receive packet callback function for the socket. Whenever a packet is received on the socket, the callback function is executed.

The contents of the callback function are application-specific; however, the function would most likely contain logic to inform the processing thread that a packet is available on the corresponding socket.

Thread Suspension

As mentioned previously, application threads can suspend while attempting to receive data from a particular TCP port. After a packet is received on that port, it is given to the first thread suspended and that thread is then resumed. An optional timeout is available when suspending on a TCP receive packet, a feature available for most NetX services.

Thread suspension is also available for connection (both client and server), client binding, and disconnection services.

TCP Socket Statistics and Errors

If enabled, the NetX TCP socket software keeps track of several statistics and errors that may be useful to the application. The following statistics and error reports are maintained for each IP/TCP instance:

  • Total TCP Packets Sent
  • Total TCP Bytes Sent
  • Total TCP Packets Received
  • Total TCP Bytes Received
  • Total TCP Invalid Packets
  • Total TCP Receive Packets Dropped
  • Total TCP Receive Checksum Errors
  • Total TCP Connections
  • Total TCP Disconnections
  • Total TCP Connections Dropped
  • Total TCP Packet Retransmits
  • TCP Socket Packets Sent
  • TCP Socket Bytes Sent
  • TCP Socket Packets Received
  • TCP Socket Bytes Received
  • TCP Socket Packet Retransmits
  • TCP Socket Packets Queued
  • TCP Socket Checksum Errors
  • TCP Socket State
  • TCP Socket Transmit Queue Depth
  • TCP Socket Transmit Window Size
  • TCP Socket Receive Window Size

All these statistics and error reports are available to the application with the nx_tcp_info_get service for total TCP statistics and the nx_tcp_socket_info_get service for TCP statistics per socket.

TCP Socket Control Block NX_TCP_SOCKET

The characteristics of each TCP socket are found in the associated NX_TCP_SOCKET control block, which contains useful information such as the link to the IP data structure, the network connection interface, the bound port, and the receive packet queue. This structure is defined in the nx_api.h file.