Building TCP/IP packets A look at the computation-steps utilizing the TCP/IP protocol

Building TCP/IP packets
A look at the computation-steps
which need to be performed for
utilizing the TCP/IP protocol
NIC’s ‘offloading’ capabilities
• An advanced feature of Intel’s most recent
PRO1000 gigabit ethernet controllers is an
ability to perform many of the calculations
associated with the processing of network
packets which otherwise would have to be
programmed by device-driver authors and
then executed at runtime by a CPU that
has much other vital work to attend to
How much work?
• To gain a concrete idea of the work that is
required to set up a conventional network
packet for transmission, and then to take it
apart when it’s received, we have created
a character-mode Linux driver that shows
us all of the essential calculation-steps, as
it does not rely on the usual networking
software included within Linux’s kernel
TCP/IP over Ethernet
Here is a diagram, from Intel’s Software Developer’s Manual,
of the widely deployed TCP/IP Ethernet packet format
UnixWare: online tutorial
recommended background reading
“The TCP/IP Protocol Stack”
© 2002 Caldera International, Inc. All rights reserved.
UnixWare 7 Release 7.1.3 - 30 October 2002
<http://uw713doc.sco.com/en/NET_tcpip/tcpN.tcpip_stack.html>
TCP/IP Protocol Stack
by Caldera, Incorporated
Encapsulation and Decapsulation
of Data within a network stack
by Caldera, Incorporated
Network stack support for TCP/IP
by Caldera, Incorporated
Internet Protocol Header
IP Header (Little Endian layout)
Transport Control Protocol Header
TCP Header (Little-Endian layout)
TCP Pseudo Header layout
Our ‘nictcp.c’ demo
• This device-driver’s ‘write()’ function will
show the sequence of steps needed for
building a packet with the TCP/IP format:
•
•
•
•
•
•
•
Setup the packet’s data ‘payload’
Prepend a TCP packet-header
Then prepend a TCP ‘pseudo’ packet-header
Compute and insert the TCP checksum
Replace the pseudo-header with an IP header
Compute and insert the IP Header Checksum
Finally prepend the Ethernet Header
Two checksum calculations
The TCP Checksum gets inserted here
The TCP Segment
TCP Pseudo-Header
TCP Header
packet-data
The TCP Checksum is computed over this array of words
The IP Header Checksum gets inserted here
Frame
Header
IP Header
The IP Header Checksum
is computed over this
array of words
TCP Header
packet-data
Sample checksum algorithm
// to compute and insert the TCP Checksum
unsigned char
*cp = phys_to_virt( txring[ txtail ].base_addr );
unsigned short *wp = (unsigned short *)( cp + 22 );
unsigned int
nbytes = 12 + 20 + len;
unsigned int
nwords = (nbytes / 2) + (nbytes % 2);
unsigned int
cksum = 0;
if ( len & 1 ) cp[ 14 + 20 + 20 + len ] = 0;
// padding
for (int i = 0; i < nwords; i++) cksum += htons( wp[ i ] );
cksum += (cksum >> 16);
// end-around-carries
cksum & 0xFFFF;
// mask for 16-bits
cksum ^= 0xFFFF;
// flip the low 16-bits
*(unsigned short*)(cp + 50) = htons( cksum );
In-class demonstration
• We can use our ‘pktsplit.c’ demo-module
to confirm the correctness of our TCP/IP
packet-format as far as the NIC hardware
is concerned – it reports (in its descriptor
‘status’ and ‘errors’ fields) that both of our
checksums were computed by the NIC on
reception -- and that neither was in error
In-class exercise
• Can you adapt these ideas in our ‘nictcp.c’
driver to produce the analogous ‘nicudp.c’
demonstration module?
• A similar ‘pseudo’ UDP Header is used to
calculate the UDP Checksum value (see
the Intel Software Developer’s Manual for
the layout and size of the UDP Header)