U-Boot TFTP Block Negotiation: Inspect the Request, Cap and Server Reply

Setting tftpblocksize does not prove that a transfer
used that block size. U-Boot can cap the requested value before sending
it, and the server can negotiate a smaller one. A network-path
investigation should capture those transitions instead of comparing
environment strings alone.

This article follows the IPv4 client in U-Boot v2025.01’s
net/tftp.c, as selected by a product’s bootloader
configuration, including a Buildroot build. It excludes the lwIP
implementation, IPv6-specific limits and malformed-option security
analysis. Downloads and uploads have different capacity rules in this
path.

Keep three block sizes
in the evidence

The implementation stores the option it wants to request separately
from the active transfer block size. The requested value starts from
CONFIG_TFTP_BLOCKSIZE; when
CONFIG_NET_TFTP_VARS is enabled, tftpblocksize
can replace it using decimal parsing. The active transfer size is reset
to 512 bytes at transfer start. Tagged
TFTP implementation
.

Before building the request, U-Boot sanitizes the requested size.
Consequently, the environment value, transmitted blksize
option and negotiated transfer size are three distinct observations.
Logging only the first cannot explain the packets on the wire.

The build default for the requested option is 1468. This corresponds
to a 1500-byte IPv4 packet after subtracting 20 bytes for the IPv4
header, 8 for UDP and 4 for TFTP, assuming the ordinary header sizes
used here. The block-size option itself counts data bytes, not those
protocol headers. Network
configuration
, RFC
2348 block-size definition
.

Configured TFTP request passes through local capacity limits and server negotiation before becoming the active block size.

Apply the
receive and transmit limits separately

For a download with IP defragmentation enabled,
sanitize_tftp_block_size_option() derives the cap from
CONFIG_NET_MAXDEFRAG minus 32 bytes, with an additional
upper limit of 65464. The reassembly configuration describes a
statically allocated receive buffer; its capacity is not a statement
about every network path.

Without receive defragmentation, the download request is capped at
1468. Uploads also use that cap because this implementation does not
provide outgoing IP fragmentation. Increasing the configured receive
reassembly buffer therefore does not enable equivalently large upload
blocks. Sanitization
logic
, reassembly-buffer
configuration
.

A local cap is not path-MTU discovery. A tunnel or another lower-MTU
segment can still make the usual Ethernet assumption inappropriate. If a
transfer works on a direct link but fails across another path, inspect
packet sizes and fragmentation evidence before assigning the fault to a
missing file or an application timeout.

Read
the server’s negotiation rather than assuming acceptance

RFC 2348 permits the server’s option acknowledgment to choose a block
size no larger than the client’s request. U-Boot’s OACK handler reads
the returned blksize and marks the option invalid if it
exceeds the requested option. If the server instead starts sending data
without acknowledging options, the default active size remains 512 in
this path. RFC
negotiation rules
, OACK
and first-data handling
.

For a source-derived example, an environment request larger than 1468
on a download build without defragmentation is reduced before
transmission. A server may then accept that reduced size, choose a
smaller one or omit negotiation. These outcomes can produce different
packet patterns from the same saved environment value. No transfer was
executed for this example.

Window negotiation is another independent variable. This source sends
a windowsize option only for read requests and only when
the requested window exceeds one. Do not infer upload window support
from a similarly named setting or from generic TFTP descriptions.

Use one-variable network
comparisons

A useful proposed capture records the build’s stack and reassembly
options, the requested environment value, the outbound request, the
server’s reply and the subsequent data lengths. Compare the same
artifact and server across the two paths. Then vary block size while
holding the requested window fixed; investigate windowing
separately.

Retain transfer completion and content verification as separate
outcomes from negotiation. A smaller block that completes is evidence
about that fixture, not a universal optimum or a measured throughput
improvement. The purpose is to locate the disagreement between local
capacity, negotiated behavior and the actual network path.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *