|WARNING| net/ring: remove internal devarg

dpdklab at iol.unh.edu dpdklab at iol.unh.edu
Tue Sep 22 14:11:51 CEST 2026


Test-Label: ai-code-review
Test-Status: WARNING
https://dpdk.org/patch/169914

_AI Code Review_

=== Patch Review: series.patch (via Claude) ===
Review date: 2026-09-22

# DPDK Patch Review

## Patch Summary
The patch removes the "internal" devarg from the ring PMD by using a per-thread global variable instead of passing a pointer via devargs. This prevents users from accidentally setting the "internal" devarg on the command line.

---

## Errors

### 1. Race Condition on Shared Global Variable

**Location:** `rte_eth_from_rings()` function

The patch introduces a per-thread global `RTE_PER_LCORE(eth_ring_internal_args)` but does not prevent concurrent calls to `rte_eth_from_rings()` from the same thread. If `rte_vdev_init()` triggers recursive calls or if an error callback invokes `rte_eth_from_rings()` again, the global will be overwritten mid-execution.

```c
/* Current code - vulnerable to reentrancy */
RTE_PER_LCORE(eth_ring_internal_args) = &args;
ret = rte_vdev_init(ring_name, NULL);
RTE_PER_LCORE(eth_ring_internal_args) = NULL;
```

**Suggested fix:** Document that `rte_eth_from_rings()` is not reentrant, or add a state check:

```c
if (RTE_PER_LCORE(eth_ring_internal_args) != NULL) {
	PMD_LOG(ERR, "Concurrent calls to rte_eth_from_rings() not supported");
	rte_errno = EBUSY;
	return -1;
}
RTE_PER_LCORE(eth_ring_internal_args) = &args;
ret = rte_vdev_init(ring_name, NULL);
RTE_PER_LCORE(eth_ring_internal_args) = NULL;
```

### 2. Global Not Cleared on Error Path

**Location:** `rte_eth_from_rings()` function

If `rte_vdev_init()` fails (returns non-zero), the function returns without clearing `RTE_PER_LCORE(eth_ring_internal_args)`. A subsequent successful call to `rte_eth_from_rings()` will incorrectly see a stale pointer.

```c
/* BAD - global not cleared if rte_vdev_init fails */
RTE_PER_LCORE(eth_ring_internal_args) = &args;
ret = rte_vdev_init(ring_name, NULL);
RTE_PER_LCORE(eth_ring_internal_args) = NULL;  /* not reached if ret != 0 */
if (ret) {
	rte_errno = EINVAL;
	return -1;
}
```

**Suggested fix:** Clear the global before checking the return value:

```c
RTE_PER_LCORE(eth_ring_internal_args) = &args;
ret = rte_vdev_init(ring_name, NULL);
RTE_PER_LCORE(eth_ring_internal_args) = NULL;  /* always clear */
if (ret) {
	rte_errno = EINVAL;
	return -1;
}
```

---

## Warnings

### 1. Removed Devarg Still in valid_arguments Array

**Location:** `valid_arguments[]` array

The patch removes `ETH_RING_INTERNAL_ARG` handling but does not remove it from the `valid_arguments` array. Users can still pass `internal=...` on the command line without a validation error, though it will be silently ignored.

**Current code:**
```c
static const char *valid_arguments[] = {
	ETH_RING_NUMA_NODE_ACTION_ARG,
	/* ETH_RING_INTERNAL_ARG removed from handling but still here? */
	NULL
};
```

**Suggested fix:** Verify that `ETH_RING_INTERNAL_ARG` is not present in `valid_arguments` after the patch (cannot see the full array definition in the diff, but the commit message implies it should be removed).

### 2. Missing Release Notes

This patch fixes a bug (Bugzilla ID 1687) that changes user-visible behavior (removing a devarg). The release notes should document this change so users know the "internal" devarg is no longer accepted.

**Suggested action:** Add an entry to the current release notes under "Removed Items" or "API Changes" noting that the `internal` devarg for `net_ring` has been removed.

---

## Info

### 1. Code Simplification Achieved

The patch successfully eliminates the `parse_internal_args()` function and its associated string parsing, replacing it with direct pointer passing via TLS. This is cleaner and removes the possibility of user misuse. The approach is appropriate for the stated goal.

### 2. Alternative Design Consideration

An alternative would be to use a mutex-protected global or a registration mechanism, but for the ring PMD's use case (single-threaded device creation is the common case), the per-thread global is a reasonable choice with acceptable trade-offs.

---

## Summary

**Critical issues:** 2 Errors (reentrancy vulnerability, error path leak)  
**Important issues:** 2 Warnings (devarg validation, release notes)  

The patch concept is sound, but the per-thread global implementation has an error path bug that will cause stale pointer issues on retry, and a potential reentrancy problem if `rte_vdev_init()` callbacks can recursively invoke `rte_eth_from_rings()`.


More information about the test-report mailing list