|WARNING| [8/8] net/ice: fix DCF port leak on probe failure

dpdklab at iol.unh.edu dpdklab at iol.unh.edu
Fri Nov 6 02:33:38 CET 2026


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

_AI Code Review_

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

# DPDK Patch Review

## ERRORS

### Patch 1/8: net/ice: fix DCF hardware init error path

**Error path resource leaks (multiple instances)**

The error handling is incomplete even after this patch.

Line `goto err_intr;` at line 856 (when VLAN offload V2 fails) now correctly jumps to the new cleanup label. However:

1. **Missing cleanup of `hw->rss_key` and `hw->rss_lut`**: The new `err_intr:` label does not free `hw->rss_key` and `hw->rss_lut`, which were allocated earlier in the function. The cleanup must fall through to `err_rss:` rather than jumping past it.

2. **Missing cleanup of `hw->vf_res`**: All error paths after `hw->vf_res` is allocated must free it. The patch adds `rte_free(hw->vf_vsi_map)` at `err_alloc:`, but this label is reached by `goto err_alloc;` (not shown in patch context) which presumably occurs before `hw->vf_vsi_map` is allocated. If `hw->vf_vsi_map` allocation fails, jumping to `err_alloc:` would then attempt to free the not-yet-allocated map.

**Suggested fix for the new error label**:
```c
err_intr:
	ice_dcf_disable_irq0(hw);
	rte_intr_disable(pci_dev->intr_handle);
	rte_intr_callback_unregister(pci_dev->intr_handle,
				     ice_dcf_dev_interrupt_handler, hw);
	rte_free(hw->qos_bw_cfg);
	hw->qos_bw_cfg = NULL;
	/* fall through to free RSS resources */
err_rss:
	rte_free(hw->rss_key);
	rte_free(hw->rss_lut);
err_alloc:
	rte_free(hw->vf_vsi_map);
	hw->vf_vsi_map = NULL;
	rte_free(hw->vf_res);
err_api:
	iavf_shutdown_adminq(&hw->avf);
```

The current patch creates a label that skips RSS cleanup when the VLAN offload step fails.

---

### Patch 2/8: net/ice: fix DCF parent adapter init error path

**Label ordering causes incomplete cleanup**

Line 494 (new line after patch): `goto uninit_flow;` when `ice_flow_init()` fails.

The new `uninit_flow:` label at line 507 calls `ice_flow_uninit()`, but `ice_flow_uninit()` should only be called if `ice_flow_init()` **succeeded**. When `ice_flow_init()` itself fails, calling `ice_flow_uninit()` on a partially-initialized flow subsystem may access uninitialized state or double-free resources that `ice_flow_init()` already cleaned up internally on its error path.

The `ice_flow_init()` failure path should jump directly to `uninit_hw:`, not to `uninit_flow:`.

**Suggested fix**:
```c
	err = ice_flow_init(parent_adapter);
	if (err) {
		PMD_INIT_LOG(ERR, "Failed to initialize flow");
		goto uninit_hw;  /* do not call uninit on failed init */
	}
```

The `uninit_flow:` label is only needed on the success path's error exit (e.g., if MAC address add failed).

---

## WARNINGS

### Patch 4/8: net/ice: fix DCF QoS buffer leak on commit

**Missing error path cleanup**

The patch correctly frees `vf_bw` and `tc_bw` on the success path (line 852-853), but the `fail_clear:` error path (line 856 onward, not shown in diff) does not free them. If the hierarchy commit fails after allocating these buffers, they leak.

The cleanup should be:
```c
fail_clear:
	/* ... existing cleanup ... */
	free(vf_bw);
	free(tc_bw);
	return ret_val;
```

---

### Patch 7/8: net/ice: fix DCF representor info leak on close

**Partial resource ownership model**

The refactoring splits close into `ice_dcf_dev_teardown()` (freed on every close/reset) and representor info (freed only on final close). However:

1. **Representor info allocation and notification are coupled**: `ice_dcf_init_repr_info()` allocates the info array, and later in `ice_dcf_dev_init()` the code notifies representors. `ice_dcf_dev_reset()` calls `ice_dcf_dev_teardown()` which calls `ice_dcf_vf_repr_notify_all(adapter, false)`, then re-initializes which calls `ice_dcf_vf_repr_notify_all(adapter, true)` again.

   The comment at line 1683 states "representor info survives ice_dcf_dev_reset", but the representor info **contents** (the `vf_rep_eth_dev` pointers) are set to NULL by the representor close/destroy in the error path of patch 8. This creates an inconsistency: the info array survives, but its contents are cleared.

2. **Unnecessary NULL check after free**: Line 1684 calls `ice_dcf_free_repr_info(dev->data->dev_private);` unconditionally. If `ice_dcf_free_repr_info()` internally checks for NULL, this is acceptable; but if not, and if `ice_dcf_dev_close()` can be called multiple times (DPDK does not forbid it), this could be a double-free.

**Recommendation**: Document in a comment that `ice_dcf_dev_close()` must not be called twice without an intervening `ice_dcf_dev_init()`, or ensure `ice_dcf_free_repr_info()` and `ice_dcf_dev_teardown()` are idempotent.

---

### Patch 8/8: net/ice: fix DCF port leak on probe failure

**Error path calls generic remove on partially-initialized device**

Line 2148: `rte_eth_dev_pci_generic_remove(pci_dev, ice_dcf_dev_uninit);`

This is called when probe has partially succeeded (DCF port created, some representors may have been created). The generic remove will call `ice_dcf_dev_uninit()`, which expects the device to be in a fully initialized or cleanly closed state. If representor creation failed partway through, `ice_dcf_dev_uninit()` may attempt to clean up state that was never set up (e.g., flow rules, queues).

**More robust approach**: After destroying the representors in the loop (lines 2140-2144), call `ice_dcf_dev_close()` on the DCF ethdev to run the normal teardown, **then** call the generic remove. Or, ensure `ice_dcf_dev_uninit()` is safe to call on a partially-initialized adapter (checks all pointers, does not assume prior `ice_dcf_dev_init()` success).

**Suggested fix**:
```c
err_remove_dcf:
	ice_dcf_free_repr_info(dcf_adapter);  /* free the info we allocated */
	(void)ice_dcf_dev_close(dcf_ethdev);  /* clean teardown */
	rte_eth_dev_pci_generic_remove(pci_dev, ice_dcf_dev_uninit);
```

This ensures the DCF port goes through the normal close path before uninit.

---

## INFO

### Patch 3/8: net/ice: fix DCF queue config buffer leak

Clean fix. The `rte_free(vc_config);` before each early return correctly prevents the leak.

---

### Patch 5/8: net/ice: fix DCF QoS bandwidth replay config leak

The added `rte_free()` before each new allocation (lines 816 and 844) prevents the leak on repeated commits. The loop in `ice_dcf_uninit_hw()` (lines 923-925) correctly frees all entries before freeing the array.

**Minor note**: The loop iterates to `hw->num_vfs`, but the TC node bandwidth is stored at index `ICE_DCF_VFID`. If `ICE_DCF_VFID >= hw->num_vfs`, the TC entry is not freed. Verify that `ICE_DCF_VFID < hw->num_vfs` or adjust the loop bound to `hw->num_vfs + 1` (or to the actual array size).

---

### Patch 6/8: net/ice: fix DCF TM config leak on close

The change correctly moves `ice_dcf_tm_conf_uninit()` outside the `if (hw->tm_conf.committed)` block, so uncommitted TM state is also freed. The `ice_dcf_clear_bw()` call remains conditional, as clearing bandwidth requires a committed hierarchy.

---

## SUMMARY

The series correctly identifies and fixes several resource leaks in the ice DCF driver's error paths and close/reset flows. However, **Patches 1 and 2 have correctness bugs** in their error handling that must be fixed. Patch 4 has a missing cleanup on the error path (Warning). Patches 7 and 8 have design issues in their error recovery that should be addressed.

Review-Result: ERROR


More information about the test-report mailing list