|WARNING| examples/l3fwd: dynamic NUMA-aware alloc lcore_conf
dpdklab at iol.unh.edu
dpdklab at iol.unh.edu
Wed Jul 15 12:21:11 CEST 2026
Test-Label: ai-code-review
Test-Status: WARNING
https://dpdk.org/patch/166736
_AI Code Review_
=== Patch Review: series.patch (via Claude) ===
Review date: 2026-07-15
# Review of DPDK Patch: l3fwd NUMA-aware lcore_conf allocation
## Errors
### 1. Resource leak on lcore initialization failure
In `init_lcore_conf()`, if allocation fails partway through the loop, previously allocated lcore_conf entries are not freed before returning -ENOMEM. The cleanup section only frees entries where `lcore_conf[lcore_id] != NULL`, but if the allocation that triggers the goto fails, the cleanup runs correctly. However, there is a logical issue: the function goes to cleanup but doesn't actually reach it on the first failure.
**Wait - let me re-check this.** Looking at the code:
```c
lcore_conf[lcore_id] = rte_zmalloc_socket(...);
if (lcore_conf[lcore_id] == NULL)
goto cleanup;
```
If the allocation fails, `lcore_conf[lcore_id]` is NULL, then we goto cleanup. The cleanup loop checks `if (lcore_conf[lcore_id] != NULL)` before freeing, so it will skip the failed entry and free all previously successful allocations. This is actually correct. No issue here.
### 2. Missing cleanup on application exit
The allocated `lcore_conf` entries are never freed in the normal exit path or signal handler. While this is typically acceptable for an application that runs until terminated, it prevents clean shutdown and causes memory leak reports from tools like valgrind or ASAN.
**Suggested fix:** Add cleanup before `rte_eal_cleanup()`:
```c
/* Before rte_eal_cleanup() in main() */
for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
if (lcore_conf[lcore_id] != NULL) {
rte_free(lcore_conf[lcore_id]);
lcore_conf[lcore_id] = NULL;
}
}
```
## Warnings
### 1. Missing validation of lcore_conf pointer before use
Throughout the codebase (all modified files), the code now dereferences `lcore_conf[lcore_id]` without checking if it's NULL. While enabled lcores should always have valid entries after `init_lcore_conf()`, defensive programming suggests checking the pointer, especially in a refactoring that changes from static array to dynamic allocation.
**Suggested fix:** Add NULL checks in functions that access lcore_conf:
```c
qconf = lcore_conf[lcore_id];
if (qconf == NULL)
rte_exit(EXIT_FAILURE, "lcore_conf not initialized for lcore %u\n", lcore_id);
```
### 2. Potential initialization order issue
`init_lcore_conf()` is called after argument parsing but before `check_lcore_params()` and `check_port_config()`. If these validation functions find errors and exit, the allocated memory is leaked. While the application exits anyway, it's cleaner to allocate after validation passes.
**Suggested fix:** Move `init_lcore_conf()` call after `check_lcore_params()` and before `l3fwd_poll_resource_setup()` or `l3fwd_event_resource_setup()`.
### 3. Inconsistent NULL initialization
In `init_lcore_conf()` cleanup path, `lcore_conf[lcore_id] = NULL` is redundant since the array is already zero-initialized (global variable). However, this is not an error - explicit NULL assignment after free is good defensive programming and prevents use-after-free bugs.
## Info
### 1. Code structure observation
The refactoring correctly changes all accesses from `lcore_conf[lcore_id].member` to `lcore_conf[lcore_id]->member`, maintaining consistency across all 6 modified files.
### 2. NUMA-aware allocation rationale
The commit message states `sizeof(struct lcore_conf)` is 133760 bytes on Kunpeng, justifying the NUMA-aware allocation. This is good documentation of the performance motivation.
### 3. Socket ID handling
The code correctly uses `rte_lcore_to_socket_id(lcore_id)` when `numa_on` is true, and falls back to socket 0 otherwise. This matches the existing pattern in `init_mem()`.
---
## Summary
**Critical issue:** Missing cleanup of allocated lcore_conf entries on normal application exit (resource leak on shutdown).
**Recommended fixes:**
1. Add lcore_conf cleanup before `rte_eal_cleanup()` in main()
2. Consider adding NULL pointer checks when dereferencing lcore_conf entries (defensive programming)
3. Consider moving `init_lcore_conf()` after parameter validation to avoid leaks on early exit
The patch correctly implements per-lcore NUMA-aware allocation and consistently updates all access patterns. The main concern is proper resource cleanup on exit paths.
More information about the test-report
mailing list