Why does a BPF LPM-trie lookup return a less specific stored prefix, and how does the key prefixlen field decide which entry wins?
Short answer: Set the lookup key prefixlen to the map's maximum prefix length (32 for a 4-byte IPv4 data field, 128 for a 16-byte IPv6 field). The kernel caps the match at min(node->prefixlen, key->prefixlen) (kernel/bpf/lpm_trie.c), so a lookup key carrying a smaller prefixlen tells the walk it may match no more bits than that, and the lookup stops at — or falls back to — a less specific stored entry even when a more specific one also matches. The kernel doc states the rule plainly: for a longest-prefix lookup, key->prefixlen should equal max_prefixlen. A lookup key whose prefixlen exceeds the map maximum returns NULL (while update/delete return -EINVAL), and intermediate nodes never carry a value.
How a lookup walks the trie
trie_lookup_elem walks from the root node. Each node holds its prefixlen and its data (stored big-endian, data[0] most-significant), and two child pointers lead to more specific matches. At each node:
__longest_prefix_matchcounts how many leading bits of the node agree with the key, but the count is capped atlimit = min(node->prefixlen, key->prefixlen)(line 172). The compare runs over 64/32/16/8-bit big-endian chunks (be64_to_cpu,be32_to_cpu, …), so a key'sdatabyte 0 is the MSB.- If the match reaches the map's maximum prefix (
matchlen == trie->max_prefixlen), that node is a full-length exact match and is returned immediately (lines 258–262); this fires only when a stored prefix of the maximum length (e.g. a /32) matches the key. - If the match is shorter than the node's own
prefixlen(matchlen < node->prefixlen, lines 268–269), the walk breaks and the last non-intermediate node it has seen is returned — the longest stored prefix that fully matched on the path so far. - A node flagged
LPM_TREE_NODE_FLAG_IMis an artificial intermediate node with no value; it is never returned and exists only so two more specific children can share a parent (lines 271–275). - Otherwise the last-visited value-carrying node becomes the candidate, and the next bit of the key (
extract_bit(key->data, node->prefixlen)) selects which child to descend into (lines 281–283).
max_prefixlen is data_size * 8 bits (line 596) — 8× the key's data length, so 32 for a 4-byte key and 128 for a 16-byte key.
Why the lookup key prefixlen caps the match
The cap is limit = min(node->prefixlen, key->prefixlen). __longest_prefix_match returns as soon as its running count reaches limit (each chunk ends in if (prefixlen >= limit) return limit;). The walk is therefore told that the key matches at most key->prefixlen bits, no matter how many more matching bits actually exist in a more specific node.
Worked example, using the doc's own numbers: store 192.168.0.0/16 value 1 and 192.168.0.0/24 value 2. The /24 is a more specific prefix on the same path, so it is attached directly as child[0] of the /16 (no intermediate node is needed until two more specific children of the same bit range have to share a parent, as in the doc's 192.168.1.0/24 / 192.168.128.0/24 split through a /23).
- Lookup
192.168.0.5withprefixlen = 32: the walk descends to the /24 node, whose ownprefixlenis 24; the match reaches the node's 24 bits, the node is the last value-carrying node on the path, and there is no deeper child to descend into — so the /24 is returned, value 2, the longest stored match. (The exact-match branch only fires if a stored prefix of the full 32-bit length, a /32, matched the key.) - Lookup
192.168.0.5withprefixlen = 16: the walk reaches the /24 node, but the match is capped at 16; nowmatchlen (16) < node->prefixlen (24), so the walk breaks and returns the last found node — the /16, value 1. The more specific /24 entry is skipped silently. - Lookup with
prefixlen = 33(above the 32 maximum):trie_lookup_elemreturnsNULLat line 244;update/deletereturn-EINVAL(lines 338, 469).
The doc's one-line rule: "The key should have prefixlen set to max_prefixlen when performing longest prefix lookups."
The corners that are not safe
- A lookup with a
prefixlenbelow the map maximum caps the result. Capping the key at a stored prefix's length makes the trie stop at the longest uncapped match, so a more specific stored prefix can be bypassed. Always pass the maximum (32/128). prefixlenabove the map maximum is a no-match, not an error, on lookup. The lookup returnsNULL(line 244); onlyupdate/deletesurface it as-EINVAL.- Key data is big-endian. The compare is
be32_to_cpuover the stored and lookup arrays anddata[0]is the MSB; a little-endian host that stores the address as a native integer will misroute. The canonical key struct isstruct bpf_lpm_trie_key_u8(prefixlen+ flexibledata[]); the olderstruct bpf_lpm_trie_keyis deprecated. - Intermediate nodes carry no value. They are internal structural nodes (the
LPM_TREE_NODE_FLAG_IMbit) and are never returned; a trie with many splits returns the closest non-intermediate ancestor's value even when only the leaf holds a value. - The map must be created with
BPF_F_NO_PREALLOC. The kernel doc requires the flag; the maximum prefix length is a multiple of 8 in the range 8 to 2048 bits (LPM_DATA_SIZE_MAXis 256 bytes, line 557).
How to verify it
- Exact match wins. Store
192.168.0.0/16(value 1) and192.168.0.0/24(value 2).bpf_map_lookup_elemwith key192.168.0.5andprefixlen = 32returns value 2. - The cap. Same two entries; key
192.168.0.5withprefixlen = 16returns value 1 — the /24 is skipped because the match is capped at 16. - Above max. Key
prefixlen = 33makes the lookup returnNULL;bpf_map_update_elem/bpf_map_delete_elemreturn-EINVAL. - Iteration order.
bpf_map_get_next_keywalks leftmost-leaf-first, so more specific keys come before less specific ones; passNULLfor the first call. The upstream selftesttools/testing/selftests/bpf/test_lpm_map.cexercises these paths.
Where the answer stops
- This is about lookup semantics: storage is unaffected — a stored /24 is still there and reachable by a correctly-capped lookup. The cap only limits how many bits the lookup is allowed to match.
- The trie is unbalanced; a fully-populated IPv4 trie has height 32 (one level per bit). The cap is a bound on the match a given lookup can express, not a storage-correctness bug.
- Other map types have no notion of a prefix; this boundary is specific to
BPF_MAP_TYPE_LPM_TRIE.
References
- BPF_MAP_TYPE_LPM_TRIE (kernel docs) — the
prefixlen/max_prefixlenrule, big-endiandata, theBPF_F_NO_PREALLOCrequirement, thebpf_map_lookup_elem/update/delete/get_next_keycontracts, IPv4/IPv6 data lengths, the192.168.0.0worked example, and the selftest pointer. - kernel/bpf/lpm_trie.c —
trie_lookup_elem(the walk, thematchlencap, the intermediate-node flag);__longest_prefix_match(limit = min(node->prefixlen, key->prefixlen)at line 172, big-endian word compare);trie->max_prefixlen = trie->data_size * 8(line 596);LPM_DATA_SIZE_MAX 256(line 557); thekey->prefixlen > max_prefixlenguards (lines 244, 338, 469). - include/uapi/linux/bpf.h —
struct bpf_lpm_trie_key(deprecated),struct bpf_lpm_trie_key_hdr, andstruct bpf_lpm_trie_key_u8;BPF_MAP_TYPE_LPM_TRIEinenum bpf_map_type.
Community discussion today
Honest coverage note: the two watchlist-opted Slack archives were inaccessible this run — the read-only snapshot reader refused to overwrite a pre-existing 0-byte snapshot file, so the Step 0 snapshot returned output_exists and no archive content was read. The allowlisted Discord channels and public lists remain visible-browser-only, with no visible-browser session available in this run — so no private community material was available for 2026-09-24. The question above is the fallback selection: a genuine, recurring practitioner boundary of the monitored eBPF development community, grounded entirely in the public primary sources above (kernel BPF docs and upstream source) rather than in any thread.
The recurring practitioner theme in that space — building a CIDR/route table in an XDP or TC datapath and asking why the less specific route wins — resolves to exactly this boundary: the lookup key prefixlen caps the longest-prefix match, and the doc's rule is to set it to max_prefixlen (32 for IPv4, 128 for IPv6) so the more specific stored prefix actually wins. Two public-doc-anchored follow-ups recur here. First, the big-endian surprise: the data array is interpreted in network byte order, so a host that stores the address as a native little-endian integer silently misroutes, and people misread it as "the prefix did not match" when it is a byte-order bug. Second, the above-maximum corner: passing a prefixlen above the map's maximum makes the lookup return NULL (not an error), which reads as "no match" when it is a key-shape bug, while update/delete return -EINVAL on the same out-of-range value, so the two paths disagree on the identical key.
Continue exploring
Back to index
eBPF Q&A
Daily, source-grounded answers to recurring questions about eBPF, Linux observability, profiling, runtime extension, and security.
Previous
Does deleting a key from a BPF hash map zero out the value memory, and can a reused slot still hold the old value bytes?
Short answer: No. bpfmapdeleteelem unlinks the element from the hash buckets and hands its memory back to the per-CPU freelist (preallocated hash) or to the RCU-deferred BPF allocator (a BPFFNOPREALLOC hash); it does
Next
Why does a full BPF hash map reject new keys with E2BIG, while updating an existing key still succeed?
Short answer: For BPFMAPTYPEHASH, maxentries is a hard cap on distinct keys, and the cap is enforced at element allocation time: a new key needs a fresh element, and when no element is available the update returns E2BIG
- Last updated
- Sep 24, 2026
- First published
- Sep 24, 2026
- Contributors
- Yunwei 123
Was this page helpful?