Re: UDP network problem

Glynn Clements (glynn@sensei.co.uk)
Wed, 20 Aug 1997 16:00:46 +0100


mshar@vax.ipm.ac.ir wrote:

> Alan Advised to increase the queue length of the slip driver (tx_queue_len,
> in file drivers/net/slip.c) from 10 to 100. I did it, and now it is possible
> to send larger packets using UDP! Thanks Alan.
>
> However I doubt if this is a general solution. One might need to transfer
> arbitrary long messages using UDP. I wonder how TCP is dealing with this
> problem: if I am not mistaken, UDP and TCP wind up using the same driver.

Both TCP and UDP use IP as the underlying protocol. The similarities
end there, however.

TCP doesn't have to preserve datagram boundaries. One write() to a TCP
stream may result in many IP datagrams being transmitted. Conversely,
multiple write()s may be coalesced into a single IP datagram (e.g.
Nagle algorithm).

With UDP, each write() generates exactly one UDP datagram which
generates exactly one IP datagram. The maximum size of an IP datagram
is implementation dependent. The guaranteed minimum is only 576 bytes.

Also, the maximum UDP datagram size is limited by the size of the send
buffer (SO_SNDBUF socket option).

Also, if you send an IP datagram which is larger than the MTU of the
outgoing interface on the sending host, or of any intermediate router,
the datagram will be fragmented. This is generally undesirable, as
loss of one fragment will require the entire datagram to be
retransmitted, not just the lost fragment.

> Is there a way to get and set the MTU or the number of buffers, from a user
> space program? If so, then one could try adjusting them to suit the size of
> the data he wants to transfer.

The MTU is a per interface parameter, and may be restricted by the
type of interface, e.g. ethernet is limited to 1500 bytes.

> Unfortunately there is an absolute packet size limit in the kernel (64K
> bytes, I think),

This is a limitation of the IP protocol.

> and it seems that breaking up the data to smaller sections
> and sending them one after the other does not work. Here is part of the code
> I used for the sender. In the receiver, a recvfrom() is used in a similar
> loop, but no min() function is used there
>
> nleft = nbytes; /* bytes to send */
> while(nleft > 0)
> {
> nread = sendto(socket, ptr, min(nleft, 3000), 0, destination_addr, addr_len);
> ...
> if(nread > 0)
> {
> nleft -= nread;
> ptr += nread;
> }
> }
>
> I tested it with the unmodified slip driver. Sending 4000 bytes would result
> in the receiver getting 3000 bytes. The sender announces that the other 1000
> bytes were sent as well, but nothing reaches the receiver, which just blocks
> for these 1000 bytes.

Bear in mind that UDP is an _unreliable_ protocol, i.e. success in
sending does _not_ imply that the datagram will be successfully
received.

You will need to implement a mechanism whereby the receiver
acknowledges receipt, and the sender resends the data if no
acknowledgement is received within a given time period.

Look at the specification of the TFTP protocol (RFC 1350) for an
example.

> How can one send arbitrary long data (even more than 64k) with UDP?

By splitting the data up into smaller packets.

If you're transferring large amounts of data, you should consider
whether you might be better off using TCP instead.

-- 
Glynn Clements <glynn@sensei.co.uk>