Jason, TCP does break up most of the data on the sending host.
For example. If a server wanted to send 64K of data to a client, it would hand that 64K down to TCP. TCP would look at the MTU for the network connection to determine the Maximum Segment Size (MSS). The MSS is the maximum amount of data that can be put into a frame. On a typical Ethernet connection the calculation is as follows:
Maximum Frame size for Ethernet = 1518 Bytes
Ethernet Header = 18 Bytes
IP Header = 20 Bytes
TCP Header = 20 Bytes
1518 - 18 - 20 - 20 = 1460 (The MSS for most connections)
TCP will split that 64K up into 1460 byte chunks and send them to the client, who will based on sequence numbers in the TCP header, reassemble the data and hand the upper layer the original 64K data block.
Microsoft will typically set the Do Not Fragment Bit in the Flags section of the IP header. This tells all intermediate layer 3 devices not to fragment these frames. Instead any layer 3 device that needs to fragment the frame will send an ICMP Destination Unreachable message back to the sending device. This message will contain the MTU for the circuit that caused fragmentation.
The sending device will then set the MTU for that connection to the MTU contained in the ICMP error message. This MTU is valid only for that one detination IP address, the information is stored in the sender's routing table.
This is a good process, since firewalls don't typically reassemble IP fragments. As a result, they my pass the fragment that contains the original TCP header, but discard the rest of the fragments.
As a note, the amount of data placed in the TCP data portion of the frame is based on the advertised MSS of the receiving device. If the sender has a MSS of 1460 and the receiver has an MSS of 300, only 300 bytes will be placed in the data portion by the sender.
NFS was an example of a protocol that let IP do the fragmentation. NFS would hand 8K down to the IP layer and let IP break it up into fragments that meet the size of the MTU.
Mike