Maintain some "TSO potential" state during segmentation at sendmsg()/sendpage() time. Use this at push-pending-frames time to defer tcp_write_xmit() calls and control it's behavior. Add tcp_flush_queue() which doesn't try to optimize TSO, it is invoked when getting packets out is more important than producing larger TSO chunks. These two cases are: 1) At end of sendmsg()/sendpage() call without MSG_MORE, indicating that we have no way to know for sure if the user will queue up more TCP data to send. 2) When sleeping within sendmsg()/sendpage() waiting for memory. Pushing out packets and receiving the ACKs may very well be the event that will free up send queue space for us. (Must consider interactions with Nagle and Minshall rules) Consider tcp_opt state which keeps a "TSO goal", it must be in sync with tcp_opt MSS state. Initially define "TSO goal" using tcp_tso_win_divisor and the current congestion window. Formally this is: max(1U, CWND / TCP_TSO_WIN_DIVISOR) We could either maintain this lazily, costing us a divide each time it is recalculated. Or, we can update it incrementally each time snd_cwnd is updated. To save some state testing during output decisions, define "TSO goal" as one for non-TSO flows. Possible send test logic: if (no new data possibly coming from user) send_now(); if (sending due to ACK queue advancement) send_now(); send_tso_goal_sized_chunks();