From: wangyunjian <wangyunjian@huawei.com>
To: <dev@dpdk.org>
Cc: <xudingke@huawei.com>, Yunjian Wang <wangyunjian@huawei.com>,
<stable@dpdk.org>
Subject: [dpdk-dev] [PATCH] net/i40e: fix crash when calling i40e_vsi_delete_mac
Date: Sat, 13 Apr 2019 17:54:51 +0800 [thread overview]
Message-ID: <1555149291-12432-1-git-send-email-wangyunjian@huawei.com> (raw)
Message-ID: <20190413095451.hUIgpir_SBcxntjY9ylq7sE9g5SPan1PsCQQMRTJLEo@z> (raw)
From: Yunjian Wang <wangyunjian@huawei.com>
Now the macvlan filter list may be accessed in the same time by two
different threads and may cause a lot of optional errors. This patch
protects the macvlan filter access with a spinlock.
Call Trace:
#1 0x00007ffb4cbe2e3c in i40e_vsi_delete_mac (vsi=vsi@entry=
0x400052804b40, addr=addr@entry=0x7ffb47672244) at /usr/src/
debug/dpdk-18.11/drivers/net/i40e/i40e_ethdev.c:7266
#2 0x00007ffb4cbe342b in i40e_set_default_mac_addr (dev=<optimized out>,
mac_addr=0x400052a6618d) at /usr/src/debug/dpdk-18.11/drivers/net/
i40e/i40e_ethdev.c:11893
#3 0x00007ffb4f569d4a in rte_eth_dev_default_mac_addr_set (port_id=
<optimized out>, addr=addr@entry=0x400052a6618d) at /usr/src/debug/
dpdk-18.11/lib/librte_ethdev/rte_ethdev.c:3366
#4 0x00007ffb4d0bb403 in mac_address_slaves_update (bonded_eth_dev=
bonded_eth_dev@entry=0xacf8c0 <rte_eth_devices>) at /usr/src/debug/
dpdk-18.11/drivers/net/bonding/rte_eth_bond_pmd.c:1854
#5 0x00007ffb4d0bd221 in bond_ethdev_lsc_event_callback (port_id=
<optimized out>, type=<optimized out>, param=<optimized out>,
ret_param= <optimized out>) at /usr/src/debug/dpdk-18.11/drivers/
net/bonding/rte_eth_bond_pmd.c:3076
#6 0x00007ffb4f56aa09 in _rte_eth_dev_callback_process (dev=dev@entry=
0xad3940 <rte_eth_devices+16512>, event=event@entry=
RTE_ETH_EVENT_INTR_LSC, ret_param=ret_param@entry=0x0)
at /usr/src/debug/dpdk-18.11/lib/librte_ethdev/rte_ethdev.c:3699
#7 0x00007ffb4cbb99f1 in i40e_dev_handle_aq_msg (dev=dev@entry=0xad3940
<rte_eth_devices+16512>) at /usr/src/debug/dpdk-18.11/drivers/net/
i40e/i40e_ethdev.c:6573
#8 0x00007ffb4cbdfbed in i40e_dev_alarm_handler (param=0xad3940
<rte_eth_devices+16512>) at /usr/src/debug/dpdk-18.11/drivers/net/
i40e/i40e_ethdev.c:6681
#9 0x00007ffb4fb9766f in eal_alarm_callback (arg=<optimized out>) at
/usr/src/debug/dpdk-18.11/lib/librte_eal/linuxapp/eal/eal_alarm.c:90
#10 0x00007ffb4fb95dd2 in eal_intr_process_interrupts (nfds=<optimized
out>, events=<optimized out>) at /usr/src/debug/dpdk-18.11/lib/
librte_eal/linuxapp/eal/eal_interrupts.c:886
#11 eal_intr_handle_interrupts (totalfds=<optimized out>, pfd=20) at
/usr/src/debug/dpdk-18.11/lib/librte_eal/linuxapp/eal/
eal_interrupts.c:946
#12 eal_intr_thread_main (arg=<optimized out>) at /usr/src/debug/
dpdk-18.11/lib/librte_eal/linuxapp/eal/eal_interrupts.c:1035
#13 0x00007ffb4b208dd5 in start_thread () from /usr/lib64/libpthread.so.0
#14 0x00007ffb4981659d in clone () from /usr/lib64/libc.so.6
Fixes: 4861cde46116 ("i40e: new poll mode driver")
Cc: stable@dpdk.org
Signed-off-by: Yunjian Wang <wangyunjian@huawei.com>
---
drivers/net/i40e/i40e_ethdev.c | 28 +++++++++++++++++++++++++---
drivers/net/i40e/i40e_ethdev.h | 1 +
drivers/net/i40e/i40e_pf.c | 6 ++++++
drivers/net/i40e/rte_pmd_i40e.c | 12 ++++++++++++
4 files changed, 44 insertions(+), 3 deletions(-)
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 5b01dc1..e4f6818 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -4036,8 +4036,9 @@ static int i40e_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
vsi = pf->main_vsi;
else
vsi = pf->vmdq[pool - 1].vsi;
-
+ rte_spinlock_lock(&vsi->mac_list_lock);
ret = i40e_vsi_add_mac(vsi, &mac_filter);
+ rte_spinlock_unlock(&vsi->mac_list_lock);
if (ret != I40E_SUCCESS) {
PMD_DRV_LOG(ERR, "Failed to add MACVLAN filter");
return -ENODEV;
@@ -4075,7 +4076,9 @@ static int i40e_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
}
vsi = pf->vmdq[i - 1].vsi;
}
+ rte_spinlock_lock(&vsi->mac_list_lock);
ret = i40e_vsi_delete_mac(vsi, macaddr);
+ rte_spinlock_unlock(&vsi->mac_list_lock);
if (ret) {
PMD_DRV_LOG(ERR, "Failed to remove MACVLAN filter");
@@ -4138,7 +4141,9 @@ static int i40e_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
ETHER_ADDR_LEN);
mac_filter.filter_type = filter->filter_type;
+ rte_spinlock_lock(&vf->vsi->mac_list_lock);
ret = i40e_vsi_add_mac(vf->vsi, &mac_filter);
+ rte_spinlock_unlock(&vf->vsi->mac_list_lock);
if (ret != I40E_SUCCESS) {
PMD_DRV_LOG(ERR, "Failed to add MAC filter.");
return -1;
@@ -4147,7 +4152,9 @@ static int i40e_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
} else {
rte_memcpy(hw->mac.addr, hw->mac.perm_addr,
ETHER_ADDR_LEN);
+ rte_spinlock_lock(&vf->vsi->mac_list_lock);
ret = i40e_vsi_delete_mac(vf->vsi, &filter->mac_addr);
+ rte_spinlock_unlock(&vf->vsi->mac_list_lock);
if (ret != I40E_SUCCESS) {
PMD_DRV_LOG(ERR, "Failed to delete MAC filter.");
return -1;
@@ -5266,9 +5273,11 @@ static int i40e_pf_config_vf_rxq_number(struct rte_eth_dev *dev)
}
/* Remove all macvlan filters of the VSI */
+ rte_spinlock_lock(&vsi->mac_list_lock);
i40e_vsi_remove_all_macvlan_filter(vsi);
TAILQ_FOREACH_SAFE(f, &vsi->mac_list, next, temp)
rte_free(f);
+ rte_spinlock_unlock(&vsi->mac_list_lock);
if (vsi->type != I40E_VSI_MAIN &&
((vsi->type != I40E_VSI_SRIOV) ||
@@ -5346,7 +5355,9 @@ static int i40e_pf_config_vf_rxq_number(struct rte_eth_dev *dev)
rte_memcpy(&mac->addr_bytes, hw->mac.perm_addr,
ETH_ADDR_LEN);
f->mac_info.filter_type = RTE_MACVLAN_PERFECT_MATCH;
+ rte_spinlock_lock(&vsi->mac_list_lock);
TAILQ_INSERT_TAIL(&vsi->mac_list, f, next);
+ rte_spinlock_unlock(&vsi->mac_list_lock);
vsi->mac_num++;
return ret;
@@ -5354,7 +5365,10 @@ static int i40e_pf_config_vf_rxq_number(struct rte_eth_dev *dev)
rte_memcpy(&filter.mac_addr,
(struct ether_addr *)(hw->mac.perm_addr), ETH_ADDR_LEN);
filter.filter_type = RTE_MACVLAN_PERFECT_MATCH;
- return i40e_vsi_add_mac(vsi, &filter);
+ rte_spinlock_lock(&vsi->mac_list_lock);
+ ret = i40e_vsi_add_mac(vsi, &filter);
+ rte_spinlock_unlock(&vsi->mac_list_lock);
+ return ret;
}
/*
@@ -5521,6 +5535,7 @@ struct i40e_vsi *
return NULL;
}
TAILQ_INIT(&vsi->mac_list);
+ rte_spinlock_init(&vsi->mac_list_lock);
vsi->type = type;
vsi->adapter = I40E_PF_TO_ADAPTER(pf);
vsi->max_macaddrs = I40E_NUM_MACADDR_MAX;
@@ -5816,8 +5831,9 @@ struct i40e_vsi *
/* MAC/VLAN configuration */
rte_memcpy(&filter.mac_addr, &broadcast, ETHER_ADDR_LEN);
filter.filter_type = RTE_MACVLAN_PERFECT_MATCH;
-
+ rte_spinlock_lock(&vsi->mac_list_lock);
ret = i40e_vsi_add_mac(vsi, &filter);
+ rte_spinlock_unlock(&vsi->mac_list_lock);
if (ret != I40E_SUCCESS) {
PMD_DRV_LOG(ERR, "Failed to add MACVLAN filter");
goto fail_msix_alloc;
@@ -5866,6 +5882,7 @@ struct i40e_vsi *
i = 0;
/* Remove all existing mac */
+ rte_spinlock_lock(&vsi->mac_list_lock);
TAILQ_FOREACH_SAFE(f, &vsi->mac_list, next, temp) {
mac_filter[i] = f->mac_info;
ret = i40e_vsi_delete_mac(vsi, &f->mac_info.mac_addr);
@@ -5889,6 +5906,7 @@ struct i40e_vsi *
}
DONE:
+ rte_spinlock_unlock(&vsi->mac_list_lock);
rte_free(mac_filter);
return ret;
}
@@ -11953,12 +11971,14 @@ static int i40e_set_default_mac_addr(struct rte_eth_dev *dev,
return -EINVAL;
}
+ rte_spinlock_lock(&vsi->mac_list_lock);
TAILQ_FOREACH(f, &vsi->mac_list, next) {
if (is_same_ether_addr(&pf->dev_addr, &f->mac_info.mac_addr))
break;
}
if (f == NULL) {
+ rte_spinlock_unlock(&vsi->mac_list_lock);
PMD_DRV_LOG(ERR, "Failed to find filter for default mac");
return -EIO;
}
@@ -11966,11 +11986,13 @@ static int i40e_set_default_mac_addr(struct rte_eth_dev *dev,
mac_filter = f->mac_info;
ret = i40e_vsi_delete_mac(vsi, &mac_filter.mac_addr);
if (ret != I40E_SUCCESS) {
+ rte_spinlock_unlock(&vsi->mac_list_lock);
PMD_DRV_LOG(ERR, "Failed to delete mac filter");
return -EIO;
}
memcpy(&mac_filter.mac_addr, mac_addr, ETH_ADDR_LEN);
ret = i40e_vsi_add_mac(vsi, &mac_filter);
+ rte_spinlock_unlock(&vsi->mac_list_lock);
if (ret != I40E_SUCCESS) {
PMD_DRV_LOG(ERR, "Failed to add mac filter");
return -EIO;
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index 930eb9a..060be26 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -368,6 +368,7 @@ struct i40e_vsi {
uint16_t mac_num; /* Total mac number */
uint32_t vfta[I40E_VFTA_SIZE]; /* VLAN bitmap */
struct i40e_mac_filter_list mac_list; /* macvlan filter list */
+ rte_spinlock_t mac_list_lock; /* macvlan filter list lock*/
/* specific VSI-defined parameters, SRIOV stored the vf_id */
uint32_t user_param;
uint16_t seid; /* The seid of VSI itself */
diff --git a/drivers/net/i40e/i40e_pf.c b/drivers/net/i40e/i40e_pf.c
index 91be450..faa80cc 100644
--- a/drivers/net/i40e/i40e_pf.c
+++ b/drivers/net/i40e/i40e_pf.c
@@ -845,11 +845,14 @@
mac = (struct ether_addr *)(addr_list->list[i].addr);
rte_memcpy(&filter.mac_addr, mac, ETHER_ADDR_LEN);
filter.filter_type = RTE_MACVLAN_PERFECT_MATCH;
+ rte_spinlock_lock(&vf->vsi->mac_list_lock);
if (is_zero_ether_addr(mac) ||
i40e_vsi_add_mac(vf->vsi, &filter)) {
+ rte_spinlock_unlock(&vf->vsi->mac_list_lock);
ret = I40E_ERR_INVALID_MAC_ADDR;
goto send_msg;
}
+ rte_spinlock_unlock(&vf->vsi->mac_list_lock);
}
send_msg:
@@ -887,11 +890,14 @@
for (i = 0; i < addr_list->num_elements; i++) {
mac = (struct ether_addr *)(addr_list->list[i].addr);
+ rte_spinlock_lock(&vf->vsi->mac_list_lock);
if(is_zero_ether_addr(mac) ||
i40e_vsi_delete_mac(vf->vsi, mac)) {
+ rte_spinlock_unlock(&vf->vsi->mac_list_lock);
ret = I40E_ERR_INVALID_MAC_ADDR;
goto send_msg;
}
+ rte_spinlock_unlock(&vf->vsi->mac_list_lock);
}
send_msg:
diff --git a/drivers/net/i40e/rte_pmd_i40e.c b/drivers/net/i40e/rte_pmd_i40e.c
index 7ae78e4..c5983c9 100644
--- a/drivers/net/i40e/rte_pmd_i40e.c
+++ b/drivers/net/i40e/rte_pmd_i40e.c
@@ -360,7 +360,9 @@
}
/* remove all the MAC and VLAN first */
+ rte_spinlock_lock(&vsi->mac_list_lock);
ret = i40e_vsi_rm_mac_filter(vsi);
+ rte_spinlock_unlock(&vsi->mac_list_lock);
if (ret) {
PMD_INIT_LOG(ERR, "Failed to remove MAC filters.");
return ret;
@@ -390,7 +392,9 @@
}
/* add all the MAC and VLAN back */
+ rte_spinlock_lock(&vsi->mac_list_lock);
ret = i40e_vsi_restore_mac_filter(vsi);
+ rte_spinlock_unlock(&vsi->mac_list_lock);
if (ret)
return ret;
if (vsi->vlan_anti_spoof_on || vsi->vlan_filter_on) {
@@ -563,10 +567,12 @@
ether_addr_copy(mac_addr, &vf->mac_addr);
/* Remove all existing mac */
+ rte_spinlock_lock(&vsi->mac_list_lock);
TAILQ_FOREACH_SAFE(f, &vsi->mac_list, next, temp)
if (i40e_vsi_delete_mac(vsi, &f->mac_info.mac_addr)
!= I40E_SUCCESS)
PMD_DRV_LOG(WARNING, "Delete MAC failed");
+ rte_spinlock_unlock(&vf->vsi->mac_list_lock);
return 0;
}
@@ -609,7 +615,9 @@
ether_addr_copy(&null_mac_addr, &vf->mac_addr);
/* Remove the mac */
+ rte_spinlock_lock(&vsi->mac_list_lock);
i40e_vsi_delete_mac(vsi, mac_addr);
+ rte_spinlock_unlock(&vsi->mac_list_lock);
return 0;
}
@@ -764,6 +772,7 @@ int rte_pmd_i40e_set_vf_broadcast(uint16_t port, uint16_t vf_id,
return -EINVAL;
}
+ rte_spinlock_lock(&vsi->mac_list_lock);
if (on) {
rte_memcpy(&filter.mac_addr, &broadcast, ETHER_ADDR_LEN);
filter.filter_type = RTE_MACVLAN_PERFECT_MATCH;
@@ -771,6 +780,7 @@ int rte_pmd_i40e_set_vf_broadcast(uint16_t port, uint16_t vf_id,
} else {
ret = i40e_vsi_delete_mac(vsi, &broadcast);
}
+ rte_spinlock_unlock(&vsi->mac_list_lock);
if (ret != I40E_SUCCESS && ret != I40E_ERR_PARAM) {
ret = -ENOTSUP;
@@ -2388,7 +2398,9 @@ int rte_pmd_i40e_ptype_mapping_replace(uint16_t port,
mac_filter.filter_type = RTE_MACVLAN_PERFECT_MATCH;
ether_addr_copy(mac_addr, &mac_filter.mac_addr);
+ rte_spinlock_lock(&vf->vsi->mac_list_lock);
ret = i40e_vsi_add_mac(vsi, &mac_filter);
+ rte_spinlock_unlock(&vf->vsi->mac_list_lock);
if (ret != I40E_SUCCESS) {
PMD_DRV_LOG(ERR, "Failed to add MAC filter.");
return -1;
--
1.8.3.1
next reply other threads:[~2019-04-13 9:55 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-04-13 9:54 wangyunjian [this message]
2019-04-13 9:54 ` wangyunjian
2019-04-15 12:21 ` Ananyev, Konstantin
2019-04-15 12:21 ` Ananyev, Konstantin
2019-04-15 12:50 ` Zhang, Qi Z
2019-04-15 12:50 ` Zhang, Qi Z
2019-04-16 2:05 ` wangyunjian
2019-04-16 2:05 ` wangyunjian
2019-04-23 3:39 ` Zhang, Qi Z
2019-04-23 3:39 ` Zhang, Qi Z
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1555149291-12432-1-git-send-email-wangyunjian@huawei.com \
--to=wangyunjian@huawei.com \
--cc=dev@dpdk.org \
--cc=stable@dpdk.org \
--cc=xudingke@huawei.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).