This patch addresses several memory leaks and
incorrect error reporting that exist in the
iavf RSS (hash) flow engine:
- iavf_hash_parse_raw_pattern() returns without
freeing "pkt_buf" when the "msk_buf" allocation
fails, leaking the first buffer on every failed
raw pattern parse.
- iavf_hash_create() only frees the parsed "meta"
on success.
Both error paths return early and leak the struct
iavf_rss_meta allocated by iavf_hash_parse_pattern_action(),
which no other caller frees.
Free in both error paths.
- iavf_hash_destroy() never releases flow->rule.
The virtchnl_rss_cfg allocated by iavf_hash_create() is only
released by the engine's free callback, iavf_hash_free(),
which is invoked from iavf_flow_uninit() but not from
iavf_flow_destroy().
So every flow destroy or flush of an RSS rule leaks it.
The early return taken while the VF is resetting leaks it too.
Free the config and clear flow->rule properly in all paths.
- Out of memory conditions are reported to the application as
EINVAL while -ENOMEM is returned.
Report ENOMEM instead.
Fixes: bc0e85586eaf ("net/iavf: support VF RSS flow rule with raw pattern")
Fixes: 7be10c3004be ("net/iavf: add RSS configuration for VF")
Fixes: c02ea7410e51 ("net/iavf: fix flow flush after PF reset")
Signed-off-by: Anurag Mandal <[email protected]>
---
drivers/net/intel/iavf/iavf_hash.c | 33 ++++++++++++++++++------------
1 file changed, 20 insertions(+), 13 deletions(-)
diff --git a/drivers/net/intel/iavf/iavf_hash.c
b/drivers/net/intel/iavf/iavf_hash.c
index 9515094402..00b616f34b 100644
--- a/drivers/net/intel/iavf/iavf_hash.c
+++ b/drivers/net/intel/iavf/iavf_hash.c
@@ -918,8 +918,10 @@ iavf_hash_parse_raw_pattern(const struct rte_flow_item
*item,
return -ENOMEM;
msk_buf = rte_zmalloc(NULL, pkt_len, 0);
- if (!msk_buf)
+ if (!msk_buf) {
+ rte_free(pkt_buf);
return -ENOMEM;
+ }
/* convert string to int array */
for (i = 0, j = 0; i < spec_len; i += 2, j++) {
@@ -1538,7 +1540,7 @@ iavf_hash_parse_pattern_action(struct iavf_adapter *ad,
rss_meta_ptr = rte_zmalloc(NULL, sizeof(*rss_meta_ptr), 0);
if (!rss_meta_ptr) {
- rte_flow_error_set(error, EINVAL,
+ rte_flow_error_set(error, ENOMEM,
RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
"No memory for rss_meta_ptr");
return -ENOMEM;
@@ -1594,9 +1596,10 @@ iavf_hash_create(__rte_unused struct iavf_adapter *ad,
rss_cfg = rte_zmalloc("iavf rss rule",
sizeof(struct virtchnl_rss_cfg), 0);
if (!rss_cfg) {
- rte_flow_error_set(error, EINVAL,
+ rte_flow_error_set(error, ENOMEM,
RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
"No memory for rss rule");
+ rte_free(meta);
return -ENOMEM;
}
@@ -1612,6 +1615,7 @@ iavf_hash_create(__rte_unused struct iavf_adapter *ad,
RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
"Failed to add rss rule.");
rte_free(rss_cfg);
+ rte_free(meta);
return -rte_errno;
}
@@ -1629,19 +1633,22 @@ iavf_hash_destroy(__rte_unused struct iavf_adapter *ad,
struct virtchnl_rss_cfg *rss_cfg;
int ret = 0;
- if (vf->vf_reset)
- return 0;
-
rss_cfg = (struct virtchnl_rss_cfg *)flow->rule;
- ret = iavf_add_del_rss_cfg(ad, rss_cfg, false);
- if (ret) {
- PMD_DRV_LOG(ERR, "fail to del RSS configure");
- rte_flow_error_set(error, -ret,
- RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
- "Failed to delete rss rule.");
- return -rte_errno;
+ if (!vf->vf_reset) {
+ ret = iavf_add_del_rss_cfg(ad, rss_cfg, false);
+ if (ret) {
+ PMD_DRV_LOG(ERR, "fail to del RSS configure");
+ rte_flow_error_set(error, -ret,
+ RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
+ "Failed to delete rss rule.");
+ return -rte_errno;
+ }
}
+
+ flow->rule = NULL;
+ rte_free(rss_cfg);
+
return ret;
}
--
2.34.1