IP fragmentation - networking

I've encountered the following statement somewhere in the net: "Although
theoretically only 8 bytes of L4 info may be guaranteed in a fragment,
assume complete L4 info is available...". I don't understand how possible
that only 8 bytes of a transport are guaranteed in a fragment, as the IP
fragment can't be less than 46 bytes (minimum payload size for Ethernet
frame), and this includes 20 bytes of IP header and 20bytes of TCP header
(not considering variable-lngth options), UDP will be less.
Thus for the first IP fragment we always can expect IP header at tcp header,
while other fragments will carry only IP header + payload.
I believe I'm missing something, but I still can't understand why only 8
bytes can be guaranteed in a fragment? I would appreaciate if someone helps
to clarify this issue. Thanks !
Mark

Imagine a router receives a TCP packet containing one more byte of data than will fit in the MTU of the destination network. It must split on an 8-byte boundary because that's an IP fragmentation rule.
It won't split into more than two fragments because that would be silly. So it must include at least one byte of data in the first fragment..
Thus the minimum number of data bytes you can place in the first fragment of an IP datagram is 8.

Related

How to fill the UDP length in the first UDP fragment when UDP package divided to IP fragment?

For example, one 2000 bytes UDP package(contains UDP header) and network MTU is 1500. So this UDP package should be split to two IP fragments. Only the first IP package contains the UDP header.
What value should be filled into UDP length in the UDP header of first IP package? 1480 or 2000?
Is there any document to confirm this?
UDP Length is the length of the UDP header AND the UDP data, in bytes. The fragmentation will/should NOT change this.
[UDP] "Length is the length in octets of this user datagram including this header and the data" --RFC768, an Internet Standard. It is also in the Stevens link referenced: "Referring to Figure 10-2, the UDP Length field is the length of the UDP header and the UDP data in bytes."
I think you may be overthinking this. Just set the UDP length to however big your data is.
IP fragmenting can occur at any router hop, without your knowledge (assuming you are the sender). It's the IP layer's responsibility to fragment and re-assemble the packet before the UDP datagram is delivered to the application. Unless you're plugged in to the NIC driver, you won't be able to reliably tell if the packet was fragmented on the way.
If there's an IP fragment lost on the way, you won't get any UDP datagram at all, it will simply be lost from the application's point of view, even though the IP layer may have gotten 9 out of 10 fragments.
Everything about this is brilliantly described in Richard Stevens et al's seminal work: TCP/IP Illustrated, Volume 1: The protocols
, section 10.7 IP Fragementation.

Send packets larger than 64K in TCP

As far as we know the absolute limitation on TCP packet size is 64K (65535 bytes), and in practicality this is far larger than the size of any packet you will see, because the lower layers (e.g. ethernet) have lower packet sizes. The MTU (Maximum Transmission Unit) for Ethernet, for instance, is 1500 bytes.
I want to know, Is there any any way or any tools, to send packets larger than 64k?
I want to test a device in facing with packet larger than 64k! I mean I want to see, if I send a packet larger than 64K, how it behave? Does it drop some part of it? Or something else.
So :
1- How to send this large packets? What is the proper layer for this?
2- How the receiver behave usually?
The IP packet format has only 16 bit for the size of the packet, so you will not be able to create a packet with a size larger than 64k. See http://en.wikipedia.org/wiki/IPv4#Total_Length. Since TCP uses IP as the lower layer this limit applies here too.
There is no such thing as a TCP packet. TCP data is sent and received in segments, which can be as large as you like up to the limits of the API you're using, as they can be comprised of multiple IP packets. At the receiver TCP is indistinguishable from a byte stream.
NB osi has nothing to do with this, or anything else.
TCP segments are not size-limited. The thing which imposes the limit is that IPv4 and IPv6 packets have 16 bit length fields, so a size larger than this limit is not possible to express.
However, RFC 2675 is a proposed standards for IPv6 which would expand the length field to 32 bits, allowing much larger TCP segments.
See here for a talk about why this change could help improve performance and here for a set of (experimental) patches to Linux to enable this RFC.

RFC791, MTU and a minimum packet size

I was reading rfc791 and trying to understand the relations with MTU as well as with the minimum packet size for IPv4. Here are two quotes from the rfc:
"All hosts must be prepared to accept datagrams of up to 576 octets (whether they arrive whole or in fragments)."
And
"Every internet module must be able to forward a datagram of 68 octets without further fragmentation. This is because an internet header may be up to 60 octets, and the minimum fragment is 8 octets."
Do I understand correctly that first related only to hosts, i.e. only hosts must be able to process minimum packet size of 576 bytes, while the second statement defines the mi packet size for a router? But of so, then it is possible to have a router not being able to receive a packet of 68 bytes for himself ?
Or I'm missing something very fundamental?
Thanks.
Mark
The 576 octet is a "least maximum". In other words, a host needs to be prepared to have a maximum packet size of no less than 576 octets. It can be bigger than that, such as the 1518 limit used by most (non-jumbo) Ethernet devices, but not any smaller.
Anything that is set up to forward packets must not split them into chunks of less than 68 octets.
By standard, 576 Bytes is "minimum MTU" supported over IP infrastructure. This means, any host/router must support this value and any IP packets can be smaller than 576 Bytes (atleast 68 Bytes) which can move IP world without fragmentation.
HTH
The first relates to accepting; the second relates to forwarding.
then it is possible to have a router not being able to receive a packet of 68 bytes for himself
That doesn't make any sense. A host must be able to accept datagrams of up to 576 octets.

UDP Networking Fundamentals

I've been doing some work with C# Networking using UDP. I'm getting on fine but need the answer to a couple of fundamental questions I'm having problems testing:
Currently I'm sending data in a ~16000 byte datagrams, which according to wireshark is getting split into several 1500 byte packets (because of max packet size limits) and then reassembled at the other end.
Am I right in understanding the datagram will be received complete at the other end OR not at all. IE it's an all or nothing thing. There is no chance of ending up with a fragmented datagram due to packet loss?
Therefore, I only need to ACK per datagram, rather than ensuring my datagrams are < 1500 bytes and ACK each one?
I've looked in a lot of places but there seems to be a lot of confusion between the differences between datagrams and the underlying packets...
Thanks for you help!
There is no chance of ending up with a fragmented datagram due to packet loss?
I believe that's true: that fragmentation and fragment reassembly is handled by the protocol layer below UDP, i.e. that it's handled by the "IP" layer, which will error if it fails to reassemble the packet-fragments into a datagram (for example, search for "fragment" in RFC 792).
http://www.pcvr.nl/tcpip/udp_user.htm#11_5 says,
"The IP layer at the destination performs the reassembly. The goal is to make fragmentation and reassembly transparent to the transport layer (TCP and UDP), which it is, except for possible performance degradation."
As you may now 16 bit UDP length field indicates that you can send a total of 65535 bytes. However, the data can be theoretically (sizeof(IP Header) + sizeof(UDP Header)) = 65535-(20+8) = 65507 bytes.
But this does not mean that all applications that are using UDP will send this amount of data as an example DNS packets limits to 512 bytes. This is because you don't get any ACK packets from server. This is one reason that packets may get lost in the network (packet transmission problems and loss). Secondly intermediate nodes may encapsulate datagrams inside of another protocol, as an example IPSEC or other protocols do that.
For UDP there is no ACK packets, so in your case if underlying application uses UDP you should not see any ACK packets. Secondly, some of the server limit their sizes to the max UDP packets depending on the application, so if you have data transfer from client to server you should see same bytes e.g 512 bytes. going and coming back in wireshark. Mostly, source makes the request and destination sends X bytes UDP datagrams back.
These links may be good for your questions:
Wireshark UDP analysis
RFC 1122 (states that 576 is the minimum maximum reassembly buffer size)
Am I right in understanding the datagram will be received complete at the other end OR not at all. IE it's an all or nothing thing. There is no chance of ending up with a fragmented datagram due to packet loss?
That is correct.
Therefore, I only need to ACK per datagram, rather than ensuring my datagrams are < 1500 bytes and ACK each one?
I don't understand this question. You need to ACK each datagram regardless of its size, and you should make them < 1500 bytes so they won't get fragmented. Otherwise you may never be able to transmit any specific datagrams at all, if it repeatedly gets fragmented and a fragment repeatedly gets lost.

Send large data on UDP socket

I need to send and receive very large data using udp. Unfortunately udp provides 8192 bytes per diagram, so there is need to divide data into smaller pieces.
I'm using Qt and QUdpSocket. There is a QByteArray with length of 921600 I want to send to client. I want to send 8192 bytes each time.
What is the fast way to split a QByteArray?
You should never need to explicitly split the data, just step through it 8 KB at a time. Typically the functions that write data to a socket (including QUdpSocket::writeDatagram, it seems) accept a pointer to the first byte and a byte count, so you can just provide a pointer into the array.
Do note that sending 8 KB datagrams is quite aggressive; they will very likely be fragmented at the IP layer which can affect delivery speed and reliability negatively.
Research the concept of "path MTU", and try to use that for the sends, it might be faster although it will result in more datagrams.
Actually the length field on a UDP header is 16 bits so a UDP datagram can be up to ~65k (minus the size of the header stuff).
However, as unwind pointed out, it will most likely be fragmented along the way to fit the smallest MTU on the path to the destination.
8192 bytes is the default receive buffer size for Windows operating systems. The MTU is likely 1500 bytes if you are using Ethernet. Any UDP datagram larger than that will be fragmented. If your datagram encounters a device along the route with an even smaller MTU, it will be fragmented yet again.
You can use the QByteArray.mid(int start, int len) method (see documentation here) to get a QByteArray of length len starting from start.
Just make len your datagram size and start with 0*len, 1*len, 2*len, ... until everything is sent.

Resources