> [PATCH v8 4/4] net/zxdh: optimize Tx xmit pkts performance<br />>  <br />> Error: the simple Tx burst signals a bad packet with a short return,<br />> which the application cannot distinguish from backpressure.<br /> <br />>     for (i = 0; i < nb_pkts; i++) {<br />>         rte_prefetch0(tx_pkts[i]);<br />>         if (unlikely(tx_pkts[i]->data_off < hdr_len)) {<br />>             txvq->stats.errors += nb_pkts - i;<br />>             nb_pkts = i;<br />>             break;<br />>         }<br />>     }<br />>  <br />> A short return from tx_burst is the backpressure signal (transmit ring<br />> full, retry later). Here it is also used to mean "packet i is bad",<br />> and the bad mbuf is left owned by the caller. The application has no<br />> way to tell the two apart: the usual<br />>  <br />>     for (sent = 0; sent < n; )<br />>         sent += rte_eth_tx_burst(port, q, &pkts[sent], n - sent);<br />>  <br />> loop treats the short return as backpressure and resubmits pkts[i],<br />> which fails again every time -- head-of-line blocking, and the good<br />> packets after i (which had ring space) never go out.<br />>  <br />> A packet that cannot be sent must be consumed by the driver, not<br />> handed back. Free it in tx_burst, increment the tx error counter, and<br />> continue with the rest of the burst. For a burst of 16 where only<br />> index 3 is bad and the ring has room, tx_burst should return 16, with<br />> stats showing 15 transmitted and 1 tx error. A short return is then<br />> reserved for the one case the application is entitled to retry: ring<br />> full.<br /> <br /> <br />Thanks for the review.  <br /> <br />zxdh_xmit_pkts_simple is installed only when the application<br />does not request RTE_ETH_TX_OFFLOAD_MULTI_SEGS.<br />It is the fast path for single-segment traffic;<br />zxdh_xmit_pkts_packed is the general path that handles multi-segment,<br />full per-packet validation, and arbitrary headroom.<br /> <br />The simple path's precondition is data_off >= hdr_len.<br />static_assert(RTE_PKTMBUF_HEADROOM >= ZXDH_DL_NET_HDR_SIZE)<br />ensures default headroom fits the header,<br />so freshly allocated mbufs from a conformant mempool satisfy it.<br />The runtime break is a defensive guard, not the error path.<br /> <br />A short return signals "this batch is not for this path",not ring backpressure.<br />The caller should keep MULTI_SEGS enabled (so packed is selected)<br />or use the tx_pkt_prepare hook (zxdh_xmit_pkts_simple_prepare),<br />which already validates data_off per packet and reports the offending index.<br /> <br />Adding free-and-compact into the simple path would<br />reintroduce a per-packet branch and an in-place compaction<br />loop on every burst — the overhead the fast path exists to avoid.<br /> <br />To make this explicit: zxdh_xmit_pkts_simple is restricted to<br />single-segment mbufs with data_off >= hdr_len; anything outside the<br />contract — including reduced-headroom mbufs — can go through<br />zxdh_xmit_pkts_packed.<br />