|WARNING| [v3] net/af_packet: add option to ignore outgoing packets
dpdklab at iol.unh.edu
dpdklab at iol.unh.edu
Tue Oct 6 09:09:49 CEST 2026
Test-Label: ai-code-review
Test-Status: WARNING
https://dpdk.org/patch/170643
_AI Code Review_
=== Patch Review: series.patch (via Claude) ===
Review date: 2026-10-06
# DPDK Patch Review
## Summary
This patch adds an `ignore_outgoing` devarg to the AF_PACKET PMD to control whether the socket receives packets transmitted by the host. Overall implementation is correct, but there are several minor issues to address.
---
## Errors
None.
---
## Warnings
### 1. Test cleanup on early failure paths
**File:** `app/test/test_pmd_af_packet.c:933-938`
The test creates `rx_port_ign_out_on` but if creation of `rx_port_ign_out_off` fails, the error path `fail_rx_ign_off` does not clean up `rx_port_ign_out_on` before jumping to `fail_rx_ign_on`. The cleanup sequence is correct for successful creation but incomplete for early failure.
**Suggested fix:**
```c
ret = create_af_packet_port("net_af_packet_ign_off",
"iface=" TAP_DEV_NAME ",ignore_outgoing=0",
&rx_port_ign_out_off);
if (ret != 0) {
err = "Failed to create ignore_outgoing=0 port";
/* Need to clean up rx_port_ign_out_on first */
rte_eth_dev_stop(rx_port_ign_out_on);
rte_eth_dev_close(rx_port_ign_out_on);
rte_vdev_uninit("net_af_packet_ign_on");
goto fail_rx_ign_on;
}
```
### 2. Test does not free received mbufs
**File:** `app/test/test_pmd_af_packet.c:967-970`
The test calls `do_rx_burst()` to receive packets but never frees the mbufs placed in `bufs[]`. This leaks memory from the mempool.
**Suggested fix:**
```c
while (elapsed < LOOPBACK_TIMEOUT_US) {
uint16_t n_off = do_rx_burst(rx_port_ign_out_off, 0, bufs, BURST_SIZE);
if (n_off > 0) {
rx_off += n_off;
rte_pktmbuf_free_bulk(bufs, n_off);
}
uint16_t n_on = do_rx_burst(rx_port_ign_out_on, 0, bufs, BURST_SIZE);
if (n_on > 0) {
rx_on += n_on;
rte_pktmbuf_free_bulk(bufs, n_on);
}
if (rx_off >= nb_tx)
break;
rte_delay_us_block(STATS_POLL_INTERVAL_US);
elapsed += STATS_POLL_INTERVAL_US;
}
```
Also free any packets received during the drain phase (lines 955-956):
```c
uint16_t n;
while ((n = do_rx_burst(rx_port_ign_out_off, 0, bufs, BURST_SIZE)) > 0)
rte_pktmbuf_free_bulk(bufs, n);
while ((n = do_rx_burst(rx_port_ign_out_on, 0, bufs, BURST_SIZE)) > 0)
rte_pktmbuf_free_bulk(bufs, n);
```
### 3. Missing bounds check on `ignore_outgoing` devarg
**File:** `drivers/net/af_packet/rte_eth_af_packet.c:1290-1293`
The patch parses `ignore_outgoing` with `parse_uint(..., 1)` which limits the value to 1, but the test at line 1093 verifies that `ignore_outgoing=2` fails. However, the actual validation happens inside `parse_uint()` (checking `max` parameter), so the implementation is correct. The test properly exercises the bounds check.
Actually correct -- no issue here.
### 4. Unclear test assertion logic
**File:** `app/test/test_pmd_af_packet.c:989-991`
The `TEST_ASSERT` calls at the end of `test_af_packet_ignore_outgoing()` will always be reached because earlier `goto fail_setup` jumps skip them. This is correct -- the assertions verify the results after all cleanup is done. The pattern is intentional.
Actually correct -- no issue here.
---
## Info
### 1. Test suite organization
**File:** `app/test/test_pmd_af_packet.c:1206`
The new test is added immediately after `test_af_packet_qdisc_bypass`, which is a good logical grouping since both test socket-level options.
### 2. Documentation completeness
The documentation in `af_packet.rst` and release notes clearly describes the new option. The release notes appropriately mention this is a PMD update, not a library or API change.
### 3. Consistent naming
The devarg name `ignore_outgoing` matches the kernel socket option name `PACKET_IGNORE_OUTGOING`, making the mapping obvious.
---
## Correctness Check Summary
**Use-after-free:** None detected.
**Resource leaks:**
- Test code leaks mbufs received during RX burst (Warning #2).
- Test cleanup path incomplete for early failure (Warning #1).
**Error handling:** Socket option error handling is correct -- the code checks `setsockopt()` return value and propagates errors.
**Bounds checking:** The `parse_uint(..., 1)` call correctly limits `ignore_outgoing` to 0 or 1.
More information about the test-report
mailing list