|WARNING| [v2] net/txgbe: keep flow rules per port

dpdklab at iol.unh.edu dpdklab at iol.unh.edu
Mon Nov 9 15:22:50 CET 2026


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

_AI Code Review_

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

# DPDK Patch Review

## ERRORS

**1. Use-after-free in txgbe_filterlist_flush()**

Line in drivers/net/txgbe/txgbe_flow.c:
```c
TAILQ_REMOVE(&adapter->flow_list, txgbe_flow_mem_ptr, entries);
rte_free(flow->rule);
rte_free(flow);
rte_free(txgbe_flow_mem_ptr);
```

After `rte_free(flow)`, the pointer `flow` is freed. However, `flow` was assigned from `txgbe_flow_mem_ptr->flow` at the start of the loop iteration. The code accesses `flow->rule` after `flow` has been potentially freed if `flow` and `txgbe_flow_mem_ptr->flow` point to the same memory.

**Suggested fix:**
```c
struct rte_flow *flow = txgbe_flow_mem_ptr->flow;
void *rule = flow->rule;

TAILQ_REMOVE(&adapter->flow_list, txgbe_flow_mem_ptr, entries);
rte_free(rule);
rte_free(flow);
rte_free(txgbe_flow_mem_ptr);
```

**2. Resource leak in txgbe_flow_create() error path**

Line in drivers/net/txgbe/txgbe_flow.c:
```c
out:
	TAILQ_REMOVE(&adapter->flow_list, txgbe_flow_mem_ptr, entries);
	rte_flow_error_set(error, -ret,
			   RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
			   "Failed to create flow.");
	rte_free(txgbe_flow_mem_ptr);
	return NULL;
```

The error path frees `txgbe_flow_mem_ptr` but does not free `flow` (allocated at the start of `txgbe_flow_create()`). This leaks the `flow` allocation on every error after the initial allocation succeeds.

**Suggested fix:**
```c
out:
	TAILQ_REMOVE(&adapter->flow_list, txgbe_flow_mem_ptr, entries);
	rte_flow_error_set(error, -ret,
			   RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
			   "Failed to create flow.");
	rte_free(flow);
	rte_free(txgbe_flow_mem_ptr);
	return NULL;
```

**3. Resource leak in txgbe_flow_create() fdir_out path**

Line in drivers/net/txgbe/txgbe_flow.c:
```c
fdir_out:
	rte_free(fdir_rule_ptr);
	if (!fdir_configured) {
		fdir_info->mask_added = false;
		fdir_conf->mode = RTE_FDIR_MODE_NONE;
	}
	goto out;
```

The `fdir_out` label frees `fdir_rule_ptr` and then jumps to `out`, but `out` does not know that `fdir_rule_ptr` was the rule being created. If any filter type allocated its rule pointer and stored it in `flow->rule` before jumping to an error path, that pointer is leaked because `out` does not free `flow->rule`.

However, examining the code more carefully: at the point where `goto fdir_out` occurs, `flow->rule` has not yet been assigned (the assignment `flow->rule = fdir_rule_ptr;` comes after the successful creation). So `flow->rule` is uninitialized or NULL. The `out` path should handle this by freeing `flow->rule` only if it was set, or the code should ensure `flow` is properly initialized.

Since the code does not initialize `flow` members to NULL after allocation, `flow->rule` contains garbage. The `out` path does not attempt to free `flow->rule`, so there's no double-free here, but the pattern is fragile.

**Suggested fix:** Initialize `flow` after allocation:
```c
flow = rte_zmalloc("txgbe_rte_flow", sizeof(struct rte_flow), 0);
```
This ensures `flow->rule` is NULL if an error occurs before it's assigned.

---

## WARNINGS

**1. Inconsistent FDIR disable check**

Line in drivers/net/txgbe/txgbe_flow.c:
```c
if (TAILQ_EMPTY(&fdir_info->fdir_list)) {
```

The patch changes the flow list from a global `filter_fdir_list` to a per-adapter list. However, the FDIR disable check uses `fdir_info->fdir_list` (which is the FDIR-specific list maintained separately in `struct txgbe_filter_info`), not the new per-adapter `flow_list`.

This is likely correct behavior (the FDIR subsystem should be disabled when its own list is empty), but the commit message says "A port disables flow director only when its own FDIR filter list is empty" and the v2 note says "A successful delete already updates the per-port FDIR filter list, so test that list instead."

However, the code does not appear to update `fdir_info->fdir_list` in the modified `txgbe_flow_destroy()` -- it only frees `fdir_rule_ptr` and removes from `adapter->flow_list`. The underlying `txgbe_fdir_filter_program()` call may update `fdir_info->fdir_list`, but this should be verified.

If `txgbe_fdir_filter_program()` does not maintain `fdir_info->fdir_list`, then the check `TAILQ_EMPTY(&fdir_info->fdir_list)` will never become true and FDIR will never be disabled.

**Suggested verification:** Ensure that `txgbe_fdir_filter_program(dev, &fdir_rule, TRUE, FALSE)` removes the filter from `fdir_info->fdir_list`. If it does not, the FDIR disable logic is broken.

**2. Missing release notes**

This patch fixes a significant bug (flow rules were being shared across ports and destroyed incorrectly) and changes internal data structure layout. While it's marked with `Fixes:` and `Cc: stable at dpdk.org`, it should include a release notes entry documenting the fix, as this affects driver behavior and could impact users who encountered the bug.

---

Review-Result: ERROR


More information about the test-report mailing list