Lines Matching full:the

4 \mainpage The uIP TCP/IP stack
7 The uIP TCP/IP stack is intended to make it possible to communicate
8 using the TCP/IP protocol suite even on small 8-bit
11 with peers running a similarly light-weight stack. The code size is on
12 the order of a few kilobytes and RAM usage can be configured to be as
15 uIP can be found at the uIP web page: http://www.sics.se/~adam/uip/
24 (see below) and the \ref psock "protosockets API" and their underlying
29 With the success of the Internet, the TCP/IP protocol suite has become
30 a global standard for communication. TCP/IP is the underlying protocol
32 peer-to-peer networking over the Internet. For embedded systems, being
33 able to run native TCP/IP makes it possible to connect the system
34 directly to an intranet or even the global Internet. Embedded devices
36 being able to fully communicate with other hosts in the network.
42 impossible to fit the full TCP/IP stack into systems with a few tens
46 The uIP implementation is designed to have only the absolute minimal
48 single network interface and contains the IP, ICMP, UDP and TCP
49 protocols. uIP is written in the C programming language.
51 Many other TCP/IP implementations for small systems assume that the
56 essential, however, if the embedded device is to communicate with
59 compliant in order to let the embedded devices to act as first-class
60 network citizens. The uIP TCP/IP implementation that is not tailored
66 The full TCP/IP suite consists of numerous protocols, ranging from low
69 transfer e-mail. The uIP is mostly concerned with the TCP and IP
70 protocols and upper layer protocols will be referred to as "the
72 or firmware and will be referred to as "the network device" that are
73 controlled by the network device driver.
75 TCP provides a reliable byte stream to the upper layer protocols. It
76 breaks the byte stream into appropriately sized segments and each
77 segment is sent in its own IP packet. The IP packets are sent out on
78 the network by the network device driver. If the destination is not on
79 the physically connected network, the IP packet is forwarded onto
80 another network by a router that is situated between the two
81 networks. If the maximum packet size of the other network is smaller
82 than the size of the IP packet, the packet is fragmented into smaller
83 packets by the router. If possible, the size of the TCP segments are
84 chosen so that fragmentation is minimized. The final recipient of the
88 The formal requirements for the protocols in the TCP/IP stack is
89 specified in a number of RFC documents published by the Internet
90 Engineering Task Force, IETF. Each of the protocols in the stack is
92 all requirements and updates the previous RFCs.
94 The RFC1122 requirements can be divided into two categories; those
95 that deal with the host to host communication and those that deal with
96 communication between the application and the networking stack. An
97 example of the first kind is "A TCP MUST be able to receive a TCP
98 option in any segment" and an example of the second kind is "There
99 MUST be a mechanism for reporting soft TCP error conditions to the
101 the first kind may not be able to communicate with other TCP/IP
103 the second kind of requirements will only affect the communication
104 within the system and will not affect host-to-host communication.
108 removed certain mechanisms in the interface between the application
109 and the stack, such as the soft error reporting mechanism and
116 The uIP stack can be run either as a task in a multitasking system, or
117 as the main program in a singletasking system. In both cases, the main
120 - Check if a packet has arrived from the network.
123 If a packet has arrived, the input handler function, uip_input(),
124 should be invoked by the main control loop. The input handler function
125 will never block, but will return at once. When it returns, the stack
126 or the application for which the incoming packet was intended may have
128 the network device driver should be called to send out these packets.
132 round-trip time estimations. When the main control loop infers that
133 the periodic timer should fire, it should invoke the timer handler
134 function uip_periodic(). Because the TCP/IP stack may perform
135 retransmissions when dealing with a timer event, the network device
136 driver should called to send out the packets that may have been produced.
140 uIP requires a few functions to be implemented specifically for the
142 be hand-tuned for the particular architecture, but generic C
143 implementations are given as part of the uIP distribution.
147 The TCP and IP protocols implement a checksum that covers the data and
148 header portions of the TCP and IP packets. Since the calculation of
150 received it is important that the function that calculates the
151 checksum is efficient. Most often, this means that the checksum
152 calculation must be fine-tuned for the particular architecture on
153 which the uIP stack runs.
156 for an architecture specific implementation of the two functions
157 uip_ipchksum() and uip_tcpchksum(). The checksum calculations in those
163 The TCP protocol uses 32-bit sequence numbers, and a TCP
165 the normal protocol processing. Since 32-bit arithmetic is not
166 natively available on many of the platforms for which uIP is intended,
167 uIP leaves the 32-bit additions to be implemented by the architecture
168 specific module and does not make use of any 32-bit arithmetic in the
172 having an architecture specific implementation of the uip_add32()
178 In the architectures for which uIP is intended, RAM is the most
179 scarce resource. With only a few kilobytes of RAM available for the
184 The uIP stack does not use explicit dynamic memory
186 packets and has a fixed table for holding connection state. The global
188 size. When a packet arrives from the network, the device driver places
189 it in the global buffer and calls the TCP/IP stack. If the packet
190 contains data, the TCP/IP stack will notify the corresponding
191 application. Because the data in the buffer will be overwritten by the
192 next incoming packet, the application will either have to act
193 immediately on the data or copy the data into a secondary buffer for
194 later processing. The packet buffer will not be overwritten by new
195 packets before the application has processed the data. Packets that
196 arrive when the application is processing the data must be queued,
197 either by the network device or by the device driver. Most single-chip
200 handled by the processor, such as RS-232 ports, can copy incoming
201 bytes to a separate buffer during application processing. If the
202 buffers are full, the incoming packet is dropped. This will cause
206 the network per connection.
208 In uIP, the same global packet buffer that is used for incoming
209 packets is also used for the TCP/IP headers of outgoing data. If the
210 application sends dynamic data, it may use the parts of the global
212 buffer. To send the data, the application passes a pointer to the data
213 as well as the length of the data to the stack. The TCP/IP headers are
214 written into the global buffer and once the headers have been
215 produced, the device driver sends the headers and the application data
216 out on the network. The data is not queued for
217 retransmissions. Instead, the application will have to reproduce the
220 The total amount of memory usage for uIP depends heavily on the
221 applications of the particular device in which the implementations are
222 to be run. The memory configuration determines both the amount of
223 traffic the system should be able to handle and the maximum amount of
225 while at the same time running a web server with highly dynamic web
227 simple Telnet server. It is possible to run the uIP implementation
235 The Application Program Interface (API) defines the way the
236 application program interacts with the TCP/IP stack. The most commonly
237 used API for TCP/IP is the BSD socket API which is used in most Unix
238 systems and has heavily influenced the Microsoft Windows WinSock
239 API. Because the socket API uses stop-and-wait semantics, it requires
240 support from an underlying multitasking operating system. Since the
242 space for the tasks might be too high in the intended uIP target
243 architectures, the BSD socket interface is not suitable for our
247 API without the overhead of full multi-threading, and a "raw"
255 \subsection rawapi The uIP raw API
257 The "raw" uIP API uses an event driven interface where the application is
260 response to certain events. uIP calls the application when data is
261 received, when data has been successfully delivered to the other end
262 of the connection, when a new connection has been set up, or when data
263 has to be retransmitted. The application is also periodically polled
264 for new data. The application program provides only one callback
265 function; it is up to the application to deal with mapping different
266 network services to different ports and connections. Because the
268 soon as the TCP/IP stack receives the packet, low response times can
272 from the application when doing retransmissions. Other TCP/IP stacks
273 buffer the transmitted data in memory until the data is known to be
274 successfully delivered to the remote end of the connection. If the
275 data needs to be retransmitted, the stack takes care of the
276 retransmission without notifying the application. With this approach,
277 the data has to be buffered in memory while waiting for an
278 acknowledgment even if the application might be able to quickly
279 regenerate the data if a retransmission has to be made.
281 In order to reduce memory usage, uIP utilizes the fact that the
282 application may be able to regenerate sent data and lets the
284 packet contents after they have been sent by the device driver, and
285 uIP requires that the application takes an active part in performing
286 the retransmission. When uIP decides that a segment should be
287 retransmitted, it calls the application with a flag set indicating
288 that a retransmission is required. The application checks the
289 retransmission flag and produces the same data that was previously
290 sent. From the application's standpoint, performing a retransmission
291 is not different from how the data originally was sent. Therefore the
292 application can be written in such a way that the same code is used
294 to note that even though the actual retransmission operation is
295 carried out by the application, it is the responsibility of the stack
296 to know when the retransmission should be made. Thus the complexity of
297 the application does not necessarily increase because it takes an
302 The application must be implemented as a C function, UIP_APPCALL(),
305 events. The functions are implemented as C macros that will evaluate
307 conjunction with each other (i.e., new data can arrive at the same
310 \subsubsection connstate The Connection Pointer
312 When the application is called by uIP, the global variable uip_conn is
313 set to point to the uip_conn structure for the connection that
314 currently is handled, and is called the "current connection". The
315 fields in the uip_conn structure for the current connection can be
317 which IP address the connection is connected. One typical use would be
318 to inspect the uip_conn->lport (the local TCP port number) to decide
319 which service the connection should provide. For instance, an
320 application might decide to act as an HTTP server if the value of
321 uip_conn->lport is equal to 80 and act as a TELNET server if the value
326 If the uIP test function uip_newdata() is non-zero, the remote host of
327 the connection has sent new data. The uip_appdata pointer point to the
328 actual data. The size of the data is obtained through the uIP function
329 uip_datalen(). The data is not buffered by uIP, but will be
330 overwritten after the application function returns, and the
331 application will therefor have to either act directly on the incoming
332 data, or by itself copy the incoming data into a buffer for later
337 When sending data, uIP adjusts the length of the data sent by the
338 application according to the available buffer space and the current
339 TCP window advertised by the receiver. The amount of buffer space is
340 dictated by the memory configuration. It is therefore possible that
341 all data sent from the application does not arrive at the receiver,
342 and the application may use the uip_mss() function to see how much
343 data that actually will be sent by the stack.
345 The application sends data by using the uIP function uip_send(). The
346 uip_send() function takes two arguments; a pointer to the data to be
347 sent and the length of the data. If the application needs RAM space
348 for producing the actual data that should be sent, the packet buffer
349 (pointed to by the uip_appdata pointer) can be used for this purpose.
351 The application can send only one chunk of data at a time on a
353 per application invocation; only the data from the last call will be
358 Retransmissions are driven by the periodic TCP timer. Every time the
359 periodic timer is invoked, the retransmission timer for each
360 connection is decremented. If the timer reaches zero, a retransmission
362 been sent by the device driver, uIP requires that the
363 application takes an active part in performing the
365 retransmitted, the application function is called with the
369 The application must check the uip_rexmit() flag and produce the same
370 data that was previously sent. From the application's standpoint,
371 performing a retransmission is not different from how the data
372 originally was sent. Therefor, the application can be written in such
373 a way that the same code is used both for sending data and
375 the actual retransmission operation is carried out by the application,
376 it is the responsibility of the stack to know when the retransmission
377 should be made. Thus the complexity of the application does not
383 The application closes the current connection by calling the
384 uip_close() during an application call. This will cause the connection
385 to be cleanly closed. In order to indicate a fatal error, the
386 application might want to abort the connection and does so by calling
387 the uip_abort() function.
389 If the connection has been closed by the remote end, the test function
390 uip_closed() is true. The application may then do any necessary
396 that the connection was aborted by the remote host, or that the
397 connection retransmitted the last data too many times and has been
398 aborted. uIP reports this by calling the application function. The
399 application can use the two test functions uip_aborted() and
404 When a connection is idle, uIP polls the application every time the
405 periodic timer fires. The application uses the test function
408 The polling event has two purposes. The first is to let the
410 the application to close connections that have been idle for too
411 long. The other purpose is to let the application send new data that
412 has been produced. The application can only send data when invoked by
413 uIP, and therefore the poll event is the only way to send data on an
419 listening with the uip_listen() function. When a connection request
421 the application function. The test function uip_connected() is true if
422 the application was invoked because a new connection was created.
424 The application can check the lport field in the uip_conn structure to
425 check to which port the new connection was connected.
430 uIP by the function uip_connect(). This function
431 allocates a new connection and sets a flag in the connection state
432 which will open a TCP connection to the specified IP address and port
433 the next time the connection is polled by uIP. The uip_connect()
435 a pointer to the uip_conn structure for the new
436 connection. If there are no free connection slots, the function
439 The function uip_ipaddr() may be used to pack an IP address into the
442 Two examples of usage are shown below. The first example shows how to
443 open a connection to TCP port 8080 of the remote end of the current
445 new connection to be opened, the uip_connect() function returns NULL
446 and the current connection is aborted by uip_abort().
456 The second example shows how to open a new connection to a specific IP
470 This section presents a number of very simple uIP applications. The
475 This first example shows a very simple application. The application
477 been established, the application replies to all data sent to it by
480 The implementation of this application is shown below. The application
481 is initialized with the function called example1_init() and the uIP
482 callback function is called example1_app(). For this application, the
498 The initialization function calls the uIP function uip_listen() to
499 register a listening port. The actual application function
500 example1_app() uses the test functions uip_newdata() and uip_rexmit()
501 to determine why it was called. If the application was called because
502 the remote end has sent it data, it responds with an "ok". If the
503 application function was called because data was lost in the network
511 This second example is slightly more advanced than the previous one,
512 and shows how the application state field in the uip_conn structure is
515 This application is similar to the first application in that it
517 to it with a single "ok". The big difference is that this application
518 prints out a welcoming "Welcome!" message when the connection has been
522 the application is implemented. The reason for the increase in
523 complexity is that if data should be lost in the network, the
524 application must know what data to retransmit. If the "Welcome!"
525 message was lost, the application must retransmit the welcome and if
526 one of the "ok" messages is lost, the application must send a new
529 The application knows that as long as the "Welcome!" message has not
530 been acknowledged by the remote host, it might have been dropped in
531 the network. But once the remote host has sent an acknowledgment
532 back, the application can be sure that the welcome has been received
533 and knows that any lost data must be an "ok" message. Thus the
534 application can be in either of two states: either in the WELCOME-SENT
535 state where the "Welcome!" has been sent but not acknowledged, or in
536 the WELCOME-ACKED state where the "Welcome!" has been acknowledged.
538 When a remote host connects to the application, the application sends
539 the "Welcome!" message and sets it's state to WELCOME-SENT. When the
540 welcome message is acknowledged, the application moves to the
541 WELCOME-ACKED state. If the application receives any new data from the
544 If the application is requested to retransmit the last message, it
545 looks at in which state the application is. If the application is in
546 the WELCOME-SENT state, it sends a "Welcome!" message since it
547 knows that the previous welcome message hasn't been acknowledged. If
548 the application is in the WELCOME-ACKED state, it knows that the last
551 The implementation of this application is seen below. This
552 configuration settings for the application is follows after its
596 The configuration for the application:
605 If the system should run multiple applications, one technique to
606 differentiate between them is to use the TCP port number of either the
607 remote end or the local end of the connection. The example below shows
608 how the two examples above can be combined into one application.
632 disk drive. This shows how to use the flow control functions of uIP.
663 When the connection has been established, an HTTP request is sent to
664 the server. Since this is the only data that is sent, the application
667 events as is done in the example.
669 When the application receives new data from the remote host, it sends
670 this data to the device by using the function device_enqueue(). It is
672 the data into its own buffers. The data in the uip_appdata buffer will
673 be overwritten by the next incoming packet.
675 If the device's queue is full, the application stops the data from the
676 remote host by calling the uIP function uip_stop(). The application
678 uip_restart() is called. The application polling event is used to
679 check if the device's queue is no longer full and if so, the data flow
685 to two ports and uses the port number to determine which file to
686 send. If the files are properly formatted, this simple application can
687 be used as a web server with static pages. The implementation follows.
731 The application state consists of a pointer to the data that should be
732 sent and the size of the data that is left to send. When a remote host
733 connects to the application, the local port number is used to
734 determine which file to send. The first chunk of data is sent using
736 actually sent, even though s->dataleft may be larger than the MSS.
738 The application is driven by incoming acknowledgments. When data has
740 send, the connection is closed using uip_close().
745 utilize the uIP API in a structured way. The following example
747 writing larger protocol implementations than the previous examples
748 showed here. The program is divided into an uIP event handler function
751 establishment or closure events and handle errors. The functions are
754 the protocol that is being implemented.
756 The uIP event handler function is shown below.
788 The function starts with dealing with any error conditions that might
790 true. If so, the appropriate error function is called. Also, if the
791 connection has been closed, the closed() function is called to the it
792 deal with the event.
794 Next, the function checks if the connection has just been established
795 by checking if uip_connected() is true. The connected() function is
796 called and is supposed to do whatever needs to be done when the
797 connection is established, such as intializing the application state
798 for the connection. Since it may be the case that data should be sent
799 out, the senddata() function is called to deal with the outgoing data.
801 The following very simple application serves as an example of how the
803 waits for any data to arrive on the connection, and responds to the
804 data by sending out the message "Hello world!". To illustrate how to
806 parts, first the "Hello" part and then the "world!" part.
868 The application state consists of a "state" variable, a "textptr"
869 pointer to a text message and the "textlen" length of the text
870 message. The "state" variable can be either "STATE_WAITING", meaning
871 that the application is waiting for data to arrive from the network,
872 "STATE_HELLO", in which the application is sending the "Hello" part of
873 the message, or "STATE_WORLD", in which the application is sending the
876 The application does not handle errors or connection closing events,
877 and therefore the aborted(), timedout() and closed() functions are
880 The connected() function will be called when a connection has been
881 established, and in this case sets the "state" variable to be
882 "STATE_WAITING" and the "textlen" variable to be zero, indicating that
885 When new data arrives from the network, the newdata() function will be
886 called by the event handler function. The newdata() function will
887 check if the connection is in the "STATE_WAITING" state, and if so
888 switches to the "STATE_HELLO" state and registers a 6 byte long "Hello
889 " message with the connection. This message will later be sent out by
890 the senddata() function.
892 The acked() function is called whenever data that previously was sent
893 has been acknowleged by the receiving host. This acked() function
894 first reduces the amount of data that is left to send, by subtracting
895 the length of the previously sent data (obtained from "uip_conn->len")
896 from the "textlen" variable, and also adjusts the "textptr" pointer
897 accordingly. It then checks if the "textlen" variable now is zero,
899 if so changes application state. If the application was in the
901 7 byte "world!\n" message to be sent. If the application was in the
902 "STATE_WORLD" state, it closes the connection.
904 Finally, the senddata() function takes care of actually sending the
905 data that is to be sent. It is called by the event handler function
907 a new connection has been established, when the connection is polled
908 because of inactivity, or when a retransmission should be made. The
909 purpose of the senddata() function is to optionally format the data
910 that is to be sent, and to call the uip_send() function to actually
911 send out the data. In this particular example, the function simply
912 calls uip_send() with the appropriate arguments if data is to be sent,
913 after checking if data should be sent out or not as indicated by the
916 It is important to note that the senddata() function never should
917 affect the application state; this should only be done in the acked()
922 The protocols in the TCP/IP protocol suite are designed in a layered
923 fashion where each protocol performs a specific function and the
924 interactions between the protocol layers are strictly defined. While
925 the layered approach is a good way to design protocols, it is not
926 always the best way to implement them. In uIP, the protocol
929 This section gives detailed information on the specific protocol
934 When incoming packets are processed by uIP, the IP layer is the first
935 protocol that examines the packet. The IP layer does a few simple
936 checks such as if the destination IP address of the incoming packet
937 matches any of the local IP address and verifies the IP header
945 holds the packet to be reassembled. An incoming fragment is copied
946 into the right place in the buffer and a bit map is used to keep track
947 of which fragments have been received. Because the first byte of an IP
948 fragment is aligned on an 8-byte boundary, the bit map requires a
949 small amount of memory. When all fragments have been reassembled, the
950 resulting IP packet is passed to the transport layer. If all fragments
951 have not been received within a specified time frame, the packet is
954 The current implementation only has a single buffer for holding
957 uncommon, this ought to be a reasonable decision. Extending the
963 IP has the ability to broadcast and multicast packets on the local
966 as the Microsoft Windows file-sharing SMB protocol. Multicast is
975 The ICMP protocol is used for reporting soft error conditions and for
976 querying host parameters. Its main use is, however, the echo mechanism
977 which is used by the "ping" program.
979 The ICMP implementation in uIP is very simple as itis restricted to
981 constructed by simply swapping the source and destination IP addresses
982 of incoming echo requests and rewriting the ICMP header with the
983 Echo-Reply message type. The ICMP checksum is adjusted using standard
986 Since only the ICMP echo message is implemented, there is no support
993 The TCP implementation in uIP is driven by incoming packets and timer
994 events. Incoming packets are parsed by TCP and if the packet contains
995 data that is to be delivered to the application, the application is
996 invoked by the means of the application function call. If the incoming
997 packet acknowledges previously sent data, the connection state is
998 updated and the application is informed, allowing it to send out new
1004 uIP, a listening connection is identified by the 16-bit port number
1005 and incoming connection requests are checked against the list of
1007 and can be altered by the applications in the system.
1015 The sliding window algorithm uses a lot of 32-bit operations and
1024 the sliding window algorithm, it is not required by the TCP
1025 specifications. Removing the sliding window mechanism does not affect
1030 TCP continuously estimates the current Round-Trip Time (RTT) of every
1031 active connection in order to find a suitable value for the
1034 The RTT estimation in uIP is implemented using TCP's periodic
1035 timer. Each time the periodic timer fires, it increments a counter for
1036 each connection that has unacknowledged data in the network. When an
1037 acknowledgment is received, the current value of the counter is used
1038 as a sample of the RTT. The sample is used together with Van
1040 estimate of the RTT. Karn's algorithm is used to ensure that
1041 retransmissions do not skew the estimates.
1045 Retransmissions are driven by the periodic TCP timer. Every time the
1046 periodic timer is invoked, the retransmission timer for each
1047 connection is decremented. If the timer reaches zero, a retransmission
1051 been sent by the device driver, uIP requires that the
1052 application takes an active part in performing the
1054 retransmitted, it calls the application with a flag set indicating
1055 that a retransmission is required. The application checks the
1056 retransmission flag and produces the same data that was previously
1057 sent. From the application's standpoint, performing a retransmission
1058 is not different from how the data originally was sent. Therefore the
1059 application can be written in such a way that the same code is used
1061 to note that even though the actual retransmission operation is
1062 carried out by the application, it is the responsibility of the stack
1063 to know when the retransmission should be made. Thus the complexity of
1064 the application does not necessarily increase because it takes an
1069 The purpose of TCP's flow control mechanisms is to allow communication
1071 segment, the sender of the segment indicates its available buffer
1072 space. A TCP sender must not send more data than the buffer space
1073 indicated by the receiver.
1075 In uIP, the application cannot send more data than the receiving host
1076 can buffer. And application cannot send more data than the amount of
1077 bytes it is allowed to send by the receiving host. If the remote host
1078 cannot accept any data at all, the stack initiates the zero window
1083 The congestion control mechanisms limit the number of simultaneous TCP
1084 segments in the network. The algorithms used for congestion control
1089 the amount of simultaneous segments cannot be further limited, thus
1090 the congestion control mechanisms are not needed.
1096 parts of the data stream as being more urgent than the normal
1097 stream. It is up to the receiving application to interpret the meaning
1098 of the urgent data.
1100 In many TCP implementations, including the BSD implementation, the
1101 urgent data feature increases the complexity of the implementation
1104 based API, the implementation of the urgent data feature does not lead
1110 dominated by the checksum calculation loop, the operation of copying
1114 the TCP/IP stack is run in the kernel, data has to be copied between
1115 the kernel space and the address space of the user processes and a
1116 context switch has to be performed once the data has been
1117 copied. Performance can be enhanced by combining the copy operation
1118 with the checksum calculation. Because high-end systems usually have
1122 A small embedded device does not have the necessary processing power
1123 to have multiple protection domains and the power to run a
1125 data between the TCP/IP stack and the application program. With an
1126 event based API there is no context switch between the TCP/IP stack
1127 and the applications.
1129 In such limited systems, the TCP/IP processing overhead is dominated
1130 by the copying of packet data from the network device to host memory,
1131 and checksum calculation. Apart from the checksum calculation and
1132 copying, the TCP processing done for an incoming packet involves only
1133 updating a few counters and flags before handing the data over to the
1134 application. Thus an estimate of the CPU overhead of our TCP/IP
1135 implementations can be obtained by calculating the amount of CPU
1136 cycles needed for the checksum calculation and copying of a maximum
1139 \subsection delack The Impact of Delayed Acknowledgments
1141 Most TCP receivers implement the delayed acknowledgment algorithm for
1142 reducing the number of pure acknowledgment packets sent. A TCP
1145 time-frame, an acknowledgment is sent. The time-frame can be as high
1149 segment will interact poorly with the delayed acknowledgment
1150 algorithm. Because the receiver only receives a single segment at a
1152 sent. This means that the maximum possible throughput is severely
1153 limited by the 500 ms idle time.
1155 Thus the maximum throughput equation when sending data from uIP will
1156 be $p = s / (t + t_d)$ where $s$ is the segment size and $t_d$ is the
1159 and a delayed acknowledgment timeout of 200 ms, the maximum
1160 throughput will be 4166 bytes per second. With the delayed acknowledgment
1161 algorithm disabled at the receiver, the maximum throughput would be
1165 not very likely to have large amounts of data to send, the delayed
1168 than a single TCP segment, and would therefore not be affected by the
1171 The maximum throughput when uIP acts as a receiver is not affected by
1172 the delayed acknowledgment throughput degradation.