Reviewed-by: Wei Zhao <wei.zh...@intel.com>
> -----Original Message----- > From: Guo, Jia <jia....@intel.com> > Sent: Thursday, July 16, 2020 4:54 PM > To: Zhao1, Wei <wei.zh...@intel.com> > Cc: bmcf...@redhat.com; dev@dpdk.org; Guo, Jia <jia....@intel.com> > Subject: [dpdk-dev] net/e1000: fix segfault on tx done clean up > > As tx mbuf is not set for some advanced descriptors, if there is no mbuf > checking before rte_pktmbuf_free_seg() function be called on the process of tx > done clean up, that will cause a segfault. So add a NULL pointer check to fix > it. > > Bugzilla ID: 501 > Fixes: 8d907d2b79f7 (net/igb: free consumed Tx buffers on demand) > > Signed-off-by: Jeff Guo <jia....@intel.com> > --- > drivers/net/e1000/igb_rxtx.c | 170 +++++++++++++++++------------------ > 1 file changed, 82 insertions(+), 88 deletions(-) > > diff --git a/drivers/net/e1000/igb_rxtx.c b/drivers/net/e1000/igb_rxtx.c index > 5717cdb70..115a723e4 100644 > --- a/drivers/net/e1000/igb_rxtx.c > +++ b/drivers/net/e1000/igb_rxtx.c > @@ -1295,113 +1295,107 @@ igb_tx_done_cleanup(struct igb_tx_queue *txq, > uint32_t free_cnt) > uint16_t tx_id; /* Current segment being processed. */ > uint16_t tx_last; /* Last segment in the current packet. */ > uint16_t tx_next; /* First segment of the next packet. */ > - int count; > + int count = 0; > > - if (txq != NULL) { > - count = 0; > - sw_ring = txq->sw_ring; > - txr = txq->tx_ring; > + if (!txq) > + return = -ENODEV; > > - /* > - * tx_tail is the last sent packet on the sw_ring. Goto the end > - * of that packet (the last segment in the packet chain) and > - * then the next segment will be the start of the oldest segment > - * in the sw_ring. This is the first packet that will be > - * attempted to be freed. > - */ > + sw_ring = txq->sw_ring; > + txr = txq->tx_ring; > > - /* Get last segment in most recently added packet. */ > - tx_first = sw_ring[txq->tx_tail].last_id; > + /* tx_tail is the last sent packet on the sw_ring. Goto the end > + * of that packet (the last segment in the packet chain) and > + * then the next segment will be the start of the oldest segment > + * in the sw_ring. This is the first packet that will be > + * attempted to be freed. > + */ > > - /* Get the next segment, which is the oldest segment in ring. */ > - tx_first = sw_ring[tx_first].next_id; > + /* Get last segment in most recently added packet. */ > + tx_first = sw_ring[txq->tx_tail].last_id; > > - /* Set the current index to the first. */ > - tx_id = tx_first; > + /* Get the next segment, which is the oldest segment in ring. */ > + tx_first = sw_ring[tx_first].next_id; > > - /* > - * Loop through each packet. For each packet, verify that an > - * mbuf exists and that the last segment is free. If so, free > - * it and move on. > - */ > - while (1) { > - tx_last = sw_ring[tx_id].last_id; > - > - if (sw_ring[tx_last].mbuf) { > - if (txr[tx_last].wb.status & > - E1000_TXD_STAT_DD) { > - /* > - * Increment the number of packets > - * freed. > - */ > - count++; > - > - /* Get the start of the next packet. */ > - tx_next = sw_ring[tx_last].next_id; > - > - /* > - * Loop through all segments in a > - * packet. > - */ > - do { > - > rte_pktmbuf_free_seg(sw_ring[tx_id].mbuf); > + /* Set the current index to the first. */ > + tx_id = tx_first; > + > + /* Loop through each packet. For each packet, verify that an > + * mbuf exists and that the last segment is free. If so, free > + * it and move on. > + */ > + while (1) { > + tx_last = sw_ring[tx_id].last_id; > + > + if (sw_ring[tx_last].mbuf) { > + if (txr[tx_last].wb.status & > + E1000_TXD_STAT_DD) { > + /* Increment the number of packets > + * freed. > + */ > + count++; > + > + /* Get the start of the next packet. */ > + tx_next = sw_ring[tx_last].next_id; > + > + /* Loop through all segments in a > + * packet. > + */ > + do { > + if (sw_ring[tx_id].mbuf) { > + rte_pktmbuf_free_seg( > + sw_ring[tx_id].mbuf); > sw_ring[tx_id].mbuf = NULL; > sw_ring[tx_id].last_id = tx_id; > + } > > - /* Move to next segemnt. */ > - tx_id = sw_ring[tx_id].next_id; > + /* Move to next segemnt. */ > + tx_id = sw_ring[tx_id].next_id; > > - } while (tx_id != tx_next); > + } while (tx_id != tx_next); > > - if (unlikely(count == (int)free_cnt)) > - break; > - } else > - /* > - * mbuf still in use, nothing left to > - * free. > - */ > + if (unlikely(count == (int)free_cnt)) > break; > } else { > - /* > - * There are multiple reasons to be here: > - * 1) All the packets on the ring have been > - * freed - tx_id is equal to tx_first > - * and some packets have been freed. > - * - Done, exit > - * 2) Interfaces has not sent a rings worth of > - * packets yet, so the segment after tail is > - * still empty. Or a previous call to this > - * function freed some of the segments but > - * not all so there is a hole in the list. > - * Hopefully this is a rare case. > - * - Walk the list and find the next mbuf. If > - * there isn't one, then done. > + /* mbuf still in use, nothing left to > + * free. > */ > - if (likely((tx_id == tx_first) && (count != 0))) > - break; > + break; > + } > + } else { > + /* There are multiple reasons to be here: > + * 1) All the packets on the ring have been > + * freed - tx_id is equal to tx_first > + * and some packets have been freed. > + * - Done, exit > + * 2) Interfaces has not sent a rings worth of > + * packets yet, so the segment after tail is > + * still empty. Or a previous call to this > + * function freed some of the segments but > + * not all so there is a hole in the list. > + * Hopefully this is a rare case. > + * - Walk the list and find the next mbuf. If > + * there isn't one, then done. > + */ > + if (likely(tx_id == tx_first && count != 0)) > + break; > > - /* > - * Walk the list and find the next mbuf, if any. > - */ > - do { > - /* Move to next segemnt. */ > - tx_id = sw_ring[tx_id].next_id; > + /* Walk the list and find the next mbuf, if any. */ > + do { > + /* Move to next segemnt. */ > + tx_id = sw_ring[tx_id].next_id; > > - if (sw_ring[tx_id].mbuf) > - break; > + if (sw_ring[tx_id].mbuf) > + break; > > - } while (tx_id != tx_first); > + } while (tx_id != tx_first); > > - /* > - * Determine why previous loop bailed. If there > - * is not an mbuf, done. > - */ > - if (sw_ring[tx_id].mbuf == NULL) > - break; > - } > + /* Determine why previous loop bailed. If there > + * is not an mbuf, done. > + */ > + if (!sw_ring[tx_id].mbuf) > + break; > } > - } else > - count = -ENODEV; > + } > > return count; > } > -- > 2.20.1