patches for DPDK stable branches
 help / color / mirror / Atom feed
* [dpdk-stable] [dpdk-dev] [PATCH v3 1/5] net/tap: fix mbuf double free when writev fails
@ 2020-04-07  4:22 wangyunjian
  2020-04-07 12:34 ` Ferruh Yigit
  0 siblings, 1 reply; 9+ messages in thread
From: wangyunjian @ 2020-04-07  4:22 UTC (permalink / raw)
  To: dev; +Cc: keith.wiles, jerry.lilijun, xudingke, Yunjian Wang, stable

From: Yunjian Wang <wangyunjian@huawei.com>

When the tap_write_mbufs() function return with break, mbuf was freed
without incrementing num_packets. This may lead applications also free
the mbuf. And the pmd_tx_burst() function should returns the number of
original packets it actually sent excluding tso mbufs.

Fixes: 9396ad334672 ("net/tap: fix reported number of Tx packets")
CC: stable@dpdk.org

Signed-off-by: Yunjian Wang <wangyunjian@huawei.com>
---
 drivers/net/tap/rte_eth_tap.c | 21 +++++++++++++++------
 1 file changed, 15 insertions(+), 6 deletions(-)

diff --git a/drivers/net/tap/rte_eth_tap.c b/drivers/net/tap/rte_eth_tap.c
index 05470a211..4c4b6b0b2 100644
--- a/drivers/net/tap/rte_eth_tap.c
+++ b/drivers/net/tap/rte_eth_tap.c
@@ -521,7 +521,7 @@ tap_tx_l3_cksum(char *packet, uint64_t ol_flags, unsigned int l2_len,
 	}
 }
 
-static inline void
+static inline int
 tap_write_mbufs(struct tx_queue *txq, uint16_t num_mbufs,
 			struct rte_mbuf **pmbufs,
 			uint16_t *num_packets, unsigned long *num_tx_bytes)
@@ -588,7 +588,7 @@ tap_write_mbufs(struct tx_queue *txq, uint16_t num_mbufs,
 			seg_len = rte_pktmbuf_data_len(mbuf);
 			l234_hlen = mbuf->l2_len + mbuf->l3_len + mbuf->l4_len;
 			if (seg_len < l234_hlen)
-				break;
+				return -1;
 
 			/* To change checksums, work on a * copy of l2, l3
 			 * headers + l4 pseudo header
@@ -634,10 +634,12 @@ tap_write_mbufs(struct tx_queue *txq, uint16_t num_mbufs,
 		/* copy the tx frame data */
 		n = writev(process_private->txq_fds[txq->queue_id], iovecs, j);
 		if (n <= 0)
-			break;
+			return -1;
+
 		(*num_packets)++;
 		(*num_tx_bytes) += rte_pktmbuf_pkt_len(mbuf);
 	}
+	return 0;
 }
 
 /* Callback to handle sending packets from the tap interface
@@ -708,8 +710,15 @@ pmd_tx_burst(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
 			num_mbufs = 1;
 		}
 
-		tap_write_mbufs(txq, num_mbufs, mbuf,
-				&num_packets, &num_tx_bytes);
+		ret = tap_write_mbufs(txq, num_mbufs, mbuf,
+				      &num_packets, &num_tx_bytes);
+		if (ret != 0) {
+			txq->stats.errs++;
+			/* free tso mbufs */
+			for (j = 0; j < ret; j++)
+				rte_pktmbuf_free(mbuf[j]);
+			break;
+		}
 		num_tx++;
 		/* free original mbuf */
 		rte_pktmbuf_free(mbuf_in);
@@ -722,7 +731,7 @@ pmd_tx_burst(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
 	txq->stats.errs += nb_pkts - num_tx;
 	txq->stats.obytes += num_tx_bytes;
 
-	return num_packets;
+	return num_tx;
 }
 
 static const char *
-- 
2.19.1



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [dpdk-stable] [dpdk-dev] [PATCH v3 1/5] net/tap: fix mbuf double free when writev fails
  2020-04-07  4:22 [dpdk-stable] [dpdk-dev] [PATCH v3 1/5] net/tap: fix mbuf double free when writev fails wangyunjian
@ 2020-04-07 12:34 ` Ferruh Yigit
  2020-04-09  8:03   ` wangyunjian
  0 siblings, 1 reply; 9+ messages in thread
From: Ferruh Yigit @ 2020-04-07 12:34 UTC (permalink / raw)
  To: wangyunjian, dev; +Cc: keith.wiles, jerry.lilijun, xudingke, stable

On 4/7/2020 5:22 AM, wangyunjian wrote:
> From: Yunjian Wang <wangyunjian@huawei.com>
> 
> When the tap_write_mbufs() function return with break, mbuf was freed
> without incrementing num_packets. This may lead applications also free
> the mbuf. And the pmd_tx_burst() function should returns the number of
> original packets it actually sent excluding tso mbufs.
> 
> Fixes: 9396ad334672 ("net/tap: fix reported number of Tx packets")
> CC: stable@dpdk.org
> 
> Signed-off-by: Yunjian Wang <wangyunjian@huawei.com>
> ---
>  drivers/net/tap/rte_eth_tap.c | 21 +++++++++++++++------
>  1 file changed, 15 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/net/tap/rte_eth_tap.c b/drivers/net/tap/rte_eth_tap.c
> index 05470a211..4c4b6b0b2 100644
> --- a/drivers/net/tap/rte_eth_tap.c
> +++ b/drivers/net/tap/rte_eth_tap.c
> @@ -521,7 +521,7 @@ tap_tx_l3_cksum(char *packet, uint64_t ol_flags, unsigned int l2_len,
>  	}
>  }
>  
> -static inline void
> +static inline int
>  tap_write_mbufs(struct tx_queue *txq, uint16_t num_mbufs,
>  			struct rte_mbuf **pmbufs,
>  			uint16_t *num_packets, unsigned long *num_tx_bytes)
> @@ -588,7 +588,7 @@ tap_write_mbufs(struct tx_queue *txq, uint16_t num_mbufs,
>  			seg_len = rte_pktmbuf_data_len(mbuf);
>  			l234_hlen = mbuf->l2_len + mbuf->l3_len + mbuf->l4_len;
>  			if (seg_len < l234_hlen)
> -				break;
> +				return -1;
>  
>  			/* To change checksums, work on a * copy of l2, l3
>  			 * headers + l4 pseudo header
> @@ -634,10 +634,12 @@ tap_write_mbufs(struct tx_queue *txq, uint16_t num_mbufs,
>  		/* copy the tx frame data */
>  		n = writev(process_private->txq_fds[txq->queue_id], iovecs, j);
>  		if (n <= 0)
> -			break;
> +			return -1;
> +
>  		(*num_packets)++;
>  		(*num_tx_bytes) += rte_pktmbuf_pkt_len(mbuf);
>  	}
> +	return 0;
>  }
>  
>  /* Callback to handle sending packets from the tap interface
> @@ -708,8 +710,15 @@ pmd_tx_burst(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
>  			num_mbufs = 1;
>  		}
>  
> -		tap_write_mbufs(txq, num_mbufs, mbuf,
> -				&num_packets, &num_tx_bytes);
> +		ret = tap_write_mbufs(txq, num_mbufs, mbuf,
> +				      &num_packets, &num_tx_bytes);

reusing 'ret' here breaks the logic at the end of the loop that free tso mbufs,
which expects 'ret' is number of mbufs in tso case.

> +		if (ret != 0) {
> +			txq->stats.errs++;
> +			/* free tso mbufs */
> +			for (j = 0; j < ret; j++)

'ret' only can be '0' or '-1', and we take the branch only when it is '-1', so
this block is not used at all and it doesn't free any mbuf.

> +				rte_pktmbuf_free(mbuf[j]);


In the no tso case, if the 'tap_write_mbufs()' fails, this doesn't free the
'mbuf_in'.

> +			break;
> +		}
>  		num_tx++;
>  		/* free original mbuf */
>  		rte_pktmbuf_free(mbuf_in);
> @@ -722,7 +731,7 @@ pmd_tx_burst(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
>  	txq->stats.errs += nb_pkts - num_tx;
>  	txq->stats.obytes += num_tx_bytes;
>  
> -	return num_packets;
> +	return num_tx;

+1 to return number of original packets.

>  }
>  
>  static const char *
> 


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [dpdk-stable] [dpdk-dev] [PATCH v3 1/5] net/tap: fix mbuf double free when writev fails
  2020-04-07 12:34 ` Ferruh Yigit
@ 2020-04-09  8:03   ` wangyunjian
  2020-04-09  9:52     ` Ferruh Yigit
  2020-04-09 14:51     ` Stephen Hemminger
  0 siblings, 2 replies; 9+ messages in thread
From: wangyunjian @ 2020-04-09  8:03 UTC (permalink / raw)
  To: Ferruh Yigit, dev; +Cc: keith.wiles, Lilijun (Jerry), xudingke, stable



> -----Original Message-----
> From: Ferruh Yigit [mailto:ferruh.yigit@intel.com]
> Sent: Tuesday, April 7, 2020 8:35 PM
> To: wangyunjian <wangyunjian@huawei.com>; dev@dpdk.org
> Cc: keith.wiles@intel.com; Lilijun (Jerry) <jerry.lilijun@huawei.com>; xudingke
> <xudingke@huawei.com>; stable@dpdk.org
> Subject: Re: [dpdk-stable] [dpdk-dev] [PATCH v3 1/5] net/tap: fix mbuf double
> free when writev fails
> 
> On 4/7/2020 5:22 AM, wangyunjian wrote:
> > From: Yunjian Wang <wangyunjian@huawei.com>
> >
> > When the tap_write_mbufs() function return with break, mbuf was freed
> > without incrementing num_packets. This may lead applications also free
> > the mbuf. And the pmd_tx_burst() function should returns the number of
> > original packets it actually sent excluding tso mbufs.
> >
> > Fixes: 9396ad334672 ("net/tap: fix reported number of Tx packets")
> > CC: stable@dpdk.org
> >
> > Signed-off-by: Yunjian Wang <wangyunjian@huawei.com>
> > ---
> >  drivers/net/tap/rte_eth_tap.c | 21 +++++++++++++++------
> >  1 file changed, 15 insertions(+), 6 deletions(-)
> >
> > diff --git a/drivers/net/tap/rte_eth_tap.c
> > b/drivers/net/tap/rte_eth_tap.c index 05470a211..4c4b6b0b2 100644
> > --- a/drivers/net/tap/rte_eth_tap.c
> > +++ b/drivers/net/tap/rte_eth_tap.c
> > @@ -521,7 +521,7 @@ tap_tx_l3_cksum(char *packet, uint64_t ol_flags,
> unsigned int l2_len,
> >  	}
> >  }
> >
> > -static inline void
> > +static inline int
> >  tap_write_mbufs(struct tx_queue *txq, uint16_t num_mbufs,
> >  			struct rte_mbuf **pmbufs,
> >  			uint16_t *num_packets, unsigned long *num_tx_bytes) @@
> -588,7
> > +588,7 @@ tap_write_mbufs(struct tx_queue *txq, uint16_t num_mbufs,
> >  			seg_len = rte_pktmbuf_data_len(mbuf);
> >  			l234_hlen = mbuf->l2_len + mbuf->l3_len + mbuf->l4_len;
> >  			if (seg_len < l234_hlen)
> > -				break;
> > +				return -1;
> >
> >  			/* To change checksums, work on a * copy of l2, l3
> >  			 * headers + l4 pseudo header
> > @@ -634,10 +634,12 @@ tap_write_mbufs(struct tx_queue *txq, uint16_t
> num_mbufs,
> >  		/* copy the tx frame data */
> >  		n = writev(process_private->txq_fds[txq->queue_id], iovecs, j);
> >  		if (n <= 0)
> > -			break;
> > +			return -1;
> > +
> >  		(*num_packets)++;
> >  		(*num_tx_bytes) += rte_pktmbuf_pkt_len(mbuf);
> >  	}
> > +	return 0;
> >  }
> >
> >  /* Callback to handle sending packets from the tap interface @@
> > -708,8 +710,15 @@ pmd_tx_burst(void *queue, struct rte_mbuf **bufs,
> uint16_t nb_pkts)
> >  			num_mbufs = 1;
> >  		}
> >
> > -		tap_write_mbufs(txq, num_mbufs, mbuf,
> > -				&num_packets, &num_tx_bytes);
> > +		ret = tap_write_mbufs(txq, num_mbufs, mbuf,
> > +				      &num_packets, &num_tx_bytes);
> 
> reusing 'ret' here breaks the logic at the end of the loop that free tso mbufs,
> which expects 'ret' is number of mbufs in tso case.
> 
> > +		if (ret != 0) {
> > +			txq->stats.errs++;
> > +			/* free tso mbufs */
> > +			for (j = 0; j < ret; j++)
> 
> 'ret' only can be '0' or '-1', and we take the branch only when it is '-1', so this
> block is not used at all and it doesn't free any mbuf.

I'm sorry for my mistakes. I will fix it in next version.
what about following:

error = tap_write_mbufs(txq, num_mbufs, mbuf,
                     &num_packets, &num_tx_bytes);
if (error == -1) {
    txq->stats.errs++;
    /* free tso mbufs */
    for (j = 0; j < ret; j++)
        rte_pktmbuf_free(mbuf[j]);
    break;
}

Thanks
Yunjian
> > +				rte_pktmbuf_free(mbuf[j]);
> 
> 
> In the no tso case, if the 'tap_write_mbufs()' fails, this doesn't free the
> 'mbuf_in'.
> 
> > +			break;
> > +		}
> >  		num_tx++;
> >  		/* free original mbuf */
> >  		rte_pktmbuf_free(mbuf_in);
> > @@ -722,7 +731,7 @@ pmd_tx_burst(void *queue, struct rte_mbuf **bufs,
> uint16_t nb_pkts)
> >  	txq->stats.errs += nb_pkts - num_tx;
> >  	txq->stats.obytes += num_tx_bytes;
> >
> > -	return num_packets;
> > +	return num_tx;
> 
> +1 to return number of original packets.
> 
> >  }
> >
> >  static const char *
> >


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [dpdk-stable] [dpdk-dev] [PATCH v3 1/5] net/tap: fix mbuf double free when writev fails
  2020-04-09  8:03   ` wangyunjian
@ 2020-04-09  9:52     ` Ferruh Yigit
  2020-04-09 12:53       ` wangyunjian
  2020-04-09 14:51     ` Stephen Hemminger
  1 sibling, 1 reply; 9+ messages in thread
From: Ferruh Yigit @ 2020-04-09  9:52 UTC (permalink / raw)
  To: wangyunjian, dev; +Cc: keith.wiles, Lilijun (Jerry), xudingke, stable

On 4/9/2020 9:03 AM, wangyunjian wrote:
> 
> 
>> -----Original Message-----
>> From: Ferruh Yigit [mailto:ferruh.yigit@intel.com]
>> Sent: Tuesday, April 7, 2020 8:35 PM
>> To: wangyunjian <wangyunjian@huawei.com>; dev@dpdk.org
>> Cc: keith.wiles@intel.com; Lilijun (Jerry) <jerry.lilijun@huawei.com>; xudingke
>> <xudingke@huawei.com>; stable@dpdk.org
>> Subject: Re: [dpdk-stable] [dpdk-dev] [PATCH v3 1/5] net/tap: fix mbuf double
>> free when writev fails
>>
>> On 4/7/2020 5:22 AM, wangyunjian wrote:
>>> From: Yunjian Wang <wangyunjian@huawei.com>
>>>
>>> When the tap_write_mbufs() function return with break, mbuf was freed
>>> without incrementing num_packets. This may lead applications also free
>>> the mbuf. And the pmd_tx_burst() function should returns the number of
>>> original packets it actually sent excluding tso mbufs.
>>>
>>> Fixes: 9396ad334672 ("net/tap: fix reported number of Tx packets")
>>> CC: stable@dpdk.org
>>>
>>> Signed-off-by: Yunjian Wang <wangyunjian@huawei.com>
>>> ---
>>>  drivers/net/tap/rte_eth_tap.c | 21 +++++++++++++++------
>>>  1 file changed, 15 insertions(+), 6 deletions(-)
>>>
>>> diff --git a/drivers/net/tap/rte_eth_tap.c
>>> b/drivers/net/tap/rte_eth_tap.c index 05470a211..4c4b6b0b2 100644
>>> --- a/drivers/net/tap/rte_eth_tap.c
>>> +++ b/drivers/net/tap/rte_eth_tap.c
>>> @@ -521,7 +521,7 @@ tap_tx_l3_cksum(char *packet, uint64_t ol_flags,
>> unsigned int l2_len,
>>>  	}
>>>  }
>>>
>>> -static inline void
>>> +static inline int
>>>  tap_write_mbufs(struct tx_queue *txq, uint16_t num_mbufs,
>>>  			struct rte_mbuf **pmbufs,
>>>  			uint16_t *num_packets, unsigned long *num_tx_bytes) @@
>> -588,7
>>> +588,7 @@ tap_write_mbufs(struct tx_queue *txq, uint16_t num_mbufs,
>>>  			seg_len = rte_pktmbuf_data_len(mbuf);
>>>  			l234_hlen = mbuf->l2_len + mbuf->l3_len + mbuf->l4_len;
>>>  			if (seg_len < l234_hlen)
>>> -				break;
>>> +				return -1;
>>>
>>>  			/* To change checksums, work on a * copy of l2, l3
>>>  			 * headers + l4 pseudo header
>>> @@ -634,10 +634,12 @@ tap_write_mbufs(struct tx_queue *txq, uint16_t
>> num_mbufs,
>>>  		/* copy the tx frame data */
>>>  		n = writev(process_private->txq_fds[txq->queue_id], iovecs, j);
>>>  		if (n <= 0)
>>> -			break;
>>> +			return -1;
>>> +
>>>  		(*num_packets)++;
>>>  		(*num_tx_bytes) += rte_pktmbuf_pkt_len(mbuf);
>>>  	}
>>> +	return 0;
>>>  }
>>>
>>>  /* Callback to handle sending packets from the tap interface @@
>>> -708,8 +710,15 @@ pmd_tx_burst(void *queue, struct rte_mbuf **bufs,
>> uint16_t nb_pkts)
>>>  			num_mbufs = 1;
>>>  		}
>>>
>>> -		tap_write_mbufs(txq, num_mbufs, mbuf,
>>> -				&num_packets, &num_tx_bytes);
>>> +		ret = tap_write_mbufs(txq, num_mbufs, mbuf,
>>> +				      &num_packets, &num_tx_bytes);
>>
>> reusing 'ret' here breaks the logic at the end of the loop that free tso mbufs,
>> which expects 'ret' is number of mbufs in tso case.
>>
>>> +		if (ret != 0) {
>>> +			txq->stats.errs++;
>>> +			/* free tso mbufs */
>>> +			for (j = 0; j < ret; j++)
>>
>> 'ret' only can be '0' or '-1', and we take the branch only when it is '-1', so this
>> block is not used at all and it doesn't free any mbuf.
> 
> I'm sorry for my mistakes. I will fix it in next version.
> what about following:
> 
> error = tap_write_mbufs(txq, num_mbufs, mbuf,
>                      &num_packets, &num_tx_bytes);
> if (error == -1) {
>     txq->stats.errs++;
>     /* free tso mbufs */
>     for (j = 0; j < ret; j++)
>         rte_pktmbuf_free(mbuf[j]);
>     break;
> }

+1, but still needs to free the 'mbuf_in' before break.

Or maybe it is better to create a new variable like 'num_tso_mbufs' and use it
instead of 'ret', which is more readable, and this enables to reuse the 'ret'.

> 
> Thanks
> Yunjian
>>> +				rte_pktmbuf_free(mbuf[j]);
>>
>>
>> In the no tso case, if the 'tap_write_mbufs()' fails, this doesn't free the
>> 'mbuf_in'.
>>
>>> +			break;
>>> +		}
>>>  		num_tx++;
>>>  		/* free original mbuf */
>>>  		rte_pktmbuf_free(mbuf_in);
>>> @@ -722,7 +731,7 @@ pmd_tx_burst(void *queue, struct rte_mbuf **bufs,
>> uint16_t nb_pkts)
>>>  	txq->stats.errs += nb_pkts - num_tx;
>>>  	txq->stats.obytes += num_tx_bytes;
>>>
>>> -	return num_packets;
>>> +	return num_tx;
>>
>> +1 to return number of original packets.
>>
>>>  }
>>>
>>>  static const char *
>>>
> 


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [dpdk-stable] [dpdk-dev] [PATCH v3 1/5] net/tap: fix mbuf double free when writev fails
  2020-04-09  9:52     ` Ferruh Yigit
@ 2020-04-09 12:53       ` wangyunjian
  2020-04-09 13:03         ` Ferruh Yigit
  0 siblings, 1 reply; 9+ messages in thread
From: wangyunjian @ 2020-04-09 12:53 UTC (permalink / raw)
  To: Ferruh Yigit, dev; +Cc: keith.wiles, Lilijun (Jerry), xudingke, stable



> -----Original Message-----
> From: Ferruh Yigit [mailto:ferruh.yigit@intel.com]
> Sent: Thursday, April 9, 2020 5:52 PM
> To: wangyunjian <wangyunjian@huawei.com>; dev@dpdk.org
> Cc: keith.wiles@intel.com; Lilijun (Jerry) <jerry.lilijun@huawei.com>; xudingke
> <xudingke@huawei.com>; stable@dpdk.org
> Subject: Re: [dpdk-stable] [dpdk-dev] [PATCH v3 1/5] net/tap: fix mbuf double
> free when writev fails
> 
> On 4/9/2020 9:03 AM, wangyunjian wrote:
> >
> >
> >> -----Original Message-----
> >> From: Ferruh Yigit [mailto:ferruh.yigit@intel.com]
> >> Sent: Tuesday, April 7, 2020 8:35 PM
> >> To: wangyunjian <wangyunjian@huawei.com>; dev@dpdk.org
> >> Cc: keith.wiles@intel.com; Lilijun (Jerry)
> >> <jerry.lilijun@huawei.com>; xudingke <xudingke@huawei.com>;
> >> stable@dpdk.org
> >> Subject: Re: [dpdk-stable] [dpdk-dev] [PATCH v3 1/5] net/tap: fix
> >> mbuf double free when writev fails
> >>
> >> On 4/7/2020 5:22 AM, wangyunjian wrote:
> >>> From: Yunjian Wang <wangyunjian@huawei.com>
> >>>
> >>> When the tap_write_mbufs() function return with break, mbuf was
> >>> freed without incrementing num_packets. This may lead applications
> >>> also free the mbuf. And the pmd_tx_burst() function should returns
> >>> the number of original packets it actually sent excluding tso mbufs.
> >>>
> >>> Fixes: 9396ad334672 ("net/tap: fix reported number of Tx packets")
> >>> CC: stable@dpdk.org
> >>>
> >>> Signed-off-by: Yunjian Wang <wangyunjian@huawei.com>
> >>> ---
> >>>  drivers/net/tap/rte_eth_tap.c | 21 +++++++++++++++------
> >>>  1 file changed, 15 insertions(+), 6 deletions(-)
> >>>
> >>> diff --git a/drivers/net/tap/rte_eth_tap.c
> >>> b/drivers/net/tap/rte_eth_tap.c index 05470a211..4c4b6b0b2 100644
> >>> --- a/drivers/net/tap/rte_eth_tap.c
> >>> +++ b/drivers/net/tap/rte_eth_tap.c
> >>> @@ -521,7 +521,7 @@ tap_tx_l3_cksum(char *packet, uint64_t ol_flags,
> >> unsigned int l2_len,
> >>>  	}
> >>>  }
> >>>
> >>> -static inline void
> >>> +static inline int
> >>>  tap_write_mbufs(struct tx_queue *txq, uint16_t num_mbufs,
> >>>  			struct rte_mbuf **pmbufs,
> >>>  			uint16_t *num_packets, unsigned long *num_tx_bytes)
> @@
> >> -588,7
> >>> +588,7 @@ tap_write_mbufs(struct tx_queue *txq, uint16_t num_mbufs,
> >>>  			seg_len = rte_pktmbuf_data_len(mbuf);
> >>>  			l234_hlen = mbuf->l2_len + mbuf->l3_len + mbuf->l4_len;
> >>>  			if (seg_len < l234_hlen)
> >>> -				break;
> >>> +				return -1;
> >>>
> >>>  			/* To change checksums, work on a * copy of l2, l3
> >>>  			 * headers + l4 pseudo header
> >>> @@ -634,10 +634,12 @@ tap_write_mbufs(struct tx_queue *txq,
> uint16_t
> >> num_mbufs,
> >>>  		/* copy the tx frame data */
> >>>  		n = writev(process_private->txq_fds[txq->queue_id], iovecs, j);
> >>>  		if (n <= 0)
> >>> -			break;
> >>> +			return -1;
> >>> +
> >>>  		(*num_packets)++;
> >>>  		(*num_tx_bytes) += rte_pktmbuf_pkt_len(mbuf);
> >>>  	}
> >>> +	return 0;
> >>>  }
> >>>
> >>>  /* Callback to handle sending packets from the tap interface @@
> >>> -708,8 +710,15 @@ pmd_tx_burst(void *queue, struct rte_mbuf **bufs,
> >> uint16_t nb_pkts)
> >>>  			num_mbufs = 1;
> >>>  		}
> >>>
> >>> -		tap_write_mbufs(txq, num_mbufs, mbuf,
> >>> -				&num_packets, &num_tx_bytes);
> >>> +		ret = tap_write_mbufs(txq, num_mbufs, mbuf,
> >>> +				      &num_packets, &num_tx_bytes);
> >>
> >> reusing 'ret' here breaks the logic at the end of the loop that free
> >> tso mbufs, which expects 'ret' is number of mbufs in tso case.
> >>
> >>> +		if (ret != 0) {
> >>> +			txq->stats.errs++;
> >>> +			/* free tso mbufs */
> >>> +			for (j = 0; j < ret; j++)
> >>
> >> 'ret' only can be '0' or '-1', and we take the branch only when it is
> >> '-1', so this block is not used at all and it doesn't free any mbuf.
> >
> > I'm sorry for my mistakes. I will fix it in next version.
> > what about following:
> >
> > error = tap_write_mbufs(txq, num_mbufs, mbuf,
> >                      &num_packets, &num_tx_bytes); if (error == -1) {
> >     txq->stats.errs++;
> >     /* free tso mbufs */
> >     for (j = 0; j < ret; j++)
> >         rte_pktmbuf_free(mbuf[j]);
> >     break;
> > }
> 
> +1, but still needs to free the 'mbuf_in' before break.

I don't think it needs to free the 'mbuf_in' before break.
The 'num_tx' does not increase, the caller will free unsent packets.

> 
> Or maybe it is better to create a new variable like 'num_tso_mbufs' and use it
> instead of 'ret', which is more readable, and this enables to reuse the 'ret'.

Thanks for your suggestion, will include it in next version.

Yunjian

> 
> >
> > Thanks
> > Yunjian
> >>> +				rte_pktmbuf_free(mbuf[j]);
> >>
> >>
> >> In the no tso case, if the 'tap_write_mbufs()' fails, this doesn't
> >> free the 'mbuf_in'.
> >>
> >>> +			break;
> >>> +		}
> >>>  		num_tx++;
> >>>  		/* free original mbuf */
> >>>  		rte_pktmbuf_free(mbuf_in);
> >>> @@ -722,7 +731,7 @@ pmd_tx_burst(void *queue, struct rte_mbuf
> >>> **bufs,
> >> uint16_t nb_pkts)
> >>>  	txq->stats.errs += nb_pkts - num_tx;
> >>>  	txq->stats.obytes += num_tx_bytes;
> >>>
> >>> -	return num_packets;
> >>> +	return num_tx;
> >>
> >> +1 to return number of original packets.
> >>
> >>>  }
> >>>
> >>>  static const char *
> >>>
> >


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [dpdk-stable] [dpdk-dev] [PATCH v3 1/5] net/tap: fix mbuf double free when writev fails
  2020-04-09 12:53       ` wangyunjian
@ 2020-04-09 13:03         ` Ferruh Yigit
  0 siblings, 0 replies; 9+ messages in thread
From: Ferruh Yigit @ 2020-04-09 13:03 UTC (permalink / raw)
  To: wangyunjian, dev; +Cc: keith.wiles, Lilijun (Jerry), xudingke, stable

On 4/9/2020 1:53 PM, wangyunjian wrote:
> 
> 
>> -----Original Message-----
>> From: Ferruh Yigit [mailto:ferruh.yigit@intel.com]
>> Sent: Thursday, April 9, 2020 5:52 PM
>> To: wangyunjian <wangyunjian@huawei.com>; dev@dpdk.org
>> Cc: keith.wiles@intel.com; Lilijun (Jerry) <jerry.lilijun@huawei.com>; xudingke
>> <xudingke@huawei.com>; stable@dpdk.org
>> Subject: Re: [dpdk-stable] [dpdk-dev] [PATCH v3 1/5] net/tap: fix mbuf double
>> free when writev fails
>>
>> On 4/9/2020 9:03 AM, wangyunjian wrote:
>>>
>>>
>>>> -----Original Message-----
>>>> From: Ferruh Yigit [mailto:ferruh.yigit@intel.com]
>>>> Sent: Tuesday, April 7, 2020 8:35 PM
>>>> To: wangyunjian <wangyunjian@huawei.com>; dev@dpdk.org
>>>> Cc: keith.wiles@intel.com; Lilijun (Jerry)
>>>> <jerry.lilijun@huawei.com>; xudingke <xudingke@huawei.com>;
>>>> stable@dpdk.org
>>>> Subject: Re: [dpdk-stable] [dpdk-dev] [PATCH v3 1/5] net/tap: fix
>>>> mbuf double free when writev fails
>>>>
>>>> On 4/7/2020 5:22 AM, wangyunjian wrote:
>>>>> From: Yunjian Wang <wangyunjian@huawei.com>
>>>>>
>>>>> When the tap_write_mbufs() function return with break, mbuf was
>>>>> freed without incrementing num_packets. This may lead applications
>>>>> also free the mbuf. And the pmd_tx_burst() function should returns
>>>>> the number of original packets it actually sent excluding tso mbufs.
>>>>>
>>>>> Fixes: 9396ad334672 ("net/tap: fix reported number of Tx packets")
>>>>> CC: stable@dpdk.org
>>>>>
>>>>> Signed-off-by: Yunjian Wang <wangyunjian@huawei.com>
>>>>> ---
>>>>>  drivers/net/tap/rte_eth_tap.c | 21 +++++++++++++++------
>>>>>  1 file changed, 15 insertions(+), 6 deletions(-)
>>>>>
>>>>> diff --git a/drivers/net/tap/rte_eth_tap.c
>>>>> b/drivers/net/tap/rte_eth_tap.c index 05470a211..4c4b6b0b2 100644
>>>>> --- a/drivers/net/tap/rte_eth_tap.c
>>>>> +++ b/drivers/net/tap/rte_eth_tap.c
>>>>> @@ -521,7 +521,7 @@ tap_tx_l3_cksum(char *packet, uint64_t ol_flags,
>>>> unsigned int l2_len,
>>>>>  	}
>>>>>  }
>>>>>
>>>>> -static inline void
>>>>> +static inline int
>>>>>  tap_write_mbufs(struct tx_queue *txq, uint16_t num_mbufs,
>>>>>  			struct rte_mbuf **pmbufs,
>>>>>  			uint16_t *num_packets, unsigned long *num_tx_bytes)
>> @@
>>>> -588,7
>>>>> +588,7 @@ tap_write_mbufs(struct tx_queue *txq, uint16_t num_mbufs,
>>>>>  			seg_len = rte_pktmbuf_data_len(mbuf);
>>>>>  			l234_hlen = mbuf->l2_len + mbuf->l3_len + mbuf->l4_len;
>>>>>  			if (seg_len < l234_hlen)
>>>>> -				break;
>>>>> +				return -1;
>>>>>
>>>>>  			/* To change checksums, work on a * copy of l2, l3
>>>>>  			 * headers + l4 pseudo header
>>>>> @@ -634,10 +634,12 @@ tap_write_mbufs(struct tx_queue *txq,
>> uint16_t
>>>> num_mbufs,
>>>>>  		/* copy the tx frame data */
>>>>>  		n = writev(process_private->txq_fds[txq->queue_id], iovecs, j);
>>>>>  		if (n <= 0)
>>>>> -			break;
>>>>> +			return -1;
>>>>> +
>>>>>  		(*num_packets)++;
>>>>>  		(*num_tx_bytes) += rte_pktmbuf_pkt_len(mbuf);
>>>>>  	}
>>>>> +	return 0;
>>>>>  }
>>>>>
>>>>>  /* Callback to handle sending packets from the tap interface @@
>>>>> -708,8 +710,15 @@ pmd_tx_burst(void *queue, struct rte_mbuf **bufs,
>>>> uint16_t nb_pkts)
>>>>>  			num_mbufs = 1;
>>>>>  		}
>>>>>
>>>>> -		tap_write_mbufs(txq, num_mbufs, mbuf,
>>>>> -				&num_packets, &num_tx_bytes);
>>>>> +		ret = tap_write_mbufs(txq, num_mbufs, mbuf,
>>>>> +				      &num_packets, &num_tx_bytes);
>>>>
>>>> reusing 'ret' here breaks the logic at the end of the loop that free
>>>> tso mbufs, which expects 'ret' is number of mbufs in tso case.
>>>>
>>>>> +		if (ret != 0) {
>>>>> +			txq->stats.errs++;
>>>>> +			/* free tso mbufs */
>>>>> +			for (j = 0; j < ret; j++)
>>>>
>>>> 'ret' only can be '0' or '-1', and we take the branch only when it is
>>>> '-1', so this block is not used at all and it doesn't free any mbuf.
>>>
>>> I'm sorry for my mistakes. I will fix it in next version.
>>> what about following:
>>>
>>> error = tap_write_mbufs(txq, num_mbufs, mbuf,
>>>                      &num_packets, &num_tx_bytes); if (error == -1) {
>>>     txq->stats.errs++;
>>>     /* free tso mbufs */
>>>     for (j = 0; j < ret; j++)
>>>         rte_pktmbuf_free(mbuf[j]);
>>>     break;
>>> }
>>
>> +1, but still needs to free the 'mbuf_in' before break.
> 
> I don't think it needs to free the 'mbuf_in' before break.
> The 'num_tx' does not increase, the caller will free unsent packets.

Yep, you are right.

> 
>>
>> Or maybe it is better to create a new variable like 'num_tso_mbufs' and use it
>> instead of 'ret', which is more readable, and this enables to reuse the 'ret'.
> 
> Thanks for your suggestion, will include it in next version.
> 
> Yunjian
> 
>>
>>>
>>> Thanks
>>> Yunjian
>>>>> +				rte_pktmbuf_free(mbuf[j]);
>>>>
>>>>
>>>> In the no tso case, if the 'tap_write_mbufs()' fails, this doesn't
>>>> free the 'mbuf_in'.
>>>>
>>>>> +			break;
>>>>> +		}
>>>>>  		num_tx++;
>>>>>  		/* free original mbuf */
>>>>>  		rte_pktmbuf_free(mbuf_in);
>>>>> @@ -722,7 +731,7 @@ pmd_tx_burst(void *queue, struct rte_mbuf
>>>>> **bufs,
>>>> uint16_t nb_pkts)
>>>>>  	txq->stats.errs += nb_pkts - num_tx;
>>>>>  	txq->stats.obytes += num_tx_bytes;
>>>>>
>>>>> -	return num_packets;
>>>>> +	return num_tx;
>>>>
>>>> +1 to return number of original packets.
>>>>
>>>>>  }
>>>>>
>>>>>  static const char *
>>>>>
>>>
> 


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [dpdk-stable] [dpdk-dev] [PATCH v3 1/5] net/tap: fix mbuf double free when writev fails
  2020-04-09  8:03   ` wangyunjian
  2020-04-09  9:52     ` Ferruh Yigit
@ 2020-04-09 14:51     ` Stephen Hemminger
  2020-04-10  1:41       ` wangyunjian
  1 sibling, 1 reply; 9+ messages in thread
From: Stephen Hemminger @ 2020-04-09 14:51 UTC (permalink / raw)
  To: wangyunjian
  Cc: Ferruh Yigit, dev, keith.wiles, Lilijun (Jerry), xudingke, stable

On Thu, 9 Apr 2020 08:03:23 +0000
wangyunjian <wangyunjian@huawei.com> wrote:

> error = tap_write_mbufs(txq, num_mbufs, mbuf,
>                      &num_packets, &num_tx_bytes);
> if (error == -1) {
>     txq->stats.errs++;
>     /* free tso mbufs */
>     for (j = 0; j < ret; j++)
>         rte_pktmbuf_free(mbuf[j]);
>     break;
> }

There is a free bulk, and normally each buf counts against errors.

        if (error == -1) {
		txq->stats.errs += num_packets;
		rte_pktmbuf_free_bulk(mbuf, num_packets);
		break;
	}


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [dpdk-stable] [dpdk-dev] [PATCH v3 1/5] net/tap: fix mbuf double free when writev fails
  2020-04-09 14:51     ` Stephen Hemminger
@ 2020-04-10  1:41       ` wangyunjian
  2020-04-10  7:45         ` Ferruh Yigit
  0 siblings, 1 reply; 9+ messages in thread
From: wangyunjian @ 2020-04-10  1:41 UTC (permalink / raw)
  To: Stephen Hemminger
  Cc: Ferruh Yigit, dev, keith.wiles, Lilijun (Jerry), xudingke, stable

> -----Original Message-----
> From: Stephen Hemminger [mailto:stephen@networkplumber.org]
> Sent: Thursday, April 9, 2020 10:51 PM
> To: wangyunjian <wangyunjian@huawei.com>
> Cc: Ferruh Yigit <ferruh.yigit@intel.com>; dev@dpdk.org;
> keith.wiles@intel.com; Lilijun (Jerry) <jerry.lilijun@huawei.com>; xudingke
> <xudingke@huawei.com>; stable@dpdk.org
> Subject: Re: [dpdk-dev] [dpdk-stable] [PATCH v3 1/5] net/tap: fix mbuf double
> free when writev fails
> 
> On Thu, 9 Apr 2020 08:03:23 +0000
> wangyunjian <wangyunjian@huawei.com> wrote:
> 
> > error = tap_write_mbufs(txq, num_mbufs, mbuf,
> >                      &num_packets, &num_tx_bytes); if (error == -1) {
> >     txq->stats.errs++;
> >     /* free tso mbufs */
> >     for (j = 0; j < ret; j++)
> >         rte_pktmbuf_free(mbuf[j]);
> >     break;
> > }
> 
> There is a free bulk, and normally each buf counts against errors.
> 
>         if (error == -1) {
> 		txq->stats.errs += num_packets;

I think to consider only the original packet number, not sent packets.

> 		rte_pktmbuf_free_bulk(mbuf, num_packets);

Thanks for your suggestion, will include it in next version.

Yunjian
> 		break;
> 	}


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [dpdk-stable] [dpdk-dev] [PATCH v3 1/5] net/tap: fix mbuf double free when writev fails
  2020-04-10  1:41       ` wangyunjian
@ 2020-04-10  7:45         ` Ferruh Yigit
  0 siblings, 0 replies; 9+ messages in thread
From: Ferruh Yigit @ 2020-04-10  7:45 UTC (permalink / raw)
  To: wangyunjian, Stephen Hemminger
  Cc: dev, keith.wiles, Lilijun (Jerry), xudingke, stable

On 4/10/2020 2:41 AM, wangyunjian wrote:
>> -----Original Message-----
>> From: Stephen Hemminger [mailto:stephen@networkplumber.org]
>> Sent: Thursday, April 9, 2020 10:51 PM
>> To: wangyunjian <wangyunjian@huawei.com>
>> Cc: Ferruh Yigit <ferruh.yigit@intel.com>; dev@dpdk.org;
>> keith.wiles@intel.com; Lilijun (Jerry) <jerry.lilijun@huawei.com>; xudingke
>> <xudingke@huawei.com>; stable@dpdk.org
>> Subject: Re: [dpdk-dev] [dpdk-stable] [PATCH v3 1/5] net/tap: fix mbuf double
>> free when writev fails
>>
>> On Thu, 9 Apr 2020 08:03:23 +0000
>> wangyunjian <wangyunjian@huawei.com> wrote:
>>
>>> error = tap_write_mbufs(txq, num_mbufs, mbuf,
>>>                      &num_packets, &num_tx_bytes); if (error == -1) {
>>>     txq->stats.errs++;
>>>     /* free tso mbufs */
>>>     for (j = 0; j < ret; j++)
>>>         rte_pktmbuf_free(mbuf[j]);
>>>     break;
>>> }
>>
>> There is a free bulk, and normally each buf counts against errors.
>>
>>         if (error == -1) {
>> 		txq->stats.errs += num_packets;
> 
> I think to consider only the original packet number, not sent packets.

+1. 'mubf' here is the output of the 'rte_gso_segment()', the number of mbuf
application sent is 1.

> 
>> 		rte_pktmbuf_free_bulk(mbuf, num_packets);
> 
> Thanks for your suggestion, will include it in next version.
> 
> Yunjian
>> 		break;
>> 	}
> 


^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2020-04-10  7:45 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-04-07  4:22 [dpdk-stable] [dpdk-dev] [PATCH v3 1/5] net/tap: fix mbuf double free when writev fails wangyunjian
2020-04-07 12:34 ` Ferruh Yigit
2020-04-09  8:03   ` wangyunjian
2020-04-09  9:52     ` Ferruh Yigit
2020-04-09 12:53       ` wangyunjian
2020-04-09 13:03         ` Ferruh Yigit
2020-04-09 14:51     ` Stephen Hemminger
2020-04-10  1:41       ` wangyunjian
2020-04-10  7:45         ` Ferruh Yigit

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).