[v3] rte_ethdev: safer memory access by calling Rx/Tx callback
Checks
Commit Message
When compiling with -O0,
the compiler does not optimize two memory accesses into one.
Leads to accessing a null pointer when queue post Rx burst callback
removal while traffic is running.
Signed-off-by: ZY Qiu <tgw_team@tencent.com>
---
lib/librte_ethdev/rte_ethdev.h | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
Comments
On Thu, Mar 5, 2020 at 10:17 PM ZY Qiu <quzeyao@gmail.com> wrote:
>
> When compiling with -O0,
> the compiler does not optimize two memory accesses into one.
> Leads to accessing a null pointer when queue post Rx burst callback
> removal while traffic is running.
>
> Signed-off-by: ZY Qiu <tgw_team@tencent.com>
> ---
> lib/librte_ethdev/rte_ethdev.h | 9 +++++----
> 1 file changed, 5 insertions(+), 4 deletions(-)
>
> diff --git a/lib/librte_ethdev/rte_ethdev.h b/lib/librte_ethdev/rte_ethdev.h
> index d1a593ad1..c46612e3e 100644
> --- a/lib/librte_ethdev/rte_ethdev.h
> +++ b/lib/librte_ethdev/rte_ethdev.h
> @@ -4388,10 +4388,10 @@ rte_eth_rx_burst(uint16_t port_id, uint16_t queue_id,
> rx_pkts, nb_pkts);
>
> #ifdef RTE_ETHDEV_RXTX_CALLBACKS
> - if (unlikely(dev->post_rx_burst_cbs[queue_id] != NULL)) {
> - struct rte_eth_rxtx_callback *cb =
> - dev->post_rx_burst_cbs[queue_id];
> + struct rte_eth_rxtx_callback *volatile cb =
> + dev->post_rx_burst_cbs[queue_id];
Is adding rte_compiler_barrier() here without changing to volatile
solving the problem in your case?
If so, I prefer to change to compiler_barrier() as volatile may have a
performance impact on fast-path code.
>
> + if (unlikely(cb != NULL)) {
> do {
> nb_rx = cb->fn.rx(port_id, queue_id, rx_pkts, nb_rx,
> nb_pkts, cb->param);
> @@ -4652,7 +4652,8 @@ rte_eth_tx_burst(uint16_t port_id, uint16_t queue_id,
> #endif
>
> #ifdef RTE_ETHDEV_RXTX_CALLBACKS
> - struct rte_eth_rxtx_callback *cb = dev->pre_tx_burst_cbs[queue_id];
> + struct rte_eth_rxtx_callback *volatile cb =
> + dev->pre_tx_burst_cbs[queue_id];
>
> if (unlikely(cb != NULL)) {
> do {
> --
> 2.17.1
>
> -----Original Message-----
> From: ZY Qiu <quzeyao@gmail.com>
> Sent: Thursday, March 5, 2020 4:47 PM
> To: Thomas Monjalon <thomas@monjalon.net>; Yigit, Ferruh <ferruh.yigit@intel.com>; Andrew Rybchenko <arybchenko@solarflare.com>
> Cc: dev@dpdk.org; stephen@networkplumber.org; Ananyev, Konstantin <konstantin.ananyev@intel.com>; ZY Qiu
> <tgw_team@tencent.com>
> Subject: [PATCH v3] rte_ethdev: safer memory access by calling Rx/Tx callback
>
> When compiling with -O0,
> the compiler does not optimize two memory accesses into one.
> Leads to accessing a null pointer when queue post Rx burst callback
> removal while traffic is running.
>
> Signed-off-by: ZY Qiu <tgw_team@tencent.com>
> ---
> lib/librte_ethdev/rte_ethdev.h | 9 +++++----
> 1 file changed, 5 insertions(+), 4 deletions(-)
>
> diff --git a/lib/librte_ethdev/rte_ethdev.h b/lib/librte_ethdev/rte_ethdev.h
> index d1a593ad1..c46612e3e 100644
> --- a/lib/librte_ethdev/rte_ethdev.h
> +++ b/lib/librte_ethdev/rte_ethdev.h
> @@ -4388,10 +4388,10 @@ rte_eth_rx_burst(uint16_t port_id, uint16_t queue_id,
> rx_pkts, nb_pkts);
>
> #ifdef RTE_ETHDEV_RXTX_CALLBACKS
> - if (unlikely(dev->post_rx_burst_cbs[queue_id] != NULL)) {
> - struct rte_eth_rxtx_callback *cb =
> - dev->post_rx_burst_cbs[queue_id];
> + struct rte_eth_rxtx_callback *volatile cb =
> + dev->post_rx_burst_cbs[queue_id];
>
> + if (unlikely(cb != NULL)) {
> do {
> nb_rx = cb->fn.rx(port_id, queue_id, rx_pkts, nb_rx,
> nb_pkts, cb->param);
> @@ -4652,7 +4652,8 @@ rte_eth_tx_burst(uint16_t port_id, uint16_t queue_id,
> #endif
>
> #ifdef RTE_ETHDEV_RXTX_CALLBACKS
> - struct rte_eth_rxtx_callback *cb = dev->pre_tx_burst_cbs[queue_id];
> + struct rte_eth_rxtx_callback *volatile cb =
> + dev->pre_tx_burst_cbs[queue_id];
>
> if (unlikely(cb != NULL)) {
> do {
> --
Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
> 2.17.1
On Wed, Mar 11, 2020 at 5:52 PM Ananyev, Konstantin
<konstantin.ananyev@intel.com> wrote:
>
>
>
> > -----Original Message-----
> > From: ZY Qiu <quzeyao@gmail.com>
> > Sent: Thursday, March 5, 2020 4:47 PM
> > To: Thomas Monjalon <thomas@monjalon.net>; Yigit, Ferruh <ferruh.yigit@intel.com>; Andrew Rybchenko <arybchenko@solarflare.com>
> > Cc: dev@dpdk.org; stephen@networkplumber.org; Ananyev, Konstantin <konstantin.ananyev@intel.com>; ZY Qiu
> > <tgw_team@tencent.com>
> > Subject: [PATCH v3] rte_ethdev: safer memory access by calling Rx/Tx callback
> >
> > When compiling with -O0,
> > the compiler does not optimize two memory accesses into one.
> > Leads to accessing a null pointer when queue post Rx burst callback
> > removal while traffic is running.
> >
> > Signed-off-by: ZY Qiu <tgw_team@tencent.com>
> > ---
> > lib/librte_ethdev/rte_ethdev.h | 9 +++++----
> > 1 file changed, 5 insertions(+), 4 deletions(-)
> >
> > diff --git a/lib/librte_ethdev/rte_ethdev.h b/lib/librte_ethdev/rte_ethdev.h
> > index d1a593ad1..c46612e3e 100644
> > --- a/lib/librte_ethdev/rte_ethdev.h
> > +++ b/lib/librte_ethdev/rte_ethdev.h
> > @@ -4388,10 +4388,10 @@ rte_eth_rx_burst(uint16_t port_id, uint16_t queue_id,
> > rx_pkts, nb_pkts);
> >
> > #ifdef RTE_ETHDEV_RXTX_CALLBACKS
> > - if (unlikely(dev->post_rx_burst_cbs[queue_id] != NULL)) {
> > - struct rte_eth_rxtx_callback *cb =
> > - dev->post_rx_burst_cbs[queue_id];
> > + struct rte_eth_rxtx_callback *volatile cb =
> > + dev->post_rx_burst_cbs[queue_id];
I prefer to change to compiler_barrier() if it working as volatile may have a
performance impact on fast-path code.
> >
> > + if (unlikely(cb != NULL)) {
> > do {
> > nb_rx = cb->fn.rx(port_id, queue_id, rx_pkts, nb_rx,
> > nb_pkts, cb->param);
> > @@ -4652,7 +4652,8 @@ rte_eth_tx_burst(uint16_t port_id, uint16_t queue_id,
> > #endif
> >
> > #ifdef RTE_ETHDEV_RXTX_CALLBACKS
> > - struct rte_eth_rxtx_callback *cb = dev->pre_tx_burst_cbs[queue_id];
> > + struct rte_eth_rxtx_callback *volatile cb =
> > + dev->pre_tx_burst_cbs[queue_id];
> >
> > if (unlikely(cb != NULL)) {
> > do {
> > --
>
> Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
>
> > 2.17.1
>
On 3/11/2020 12:26 PM, Jerin Jacob wrote:
> On Wed, Mar 11, 2020 at 5:52 PM Ananyev, Konstantin
> <konstantin.ananyev@intel.com> wrote:
>>
>>
>>
>>> -----Original Message-----
>>> From: ZY Qiu <quzeyao@gmail.com>
>>> Sent: Thursday, March 5, 2020 4:47 PM
>>> To: Thomas Monjalon <thomas@monjalon.net>; Yigit, Ferruh <ferruh.yigit@intel.com>; Andrew Rybchenko <arybchenko@solarflare.com>
>>> Cc: dev@dpdk.org; stephen@networkplumber.org; Ananyev, Konstantin <konstantin.ananyev@intel.com>; ZY Qiu
>>> <tgw_team@tencent.com>
>>> Subject: [PATCH v3] rte_ethdev: safer memory access by calling Rx/Tx callback
>>>
>>> When compiling with -O0,
>>> the compiler does not optimize two memory accesses into one.
>>> Leads to accessing a null pointer when queue post Rx burst callback
>>> removal while traffic is running.
>>>
>>> Signed-off-by: ZY Qiu <tgw_team@tencent.com>
>>> ---
>>> lib/librte_ethdev/rte_ethdev.h | 9 +++++----
>>> 1 file changed, 5 insertions(+), 4 deletions(-)
>>>
>>> diff --git a/lib/librte_ethdev/rte_ethdev.h b/lib/librte_ethdev/rte_ethdev.h
>>> index d1a593ad1..c46612e3e 100644
>>> --- a/lib/librte_ethdev/rte_ethdev.h
>>> +++ b/lib/librte_ethdev/rte_ethdev.h
>>> @@ -4388,10 +4388,10 @@ rte_eth_rx_burst(uint16_t port_id, uint16_t queue_id,
>>> rx_pkts, nb_pkts);
>>>
>>> #ifdef RTE_ETHDEV_RXTX_CALLBACKS
>>> - if (unlikely(dev->post_rx_burst_cbs[queue_id] != NULL)) {
>>> - struct rte_eth_rxtx_callback *cb =
>>> - dev->post_rx_burst_cbs[queue_id];
>>> + struct rte_eth_rxtx_callback *volatile cb =
>>> + dev->post_rx_burst_cbs[queue_id];
>
> I prefer to change to compiler_barrier() if it working as volatile may have a
> performance impact on fast-path code.
>
Hi ZY Qiu,
Did you able to test with compiler barrier, is it solving your problem?
If there is no update on the issue, I will mark it as rejected.
Thanks,
ferruh
>
>>>
>>> + if (unlikely(cb != NULL)) {
>>> do {
>>> nb_rx = cb->fn.rx(port_id, queue_id, rx_pkts, nb_rx,
>>> nb_pkts, cb->param);
>>> @@ -4652,7 +4652,8 @@ rte_eth_tx_burst(uint16_t port_id, uint16_t queue_id,
>>> #endif
>>>
>>> #ifdef RTE_ETHDEV_RXTX_CALLBACKS
>>> - struct rte_eth_rxtx_callback *cb = dev->pre_tx_burst_cbs[queue_id];
>>> + struct rte_eth_rxtx_callback *volatile cb =
>>> + dev->pre_tx_burst_cbs[queue_id];
>>>
>>> if (unlikely(cb != NULL)) {
>>> do {
>>> --
>>
>> Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
>>
>>> 2.17.1
>>
@@ -4388,10 +4388,10 @@ rte_eth_rx_burst(uint16_t port_id, uint16_t queue_id,
rx_pkts, nb_pkts);
#ifdef RTE_ETHDEV_RXTX_CALLBACKS
- if (unlikely(dev->post_rx_burst_cbs[queue_id] != NULL)) {
- struct rte_eth_rxtx_callback *cb =
- dev->post_rx_burst_cbs[queue_id];
+ struct rte_eth_rxtx_callback *volatile cb =
+ dev->post_rx_burst_cbs[queue_id];
+ if (unlikely(cb != NULL)) {
do {
nb_rx = cb->fn.rx(port_id, queue_id, rx_pkts, nb_rx,
nb_pkts, cb->param);
@@ -4652,7 +4652,8 @@ rte_eth_tx_burst(uint16_t port_id, uint16_t queue_id,
#endif
#ifdef RTE_ETHDEV_RXTX_CALLBACKS
- struct rte_eth_rxtx_callback *cb = dev->pre_tx_burst_cbs[queue_id];
+ struct rte_eth_rxtx_callback *volatile cb =
+ dev->pre_tx_burst_cbs[queue_id];
if (unlikely(cb != NULL)) {
do {