LCOV - code coverage report
Current view: top level - drivers/net/zxdh - zxdh_rxtx.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 436 0.0 %
Date: 2026-10-01 18:19:24 Functions: 0 15 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 250 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(c) 2024 ZTE Corporation
       3                 :            :  */
       4                 :            : 
       5                 :            : #include <stdint.h>
       6                 :            : #include <stdalign.h>
       7                 :            : 
       8                 :            : #include <rte_net.h>
       9                 :            : 
      10                 :            : #include "zxdh_logs.h"
      11                 :            : #include "zxdh_pci.h"
      12                 :            : #include "zxdh_common.h"
      13                 :            : #include "zxdh_rxtx.h"
      14                 :            : #include "zxdh_queue.h"
      15                 :            : 
      16                 :            : #define ZXDH_SVLAN_TPID                       0x88a8
      17                 :            : #define ZXDH_CVLAN_TPID                       0x8100
      18                 :            : 
      19                 :            : #define ZXDH_PKT_FORM_CPU                     0x20    /* 1-cpu 0-np */
      20                 :            : #define ZXDH_NO_IP_FRAGMENT                   0x2000  /* ip fragment flag */
      21                 :            : #define ZXDH_NO_IPID_UPDATE                   0x4000  /* ipid update flag */
      22                 :            : 
      23                 :            : #define ZXDH_PI_L3TYPE_IP                     0x00
      24                 :            : #define ZXDH_PI_L3TYPE_IPV6                   0x40
      25                 :            : #define ZXDH_PI_L3TYPE_NOIP                   0x80
      26                 :            : #define ZXDH_PI_L3TYPE_RSV                    0xC0
      27                 :            : #define ZXDH_PI_L3TYPE_MASK                   0xC0
      28                 :            : 
      29                 :            : #define  ZXDH_PD_OFFLOAD_SPEC_PHYPORT         (1 << 15)
      30                 :            : #define  ZXDH_PD_OFFLOAD_SVLAN_INSERT         (1 << 14)
      31                 :            : #define  ZXDH_PD_OFFLOAD_CVLAN_INSERT         (1 << 13)
      32                 :            : #define  ZXDH_PD_OFFLOAD_OUTER_IPCSUM         (1 << 12)
      33                 :            : #define  ZXDH_PD_OFFLOAD_PRIO_MASK            (0x7 << 8)
      34                 :            : #define  ZXDH_PD_OFFLOAD_DELAY_STAT           (1 << 7)
      35                 :            : 
      36                 :            : #define ZXDH_PCODE_MASK                       0x1F
      37                 :            : #define ZXDH_PCODE_IP_PKT_TYPE                0x01
      38                 :            : #define ZXDH_PCODE_TCP_PKT_TYPE               0x02
      39                 :            : #define ZXDH_PCODE_UDP_PKT_TYPE               0x03
      40                 :            : #define ZXDH_PCODE_NO_IP_PKT_TYPE             0x09
      41                 :            : #define ZXDH_PCODE_NO_REASSMBLE_TCP_PKT_TYPE  0x0C
      42                 :            : 
      43                 :            : /* Uplink pd header byte0~1 */
      44                 :            : #define ZXDH_MBUF_F_RX_OUTER_L4_CKSUM_BAD                0x00080000
      45                 :            : #define ZXDH_MBUF_F_RX_QINQ                              0x00100000
      46                 :            : #define ZXDH_MBUF_F_RX_SEC_OFFLOAD                       0x00200000
      47                 :            : #define ZXDH_MBUF_F_RX_QINQ_STRIPPED                     0x00400000
      48                 :            : #define FELX_4BYTE                                       0x00800000
      49                 :            : #define FELX_8BYTE                                       0x01000000
      50                 :            : #define ZXDH_MBUF_F_RX_FDIR_FLX_MASK                     0x01800000
      51                 :            : #define ZXDH_MBUF_F_RX_FDIR_ID                           0x02000000
      52                 :            : #define ZXDH_MBUF_F_RX_1588_TMST                         0x04000000
      53                 :            : #define ZXDH_MBUF_F_RX_1588_PTP                          0x08000000
      54                 :            : #define ZXDH_MBUF_F_RX_VLAN_STRIPPED                     0x10000000
      55                 :            : #define ZXDH_MBUF_F_RX_OUTER_IP_CKSUM_BAD                0x20000000
      56                 :            : #define ZXDH_MBUF_F_RX_FDIR                              0x40000000
      57                 :            : #define ZXDH_MBUF_F_RX_RSS_HASH                          0x80000000
      58                 :            : #define ZXDH_MBUF_F_RX_INNER_IP_CKSUM_BAD                0x00020000
      59                 :            : #define ZXDH_MBUF_RX_CHECKSUM_BASED_OUTER                0x00010000
      60                 :            : 
      61                 :            : /* Outer/Inner L2 type */
      62                 :            : #define ZXDH_PD_L2TYPE_MASK                              0xf000
      63                 :            : #define ZXDH_PTYPE_L2_ETHER                              0x1000
      64                 :            : #define ZXDH_PTYPE_L2_ETHER_TIMESYNC                     0x2000
      65                 :            : #define ZXDH_PTYPE_L2_ETHER_ARP                          0x3000
      66                 :            : #define ZXDH_PTYPE_L2_ETHER_LLDP                         0x4000
      67                 :            : #define ZXDH_PTYPE_L2_ETHER_NSH                          0x5000
      68                 :            : #define ZXDH_PTYPE_L2_ETHER_VLAN                         0x6000
      69                 :            : #define ZXDH_PTYPE_L2_ETHER_QINQ                         0x7000
      70                 :            : #define ZXDH_PTYPE_L2_ETHER_PPPOE                        0x8000
      71                 :            : #define ZXDH_PTYPE_L2_ETHER_FCOE                         0x9000
      72                 :            : #define ZXDH_PTYPE_L2_ETHER_MPLS                         0xa000
      73                 :            : 
      74                 :            : /* Outer/Inner L3 type */
      75                 :            : #define ZXDH_PD_L3TYPE_MASK                              0x0f00
      76                 :            : #define ZXDH_PTYPE_L3_IPV4                               0x0100
      77                 :            : #define ZXDH_PTYPE_L3_IPV4_EXT                           0x0200
      78                 :            : #define ZXDH_PTYPE_L3_IPV6                               0x0300
      79                 :            : #define ZXDH_PTYPE_L3_IPV4_EXT_UNKNOWN                   0x0400
      80                 :            : #define ZXDH_PTYPE_L3_IPV6_EXT                           0x0500
      81                 :            : #define ZXDH_PTYPE_L3_IPV6_EXT_UNKNOWN                   0x0600
      82                 :            : 
      83                 :            : /* Outer/Inner L4 type */
      84                 :            : #define ZXDH_PD_L4TYPE_MASK    0x00f0
      85                 :            : #define ZXDH_PTYPE_L4_TCP      0x0010
      86                 :            : #define ZXDH_PTYPE_L4_UDP      0x0020
      87                 :            : #define ZXDH_PTYPE_L4_FRAG     0x0030
      88                 :            : #define ZXDH_PTYPE_L4_SCTP     0x0040
      89                 :            : #define ZXDH_PTYPE_L4_ICMP     0x0050
      90                 :            : #define ZXDH_PTYPE_L4_NONFRAG  0x0060
      91                 :            : #define ZXDH_PTYPE_L4_IGMP     0x0070
      92                 :            : 
      93                 :            : #define ZXDH_TX_MAX_SEGS                      31
      94                 :            : #define ZXDH_RX_MAX_SEGS                      31
      95                 :            : 
      96                 :            : #define ZXDH_PI_LRO_FLAG    0x00000001
      97                 :            : 
      98                 :            : #define ZXDH_MIN_MSS                                     64
      99                 :            : #define ZXDH_VLAN_ID_MASK                                0xfff
     100                 :            : 
     101                 :            : #define ZXDH_MTU_MSS_UNIT_SHIFTBIT                       2
     102                 :            : #define ZXDH_MTU_MSS_MASK                                0xFFF
     103                 :            : #define ZXDH_PD_HDR_SIZE_MAX                             256
     104                 :            : 
     105                 :            : /* error code */
     106                 :            : #define ZXDH_UDP_CSUM_ERR  0x0020
     107                 :            : #define ZXDH_TCP_CSUM_ERR  0x0040
     108                 :            : #define ZXDH_IPV4_CSUM_ERR 0x0100
     109                 :            : 
     110                 :            : #define ZXDH_DTPOFFLOAD_MASK ( \
     111                 :            :                 RTE_MBUF_F_TX_IP_CKSUM |        \
     112                 :            :                 RTE_MBUF_F_TX_L4_MASK |         \
     113                 :            :                 RTE_MBUF_F_TX_TCP_SEG |         \
     114                 :            :                 RTE_MBUF_F_TX_SEC_OFFLOAD |     \
     115                 :            :                 RTE_MBUF_F_TX_UDP_SEG)
     116                 :            : 
     117                 :            : #define ZXDH_NEXT_CACHELINE_OFF_16B  (RTE_CACHE_LINE_SIZE / 16)
     118                 :            : 
     119                 :            : uint32_t zxdh_outer_l2_type[16] = {
     120                 :            :         0,
     121                 :            :         RTE_PTYPE_L2_ETHER,
     122                 :            :         RTE_PTYPE_L2_ETHER_TIMESYNC,
     123                 :            :         RTE_PTYPE_L2_ETHER_ARP,
     124                 :            :         RTE_PTYPE_L2_ETHER_LLDP,
     125                 :            :         RTE_PTYPE_L2_ETHER_NSH,
     126                 :            :         RTE_PTYPE_L2_ETHER_VLAN,
     127                 :            :         RTE_PTYPE_L2_ETHER_QINQ,
     128                 :            :         RTE_PTYPE_L2_ETHER_PPPOE,
     129                 :            :         RTE_PTYPE_L2_ETHER_FCOE,
     130                 :            :         RTE_PTYPE_L2_ETHER_MPLS,
     131                 :            : };
     132                 :            : 
     133                 :            : uint32_t zxdh_outer_l3_type[16] = {
     134                 :            :         0,
     135                 :            :         RTE_PTYPE_L3_IPV4,
     136                 :            :         RTE_PTYPE_L3_IPV4_EXT,
     137                 :            :         RTE_PTYPE_L3_IPV6,
     138                 :            :         RTE_PTYPE_L3_IPV4_EXT_UNKNOWN,
     139                 :            :         RTE_PTYPE_L3_IPV6_EXT,
     140                 :            :         RTE_PTYPE_L3_IPV6_EXT_UNKNOWN,
     141                 :            : };
     142                 :            : 
     143                 :            : uint32_t zxdh_outer_l4_type[16] = {
     144                 :            :         0,
     145                 :            :         RTE_PTYPE_L4_TCP,
     146                 :            :         RTE_PTYPE_L4_UDP,
     147                 :            :         RTE_PTYPE_L4_FRAG,
     148                 :            :         RTE_PTYPE_L4_SCTP,
     149                 :            :         RTE_PTYPE_L4_ICMP,
     150                 :            :         RTE_PTYPE_L4_NONFRAG,
     151                 :            :         RTE_PTYPE_L4_IGMP,
     152                 :            : };
     153                 :            : 
     154                 :            : uint32_t zxdh_tunnel_type[16] = {
     155                 :            :         0,
     156                 :            :         RTE_PTYPE_TUNNEL_IP,
     157                 :            :         RTE_PTYPE_TUNNEL_GRE,
     158                 :            :         RTE_PTYPE_TUNNEL_VXLAN,
     159                 :            :         RTE_PTYPE_TUNNEL_NVGRE,
     160                 :            :         RTE_PTYPE_TUNNEL_GENEVE,
     161                 :            :         RTE_PTYPE_TUNNEL_GRENAT,
     162                 :            :         RTE_PTYPE_TUNNEL_GTPC,
     163                 :            :         RTE_PTYPE_TUNNEL_GTPU,
     164                 :            :         RTE_PTYPE_TUNNEL_ESP,
     165                 :            :         RTE_PTYPE_TUNNEL_L2TP,
     166                 :            :         RTE_PTYPE_TUNNEL_VXLAN_GPE,
     167                 :            :         RTE_PTYPE_TUNNEL_MPLS_IN_GRE,
     168                 :            :         RTE_PTYPE_TUNNEL_MPLS_IN_UDP,
     169                 :            : };
     170                 :            : 
     171                 :            : uint32_t zxdh_inner_l2_type[16] = {
     172                 :            :         0,
     173                 :            :         RTE_PTYPE_INNER_L2_ETHER,
     174                 :            :         0,
     175                 :            :         0,
     176                 :            :         0,
     177                 :            :         0,
     178                 :            :         RTE_PTYPE_INNER_L2_ETHER_VLAN,
     179                 :            :         RTE_PTYPE_INNER_L2_ETHER_QINQ,
     180                 :            :         0,
     181                 :            :         0,
     182                 :            :         0,
     183                 :            : };
     184                 :            : 
     185                 :            : uint32_t zxdh_inner_l3_type[16] = {
     186                 :            :         0,
     187                 :            :         RTE_PTYPE_INNER_L3_IPV4,
     188                 :            :         RTE_PTYPE_INNER_L3_IPV4_EXT,
     189                 :            :         RTE_PTYPE_INNER_L3_IPV6,
     190                 :            :         RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN,
     191                 :            :         RTE_PTYPE_INNER_L3_IPV6_EXT,
     192                 :            :         RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN,
     193                 :            : };
     194                 :            : 
     195                 :            : uint32_t zxdh_inner_l4_type[16] = {
     196                 :            :         0,
     197                 :            :         RTE_PTYPE_INNER_L4_TCP,
     198                 :            :         RTE_PTYPE_INNER_L4_UDP,
     199                 :            :         RTE_PTYPE_INNER_L4_FRAG,
     200                 :            :         RTE_PTYPE_INNER_L4_SCTP,
     201                 :            :         RTE_PTYPE_INNER_L4_ICMP,
     202                 :            :         0,
     203                 :            :         0,
     204                 :            : };
     205                 :            : 
     206                 :            : static inline uint16_t
     207                 :            : zxdh_get_mtu(struct zxdh_virtqueue *vq)
     208                 :            : {
     209                 :          0 :         struct rte_eth_dev *eth_dev = vq->hw->eth_dev;
     210                 :            : 
     211                 :          0 :         return eth_dev->data->mtu;
     212                 :            : }
     213                 :            : 
     214                 :            : static void
     215                 :          0 : zxdh_xmit_fill_net_hdr(struct zxdh_virtqueue *vq, struct rte_mbuf *cookie,
     216                 :            :                                 struct zxdh_net_hdr_dl *hdr)
     217                 :            : {
     218                 :            :         uint16_t mtu_or_mss = 0;
     219                 :            :         uint16_t pkt_flag_lw16 = ZXDH_NO_IPID_UPDATE;
     220                 :            :         uint16_t l3_offset;
     221                 :            :         uint8_t pcode = ZXDH_PCODE_NO_IP_PKT_TYPE;
     222                 :            :         uint8_t l3_ptype = ZXDH_PI_L3TYPE_NOIP;
     223                 :            :         struct zxdh_pi_hdr *pi_hdr = NULL;
     224                 :            :         struct zxdh_pd_hdr_dl *pd_hdr = NULL;
     225                 :          0 :         struct zxdh_hw *hw = vq->hw;
     226                 :          0 :         struct zxdh_net_hdr_dl *net_hdr_dl = hw->net_hdr_dl;
     227                 :          0 :         uint8_t hdr_len = hw->dl_net_hdr_len;
     228                 :            :         uint32_t ol_flag = 0;
     229                 :            : 
     230         [ #  # ]:          0 :         rte_memcpy(hdr, net_hdr_dl, hdr_len);
     231         [ #  # ]:          0 :         if (hw->has_tx_offload) {
     232                 :            :                 pi_hdr = &hdr->pipd_hdr_dl.pi_hdr;
     233                 :          0 :                 pd_hdr = &hdr->pipd_hdr_dl.pd_hdr;
     234                 :            : 
     235                 :            :                 pcode = ZXDH_PCODE_IP_PKT_TYPE;
     236         [ #  # ]:          0 :                 if (cookie->ol_flags & RTE_MBUF_F_TX_IPV6)
     237                 :            :                         l3_ptype = ZXDH_PI_L3TYPE_IPV6;
     238         [ #  # ]:          0 :                 else if (cookie->ol_flags & RTE_MBUF_F_TX_IPV4)
     239                 :            :                         l3_ptype = ZXDH_PI_L3TYPE_IP;
     240                 :            :                 else
     241                 :            :                         pcode = ZXDH_PCODE_NO_IP_PKT_TYPE;
     242                 :            : 
     243         [ #  # ]:          0 :                 if (cookie->ol_flags & RTE_MBUF_F_TX_TCP_SEG) {
     244                 :          0 :                         mtu_or_mss = (cookie->tso_segsz >= ZXDH_MIN_MSS)
     245                 :            :                                 ? cookie->tso_segsz
     246                 :            :                                 : ZXDH_MIN_MSS;
     247                 :          0 :                         pi_hdr->pkt_flag_hi8  |= ZXDH_TX_TCPUDP_CKSUM_CAL;
     248                 :            :                         pkt_flag_lw16 |= ZXDH_NO_IP_FRAGMENT | ZXDH_TX_IP_CKSUM_CAL;
     249                 :            :                         pcode = ZXDH_PCODE_TCP_PKT_TYPE;
     250         [ #  # ]:          0 :                 } else if (cookie->ol_flags & RTE_MBUF_F_TX_UDP_SEG) {
     251                 :            :                         mtu_or_mss = zxdh_get_mtu(vq);
     252                 :          0 :                         mtu_or_mss = (mtu_or_mss >= ZXDH_MIN_MSS) ? mtu_or_mss : ZXDH_MIN_MSS;
     253                 :            :                         pkt_flag_lw16 |= ZXDH_TX_IP_CKSUM_CAL;
     254                 :          0 :                         pi_hdr->pkt_flag_hi8 |= ZXDH_NO_TCP_FRAGMENT | ZXDH_TX_TCPUDP_CKSUM_CAL;
     255                 :            :                         pcode = ZXDH_PCODE_UDP_PKT_TYPE;
     256                 :            :                 } else {
     257                 :            :                         pkt_flag_lw16 |= ZXDH_NO_IP_FRAGMENT;
     258                 :          0 :                         pi_hdr->pkt_flag_hi8 |= ZXDH_NO_TCP_FRAGMENT;
     259                 :            :                 }
     260                 :            : 
     261         [ #  # ]:          0 :                 if (cookie->ol_flags & RTE_MBUF_F_TX_IP_CKSUM)
     262                 :          0 :                         pkt_flag_lw16 |= ZXDH_TX_IP_CKSUM_CAL;
     263                 :            : 
     264         [ #  # ]:          0 :                 if ((cookie->ol_flags & RTE_MBUF_F_TX_UDP_CKSUM) ==
     265                 :            :                         RTE_MBUF_F_TX_UDP_CKSUM){
     266                 :            :                         pcode = ZXDH_PCODE_UDP_PKT_TYPE;
     267                 :          0 :                         pi_hdr->pkt_flag_hi8 |= ZXDH_TX_TCPUDP_CKSUM_CAL;
     268         [ #  # ]:          0 :                 } else if ((cookie->ol_flags & RTE_MBUF_F_TX_TCP_CKSUM) ==
     269                 :            :                                  RTE_MBUF_F_TX_TCP_CKSUM) {
     270                 :            :                         pcode = ZXDH_PCODE_TCP_PKT_TYPE;
     271                 :          0 :                         pi_hdr->pkt_flag_hi8 |= ZXDH_TX_TCPUDP_CKSUM_CAL;
     272                 :            :                 }
     273                 :            : 
     274                 :          0 :                 pkt_flag_lw16 |= (mtu_or_mss >> ZXDH_MTU_MSS_UNIT_SHIFTBIT) & ZXDH_MTU_MSS_MASK;
     275         [ #  # ]:          0 :                 pi_hdr->pkt_flag_lw16 = rte_be_to_cpu_16(pkt_flag_lw16);
     276                 :          0 :                 pi_hdr->pkt_type = l3_ptype | ZXDH_PKT_FORM_CPU | pcode;
     277                 :            : 
     278                 :          0 :                 l3_offset = hdr_len + cookie->l2_len;
     279         [ #  # ]:          0 :                 l3_offset += (cookie->ol_flags & RTE_MBUF_F_TX_TUNNEL_MASK) ?
     280                 :          0 :                                         cookie->outer_l2_len + cookie->outer_l3_len : 0;
     281         [ #  # ]:          0 :                 pi_hdr->l3_offset = rte_be_to_cpu_16(l3_offset);
     282         [ #  # ]:          0 :                 pi_hdr->l4_offset = rte_be_to_cpu_16(l3_offset + cookie->l3_len);
     283         [ #  # ]:          0 :                 if (cookie->ol_flags & RTE_MBUF_F_TX_OUTER_IP_CKSUM)
     284                 :            :                         ol_flag |= ZXDH_PD_OFFLOAD_OUTER_IPCSUM;
     285                 :            :         } else {
     286                 :          0 :                 pd_hdr = &hdr->pd_hdr;
     287                 :            :         }
     288                 :            : 
     289         [ #  # ]:          0 :         if (cookie->ol_flags & (RTE_MBUF_F_TX_VLAN | RTE_MBUF_F_TX_QINQ)) {
     290                 :          0 :                 ol_flag |= ZXDH_PD_OFFLOAD_CVLAN_INSERT;
     291         [ #  # ]:          0 :                 pd_hdr->cvlan_insert = rte_be_to_cpu_16(cookie->vlan_tci);
     292         [ #  # ]:          0 :                 if (unlikely(cookie->ol_flags & RTE_MBUF_F_TX_QINQ)) {
     293                 :          0 :                         ol_flag |= ZXDH_PD_OFFLOAD_SVLAN_INSERT;
     294         [ #  # ]:          0 :                         pd_hdr->svlan_insert = rte_be_to_cpu_16(cookie->vlan_tci_outer);
     295                 :            :                 }
     296                 :            :         }
     297                 :            : 
     298         [ #  # ]:          0 :         pd_hdr->ol_flag = rte_be_to_cpu_16(ol_flag);
     299                 :          0 : }
     300                 :            : 
     301                 :            : static inline void
     302                 :          0 : zxdh_xmit_enqueue_push(struct zxdh_virtnet_tx *txvq,
     303                 :            :                                                 struct rte_mbuf *cookie)
     304                 :            : {
     305                 :          0 :         struct zxdh_virtqueue *vq = txvq->vq;
     306                 :          0 :         uint16_t id = vq->vq_avail_idx;
     307                 :          0 :         struct zxdh_vq_desc_extra *dxp = &vq->vq_descx[id];
     308                 :          0 :         uint16_t flags = vq->cached_flags;
     309                 :            :         struct zxdh_net_hdr_dl *hdr = NULL;
     310                 :          0 :         uint8_t hdr_len = vq->hw->dl_net_hdr_len;
     311                 :          0 :         struct zxdh_vring_packed_desc *dp = &vq->vq_packed.ring.desc[id];
     312                 :            : 
     313                 :          0 :         dxp->cookie = cookie;
     314                 :          0 :         hdr = rte_pktmbuf_mtod_offset(cookie, struct zxdh_net_hdr_dl *, -hdr_len);
     315                 :          0 :         zxdh_xmit_fill_net_hdr(vq, cookie, hdr);
     316                 :            : 
     317                 :          0 :         dp->addr = rte_pktmbuf_iova(cookie) - hdr_len;
     318                 :          0 :         dp->len  = cookie->data_len + hdr_len;
     319                 :          0 :         dp->id   = id;
     320         [ #  # ]:          0 :         if (++vq->vq_avail_idx >= vq->vq_nentries) {
     321                 :          0 :                 vq->vq_avail_idx -= vq->vq_nentries;
     322                 :          0 :                 vq->cached_flags ^= ZXDH_VRING_PACKED_DESC_F_AVAIL_USED;
     323                 :            :         }
     324                 :          0 :         vq->vq_free_cnt--;
     325                 :            :         zxdh_queue_store_flags_packed(dp, flags);
     326                 :          0 : }
     327                 :            : 
     328                 :            : static inline void
     329                 :          0 : zxdh_xmit_enqueue_append(struct zxdh_virtnet_tx *txvq,
     330                 :            :                                                 struct rte_mbuf *cookie,
     331                 :            :                                                 uint16_t needed)
     332                 :            : {
     333                 :          0 :         struct zxdh_tx_region *txr = txvq->zxdh_net_hdr_mz->addr;
     334                 :          0 :         struct zxdh_virtqueue *vq = txvq->vq;
     335                 :          0 :         uint16_t head_idx = vq->vq_avail_idx;
     336                 :            :         uint16_t idx = head_idx;
     337                 :          0 :         struct zxdh_vring_packed_desc *start_dp = vq->vq_packed.ring.desc;
     338                 :          0 :         struct zxdh_vring_packed_desc *head_dp = &vq->vq_packed.ring.desc[idx];
     339                 :            :         struct zxdh_net_hdr_dl *hdr = NULL;
     340                 :            : 
     341                 :            :         uint16_t id = vq->vq_avail_idx;
     342                 :          0 :         struct zxdh_vq_desc_extra *dxp = &vq->vq_descx[id];
     343                 :          0 :         uint8_t hdr_len = vq->hw->dl_net_hdr_len;
     344                 :            :         uint16_t head_flags = 0;
     345                 :            : 
     346                 :          0 :         dxp->cookie = NULL;
     347                 :            :         /*
     348                 :            :          * Head descriptor has no mbuf cookie. Per-segment cookies are
     349                 :            :          * stored on the segment descs so zxdh_xmit_fast_flush() can free
     350                 :            :          * each via rte_pktmbuf_free_seg(). zxdh_queue_detach_unused() walks
     351                 :            :          * the cookies on queue teardown and is the only reader that would
     352                 :            :          * otherwise observe a stray head cookie.
     353                 :            :          */
     354                 :            : 
     355                 :            :         /* setup first tx ring slot to point to header stored in reserved region. */
     356                 :          0 :         start_dp[idx].addr = txvq->zxdh_net_hdr_mem + RTE_PTR_DIFF(&txr[idx].tx_hdr, txr);
     357                 :          0 :         start_dp[idx].len  = hdr_len;
     358                 :          0 :         start_dp[idx].id = idx;
     359                 :          0 :         head_flags |= vq->cached_flags | ZXDH_VRING_DESC_F_NEXT;
     360                 :            :         hdr = (void *)&txr[idx].tx_hdr;
     361                 :            : 
     362                 :          0 :         zxdh_xmit_fill_net_hdr(vq, cookie, hdr);
     363                 :            : 
     364                 :          0 :         idx++;
     365         [ #  # ]:          0 :         if (idx >= vq->vq_nentries) {
     366                 :          0 :                 idx -= vq->vq_nentries;
     367                 :          0 :                 vq->cached_flags ^= ZXDH_VRING_PACKED_DESC_F_AVAIL_USED;
     368                 :            :         }
     369                 :            : 
     370                 :            :         do {
     371                 :          0 :                 start_dp[idx].addr = rte_pktmbuf_iova(cookie);
     372                 :          0 :                 start_dp[idx].len  = cookie->data_len;
     373                 :          0 :                 start_dp[idx].id = idx;
     374                 :            : 
     375                 :          0 :                 vq->vq_descx[idx].cookie = cookie;
     376                 :          0 :                 uint16_t flags = cookie->next ? ZXDH_VRING_DESC_F_NEXT : 0;
     377                 :          0 :                 flags |= vq->cached_flags;
     378                 :          0 :                 start_dp[idx].flags = flags;
     379                 :            : 
     380                 :          0 :                 idx++;
     381         [ #  # ]:          0 :                 if (idx >= vq->vq_nentries) {
     382                 :          0 :                         idx -= vq->vq_nentries;
     383                 :          0 :                         vq->cached_flags ^= ZXDH_VRING_PACKED_DESC_F_AVAIL_USED;
     384                 :            :                 }
     385         [ #  # ]:          0 :         } while ((cookie = cookie->next) != NULL);
     386                 :            : 
     387                 :          0 :         vq->vq_free_cnt = (uint16_t)(vq->vq_free_cnt - needed);
     388                 :          0 :         vq->vq_avail_idx = idx;
     389                 :            : 
     390                 :            :         zxdh_queue_store_flags_packed(head_dp, head_flags);
     391                 :          0 : }
     392                 :            : 
     393                 :            : static void
     394                 :            : zxdh_update_packet_stats(struct zxdh_virtnet_stats *stats, struct rte_mbuf *mbuf)
     395                 :            : {
     396                 :          0 :         uint32_t s = mbuf->pkt_len;
     397                 :            : 
     398                 :          0 :         stats->bytes += s;
     399                 :            : }
     400                 :            : 
     401                 :            : static void
     402                 :          0 : zxdh_xmit_fast_flush(struct zxdh_virtqueue *vq)
     403                 :            : {
     404                 :            :         uint16_t id       = 0;
     405                 :            :         uint16_t curr_id  = 0;
     406                 :            :         uint16_t free_cnt = 0;
     407                 :          0 :         uint16_t size     = vq->vq_nentries;
     408                 :          0 :         struct zxdh_vring_packed_desc *desc = vq->vq_packed.ring.desc;
     409                 :            :         struct zxdh_vq_desc_extra     *dxp  = NULL;
     410                 :          0 :         uint16_t used_idx = vq->vq_used_cons_idx;
     411                 :            :         uint16_t budget = size;
     412                 :            : 
     413                 :            :         /*
     414                 :            :          * The function desc_is_used performs a load-acquire operation
     415                 :            :          * or calls rte_io_rmb to ensure memory consistency. It waits
     416                 :            :          * for a used descriptor in the virtqueue.
     417                 :            :          */
     418         [ #  # ]:          0 :         while (budget > 0 && desc_is_used(&desc[used_idx], vq)) {
     419                 :            :                 /*
     420                 :            :                  * vq_nentries is validated as power-of-two in
     421                 :            :                  * zxdh_queue_desc_pre_setup(), so mask the prefetch index to keep
     422                 :            :                  * it inside desc[] when used_idx is near the end of the ring.
     423                 :            :                  */
     424                 :          0 :                 rte_prefetch0(&desc[(used_idx + ZXDH_NEXT_CACHELINE_OFF_16B) & (size - 1)]);
     425                 :          0 :                 id = desc[used_idx].id;
     426         [ #  # ]:          0 :                 if (unlikely(id >= size))
     427                 :            :                         break;
     428                 :            :                 do {
     429                 :          0 :                         desc[used_idx].id = used_idx;
     430                 :            :                         curr_id = used_idx;
     431                 :          0 :                         dxp = &vq->vq_descx[used_idx];
     432         [ #  # ]:          0 :                         if (dxp->cookie != NULL) {
     433                 :            :                                 rte_pktmbuf_free_seg(dxp->cookie);
     434                 :          0 :                                 dxp->cookie = NULL;
     435                 :            :                         }
     436                 :          0 :                         used_idx += 1;
     437                 :          0 :                         free_cnt += 1;
     438                 :          0 :                         budget -= 1;
     439         [ #  # ]:          0 :                         if (unlikely(used_idx == size)) {
     440                 :            :                                 used_idx = 0;
     441                 :          0 :                                 vq->used_wrap_counter ^= 1;
     442                 :            :                         }
     443         [ #  # ]:          0 :                         if (unlikely(budget == 0))
     444                 :            :                                 break;
     445         [ #  # ]:          0 :                 } while (curr_id != id);
     446                 :            :         }
     447                 :          0 :         vq->vq_used_cons_idx = used_idx;
     448                 :          0 :         vq->vq_free_cnt += free_cnt;
     449                 :          0 : }
     450                 :            : 
     451                 :            : uint16_t
     452                 :          0 : zxdh_xmit_pkts_packed(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
     453                 :            : {
     454                 :            :         struct zxdh_virtnet_tx *txvq = tx_queue;
     455                 :          0 :         struct zxdh_virtqueue  *vq   = txvq->vq;
     456                 :            :         uint16_t nb_tx = 0;
     457                 :            : 
     458                 :          0 :         zxdh_xmit_fast_flush(vq);
     459                 :            : 
     460         [ #  # ]:          0 :         for (nb_tx = 0; nb_tx < nb_pkts; nb_tx++) {
     461                 :          0 :                 struct rte_mbuf *txm = tx_pkts[nb_tx];
     462                 :            :                 int32_t can_push     = 0;
     463                 :            :                 int32_t slots        = 0;
     464                 :            : 
     465                 :            :                 rte_prefetch0(txm);
     466                 :            :                 /* optimize ring usage */
     467         [ #  # ]:          0 :                 if (rte_mbuf_refcnt_read(txm) == 1 &&
     468         [ #  # ]:          0 :                         RTE_MBUF_DIRECT(txm) &&
     469         [ #  # ]:          0 :                         txm->nb_segs == 1 &&
     470         [ #  # ]:          0 :                         txm->data_off >= ZXDH_DL_NET_HDR_SIZE) {
     471                 :            :                         can_push = 1;
     472                 :            :                 }
     473                 :            :                 /**
     474                 :            :                  * How many main ring entries are needed to this Tx?
     475                 :            :                  * indirect   => 1
     476                 :            :                  * any_layout => number of segments
     477                 :            :                  * default    => number of segments + 1
     478                 :            :                  **/
     479                 :          0 :                 slots = txm->nb_segs + !can_push;
     480                 :            : 
     481         [ #  # ]:          0 :                 if (unlikely(slots > vq->vq_free_cnt))
     482                 :            :                         break;
     483                 :            : 
     484                 :            :                 /* Enqueue Packet buffers */
     485         [ #  # ]:          0 :                 if (can_push)
     486                 :          0 :                         zxdh_xmit_enqueue_push(txvq, txm);
     487                 :            :                 else
     488                 :          0 :                         zxdh_xmit_enqueue_append(txvq, txm, slots);
     489                 :            :                 zxdh_update_packet_stats(&txvq->stats, txm);
     490                 :            :         }
     491                 :          0 :         txvq->stats.packets += nb_tx;
     492         [ #  # ]:          0 :         if (likely(nb_tx))
     493                 :          0 :                 zxdh_queue_notify(vq);
     494                 :          0 :         return nb_tx;
     495                 :            : }
     496                 :            : 
     497                 :          0 : static inline int dl_net_hdr_check(struct rte_mbuf *m, struct zxdh_hw *hw)
     498                 :            : {
     499   [ #  #  #  # ]:          0 :         if ((m->ol_flags & ZXDH_DTPOFFLOAD_MASK) && !hw->has_tx_offload) {
     500                 :          0 :                 PMD_TX_LOG(ERR, "port:[%d], vfid[%d]. "
     501                 :            :                                         "not support tx_offload", hw->port_id, hw->vfid);
     502                 :          0 :                 return -EINVAL;
     503                 :            :         }
     504                 :            :         return 0;
     505                 :            : }
     506                 :            : 
     507                 :          0 : uint16_t zxdh_xmit_pkts_prepare(void *tx_queue, struct rte_mbuf **tx_pkts,
     508                 :            :                                 uint16_t nb_pkts)
     509                 :            : {
     510                 :            :         struct zxdh_virtnet_tx *txvq = tx_queue;
     511                 :          0 :         struct zxdh_hw *hw = txvq->vq->hw;
     512                 :            :         uint16_t nb_tx;
     513                 :            : 
     514         [ #  # ]:          0 :         for (nb_tx = 0; nb_tx < nb_pkts; nb_tx++) {
     515                 :          0 :                 struct rte_mbuf *m = tx_pkts[nb_tx];
     516                 :            :                 int32_t error;
     517                 :            : 
     518                 :            : #ifdef RTE_LIBRTE_ETHDEV_DEBUG
     519                 :            :                 error = rte_validate_tx_offload(m);
     520                 :            :                 if (unlikely(error)) {
     521                 :            :                         rte_errno = -error;
     522                 :            :                         break;
     523                 :            :                 }
     524                 :            : #endif
     525                 :            : 
     526                 :            :                 error = rte_net_intel_cksum_prepare(m);
     527         [ #  # ]:          0 :                 if (unlikely(error)) {
     528                 :          0 :                         rte_errno = -error;
     529                 :          0 :                         break;
     530                 :            :                 }
     531         [ #  # ]:          0 :                 if (m->nb_segs > ZXDH_TX_MAX_SEGS) {
     532                 :          0 :                         PMD_TX_LOG(ERR, "%d segs dropped", m->nb_segs);
     533                 :          0 :                         txvq->stats.truncated_err += nb_pkts - nb_tx;
     534                 :          0 :                         rte_errno = ENOMEM;
     535                 :          0 :                         break;
     536                 :            :                 }
     537                 :            : 
     538                 :          0 :                 error = dl_net_hdr_check(m, hw);
     539         [ #  # ]:          0 :                 if (unlikely(error)) {
     540                 :          0 :                         rte_errno = ENOTSUP;
     541                 :          0 :                         txvq->stats.errors += nb_pkts - nb_tx;
     542                 :          0 :                         txvq->stats.offload_cfg_err += nb_pkts - nb_tx;
     543                 :          0 :                         break;
     544                 :            :                 }
     545                 :            :         }
     546                 :          0 :         return nb_tx;
     547                 :            : }
     548                 :            : 
     549                 :            : static uint16_t
     550                 :          0 : zxdh_dequeue_burst_rx_packed(struct zxdh_virtqueue *vq,
     551                 :            :                                         struct rte_mbuf **rx_pkts,
     552                 :            :                                         uint32_t *len,
     553                 :            :                                         uint16_t num)
     554                 :            : {
     555                 :          0 :         struct zxdh_vring_packed_desc *desc = vq->vq_packed.ring.desc;
     556                 :            :         struct rte_mbuf *cookie = NULL;
     557                 :            :         uint16_t i, used_idx;
     558                 :            :         uint16_t id;
     559                 :            : 
     560                 :          0 :         used_idx = vq->vq_used_cons_idx;
     561                 :          0 :         rte_prefetch0(&desc[used_idx]);
     562                 :            : 
     563         [ #  # ]:          0 :         for (i = 0; i < num; i++) {
     564                 :          0 :                 used_idx = vq->vq_used_cons_idx;
     565                 :            :                 /* desc_is_used has a load-acquire or rte_io_rmb inside
     566                 :            :                  * and wait for used desc in virtqueue.
     567                 :            :                  */
     568                 :          0 :                 if (!desc_is_used(&desc[used_idx], vq))
     569                 :          0 :                         return i;
     570                 :          0 :                 len[i] = desc[used_idx].len;
     571                 :          0 :                 id = desc[used_idx].id;
     572                 :          0 :                 cookie = (struct rte_mbuf *)vq->vq_descx[id].cookie;
     573                 :          0 :                 vq->vq_descx[id].cookie = NULL;
     574         [ #  # ]:          0 :                 if (unlikely(cookie == NULL)) {
     575                 :          0 :                         PMD_RX_LOG(ERR,
     576                 :            :                                 "vring descriptor with no mbuf cookie at %u", vq->vq_used_cons_idx);
     577                 :          0 :                         break;
     578                 :            :                 }
     579                 :            :                 rte_prefetch0(cookie);
     580                 :            :                 rte_packet_prefetch(rte_pktmbuf_mtod(cookie, void *));
     581                 :          0 :                 rx_pkts[i] = cookie;
     582                 :          0 :                 vq->vq_free_cnt++;
     583                 :          0 :                 vq->vq_used_cons_idx++;
     584         [ #  # ]:          0 :                 if (vq->vq_used_cons_idx >= vq->vq_nentries) {
     585                 :          0 :                         vq->vq_used_cons_idx -= vq->vq_nentries;
     586                 :          0 :                         vq->used_wrap_counter ^= 1;
     587                 :            :                 }
     588                 :            :         }
     589                 :            :         return i;
     590                 :            : }
     591                 :            : 
     592                 :            : static inline void
     593                 :          0 : update_outer_rx_l4_csum(struct zxdh_hw *hw, struct zxdh_pi_hdr *pi_hdr,
     594                 :            :                 struct zxdh_pd_hdr_ul *pd_hdr, struct rte_mbuf *m)
     595                 :            : {
     596         [ #  # ]:          0 :         uint32_t pd_pkt_flag = ntohl(pd_hdr->pkt_flag);
     597                 :            :         uint32_t packet_type = 0;
     598                 :            :         uint32_t idx = 0;
     599                 :          0 :         bool has_ip_verify = hw->eth_dev->data->dev_conf.rxmode.offloads &
     600                 :            :                         RTE_ETH_RX_OFFLOAD_IPV4_CKSUM;
     601         [ #  # ]:          0 :         uint16_t pkt_type_in = rte_be_to_cpu_16(pd_hdr->pkt_type_in);
     602                 :            : 
     603                 :            :         /* pi_hdr as outer csum and pd_hdr as inner csum */
     604         [ #  # ]:          0 :         if ((pd_pkt_flag & ZXDH_MBUF_RX_CHECKSUM_BASED_OUTER)) {
     605                 :          0 :                 m->ol_flags &= ~RTE_MBUF_F_RX_L4_CKSUM_MASK;
     606                 :          0 :                 m->ol_flags &= ~RTE_MBUF_F_RX_IP_CKSUM_MASK;
     607                 :            : 
     608         [ #  # ]:          0 :                 if (pi_hdr) {
     609         [ #  # ]:          0 :                         uint16_t err_code = rte_be_to_cpu_16(pi_hdr->ul.err_code);
     610         [ #  # ]:          0 :                         if (pi_hdr->pkt_flag_hi8 & ZXDH_RX_TCPUDP_CKSUM_VERIFY) {
     611         [ #  # ]:          0 :                                 if (err_code & ZXDH_UDP_CSUM_ERR)
     612                 :          0 :                                         m->ol_flags |= RTE_MBUF_F_RX_OUTER_L4_CKSUM_BAD;
     613                 :            :                                 else
     614                 :          0 :                                         m->ol_flags |= RTE_MBUF_F_RX_OUTER_L4_CKSUM_GOOD;
     615                 :            :                         }
     616                 :            : 
     617         [ #  # ]:          0 :                         if (pi_hdr->pkt_flag_hi8 & ZXDH_RX_IP_CKSUM_VERIFY) {
     618         [ #  # ]:          0 :                                 if (err_code & ZXDH_IPV4_CSUM_ERR)
     619                 :          0 :                                         m->ol_flags |= RTE_MBUF_F_RX_OUTER_IP_CKSUM_BAD;
     620                 :            :                         }
     621                 :            :                 }
     622         [ #  # ]:          0 :                 if (pd_pkt_flag & ZXDH_MBUF_F_RX_INNER_IP_CKSUM_BAD) {
     623                 :          0 :                         m->ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_BAD;
     624                 :            :                 } else {
     625         [ #  # ]:          0 :                         if (has_ip_verify) {
     626                 :          0 :                                 idx = (pkt_type_in >> 8)  & 0xF;
     627                 :          0 :                                 packet_type = zxdh_inner_l3_type[idx];
     628                 :          0 :                                 if (((packet_type & RTE_PTYPE_INNER_L3_MASK) ==
     629         [ #  # ]:          0 :                                                 RTE_PTYPE_INNER_L3_IPV4) ||
     630                 :            :                                 ((packet_type & RTE_PTYPE_INNER_L3_MASK) ==
     631                 :            :                                                 RTE_PTYPE_INNER_L3_IPV4_EXT))
     632                 :          0 :                                         m->ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_GOOD;
     633                 :            :                         }
     634                 :            :                 }
     635                 :            : 
     636                 :            :         } else {
     637         [ #  # ]:          0 :                 if ((m->ol_flags & RTE_MBUF_F_RX_L4_CKSUM_BAD) ==
     638                 :            :                                 RTE_MBUF_F_RX_L4_CKSUM_BAD)
     639                 :            :                         m->ol_flags |= RTE_MBUF_F_RX_OUTER_L4_CKSUM_UNKNOWN;
     640         [ #  # ]:          0 :                 else if ((m->ol_flags & RTE_MBUF_F_RX_L4_CKSUM_GOOD) ==
     641                 :            :                                         RTE_MBUF_F_RX_L4_CKSUM_GOOD) {
     642         [ #  # ]:          0 :                         if (pd_pkt_flag & ZXDH_MBUF_F_RX_OUTER_L4_CKSUM_BAD)
     643                 :          0 :                                 m->ol_flags |= RTE_MBUF_F_RX_OUTER_L4_CKSUM_BAD;
     644                 :            :                         else
     645                 :          0 :                                 m->ol_flags |= RTE_MBUF_F_RX_OUTER_L4_CKSUM_GOOD;
     646                 :            :                 }
     647                 :            :         }
     648                 :          0 : }
     649                 :            : 
     650                 :            : static inline void
     651                 :          0 : zxdh_rx_update_mbuf(struct zxdh_hw *hw, struct rte_mbuf *m, struct zxdh_net_hdr_ul *hdr)
     652                 :            : {
     653                 :          0 :         uint8_t has_pi = (uint64_t)(hdr->type_hdr.pd_len << 1) > ZXDH_UL_NOPI_HDR_SIZE_MAX;
     654         [ #  # ]:          0 :         struct zxdh_pd_hdr_ul *pd_hdr = has_pi ? &hdr->pipd_hdr_ul.pd_hdr : &hdr->pd_hdr;
     655                 :            :         struct zxdh_pi_hdr *pi_hdr = NULL;
     656         [ #  # ]:          0 :         uint32_t pkt_flag = ntohl(pd_hdr->pkt_flag);
     657                 :            :         uint32_t idx = 0;
     658         [ #  # ]:          0 :         uint32_t striped_vlan_tci = rte_be_to_cpu_32(pd_hdr->striped_vlan_tci);
     659         [ #  # ]:          0 :         uint16_t pkt_type_outer = rte_be_to_cpu_16(pd_hdr->pkt_type_out);
     660         [ #  # ]:          0 :         uint16_t pkt_type_inner = rte_be_to_cpu_16(pd_hdr->pkt_type_in);
     661                 :            : 
     662         [ #  # ]:          0 :         if (unlikely(pkt_flag & (ZXDH_MBUF_F_RX_1588_PTP | ZXDH_MBUF_F_RX_1588_TMST))) {
     663         [ #  # ]:          0 :                 if (pkt_flag & ZXDH_MBUF_F_RX_1588_PTP)
     664                 :          0 :                         m->ol_flags |= RTE_MBUF_F_RX_IEEE1588_PTP;
     665         [ #  # ]:          0 :                 if (pkt_flag & ZXDH_MBUF_F_RX_1588_TMST)
     666                 :          0 :                         m->ol_flags |= RTE_MBUF_F_RX_IEEE1588_TMST;
     667                 :            :         }
     668                 :            : 
     669         [ #  # ]:          0 :         if (pkt_flag & ZXDH_MBUF_F_RX_VLAN_STRIPPED) {
     670                 :          0 :                 m->ol_flags |= (RTE_MBUF_F_RX_VLAN_STRIPPED | RTE_MBUF_F_RX_VLAN);
     671         [ #  # ]:          0 :                 m->vlan_tci = (unlikely(pkt_flag & ZXDH_MBUF_F_RX_QINQ))
     672                 :          0 :                                 ? (striped_vlan_tci >> 16) & ZXDH_VLAN_ID_MASK
     673                 :          0 :                                 : striped_vlan_tci & ZXDH_VLAN_ID_MASK;
     674                 :            :         }
     675                 :            : 
     676         [ #  # ]:          0 :         if (unlikely(pkt_flag & ZXDH_MBUF_F_RX_QINQ_STRIPPED)) {
     677                 :            :                 /*
     678                 :            :                  * When PKT_RX_QINQ_STRIPPED is set and PKT_RX_VLAN_STRIPPED is unset:
     679                 :            :                  * - Only the outer VLAN is removed from the packet data.
     680                 :            :                  * - Both TCI values are saved: the inner TCI in mbuf->vlan_tci and
     681                 :            :                  *   the outer TCI in mbuf->vlan_tci_outer.
     682                 :            :                  *
     683                 :            :                  * When PKT_RX_QINQ is set, PKT_RX_VLAN must also be set, and the inner
     684                 :            :                  * TCI is saved in mbuf->vlan_tci.
     685                 :            :                  */
     686                 :          0 :                 m->ol_flags |= (RTE_MBUF_F_RX_QINQ_STRIPPED | RTE_MBUF_F_RX_QINQ);
     687                 :          0 :                 m->ol_flags |= (RTE_MBUF_F_RX_VLAN_STRIPPED | RTE_MBUF_F_RX_VLAN);
     688                 :          0 :                 m->vlan_tci = striped_vlan_tci & ZXDH_VLAN_ID_MASK;
     689                 :          0 :                 m->vlan_tci_outer = (striped_vlan_tci >> 16) & ZXDH_VLAN_ID_MASK;
     690                 :            :         }
     691                 :            : 
     692                 :            :         /* rss hash/fd handle */
     693         [ #  # ]:          0 :         if (pkt_flag & ZXDH_MBUF_F_RX_RSS_HASH) {
     694         [ #  # ]:          0 :                 m->hash.rss = rte_be_to_cpu_32(pd_hdr->rss_hash);
     695                 :          0 :                 m->ol_flags |= RTE_MBUF_F_RX_RSS_HASH;
     696                 :            :         }
     697         [ #  # ]:          0 :         if (pkt_flag & ZXDH_MBUF_F_RX_FDIR) {
     698                 :          0 :                 m->ol_flags |= RTE_MBUF_F_RX_FDIR;
     699         [ #  # ]:          0 :                 if (pkt_flag & ZXDH_MBUF_F_RX_FDIR_ID) {
     700         [ #  # ]:          0 :                         m->hash.fdir.hi = rte_be_to_cpu_32(pd_hdr->fd);
     701                 :          0 :                         m->ol_flags |= RTE_MBUF_F_RX_FDIR_ID;
     702         [ #  # ]:          0 :                 } else if ((pkt_flag & ZXDH_MBUF_F_RX_FDIR_FLX_MASK) == FELX_4BYTE) {
     703         [ #  # ]:          0 :                         m->hash.fdir.hi = rte_be_to_cpu_32(pd_hdr->fd);
     704                 :          0 :                         m->ol_flags |= RTE_MBUF_F_RX_FDIR_FLX;
     705         [ #  # ]:          0 :                 } else if (((pkt_flag & ZXDH_MBUF_F_RX_FDIR_FLX_MASK) == FELX_8BYTE)) {
     706         [ #  # ]:          0 :                         m->hash.fdir.hi = rte_be_to_cpu_32(pd_hdr->rss_hash);
     707         [ #  # ]:          0 :                         m->hash.fdir.lo = rte_be_to_cpu_32(pd_hdr->fd);
     708                 :          0 :                         m->ol_flags |= RTE_MBUF_F_RX_FDIR_FLX;
     709                 :            :                 }
     710                 :            :         }
     711                 :            :         /* checksum handle */
     712         [ #  # ]:          0 :         if (pkt_flag & ZXDH_MBUF_F_RX_OUTER_IP_CKSUM_BAD)
     713                 :          0 :                 m->ol_flags |= RTE_MBUF_F_RX_OUTER_IP_CKSUM_BAD;
     714                 :            : 
     715         [ #  # ]:          0 :         if (has_pi) {
     716                 :          0 :                 pi_hdr = &hdr->pipd_hdr_ul.pi_hdr;
     717         [ #  # ]:          0 :                 uint16_t err_code = rte_be_to_cpu_16(pi_hdr->ul.err_code);
     718   [ #  #  #  # ]:          0 :                 if (pi_hdr->pkt_type == ZXDH_PCODE_IP_PKT_TYPE ||
     719                 :            :                         ((pi_hdr->pkt_type & ZXDH_PI_L3TYPE_MASK) == ZXDH_PI_L3TYPE_IP)) {
     720         [ #  # ]:          0 :                         if (pi_hdr->pkt_flag_hi8 & ZXDH_RX_IP_CKSUM_VERIFY) {
     721         [ #  # ]:          0 :                                 if (err_code & ZXDH_IPV4_CSUM_ERR)
     722                 :          0 :                                         m->ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_BAD;
     723                 :            :                                 else
     724                 :          0 :                                         m->ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_GOOD;
     725                 :            :                         }
     726                 :            :                 }
     727                 :            : 
     728         [ #  # ]:          0 :                 if (((pi_hdr->pkt_type & ZXDH_PCODE_MASK) == ZXDH_PCODE_UDP_PKT_TYPE) ||
     729                 :            :                         ((pi_hdr->pkt_type & ZXDH_PCODE_MASK) ==
     730         [ #  # ]:          0 :                                 ZXDH_PCODE_NO_REASSMBLE_TCP_PKT_TYPE) ||
     731                 :            :                         ((pi_hdr->pkt_type & ZXDH_PCODE_MASK) == ZXDH_PCODE_TCP_PKT_TYPE)) {
     732         [ #  # ]:          0 :                         if (pi_hdr->pkt_flag_hi8 & ZXDH_RX_TCPUDP_CKSUM_VERIFY) {
     733         [ #  # ]:          0 :                                 if ((err_code & ZXDH_TCP_CSUM_ERR) ||
     734                 :            :                                         (err_code & ZXDH_UDP_CSUM_ERR))
     735                 :          0 :                                         m->ol_flags |= RTE_MBUF_F_RX_L4_CKSUM_BAD;
     736                 :            :                                 else
     737                 :          0 :                                         m->ol_flags |= RTE_MBUF_F_RX_L4_CKSUM_GOOD;
     738                 :            :                         }
     739                 :            :                 }
     740                 :            : 
     741         [ #  # ]:          0 :                 if (ntohl(pi_hdr->ul.lro_flag) & ZXDH_PI_LRO_FLAG)
     742                 :          0 :                         m->ol_flags |= RTE_MBUF_F_RX_LRO;
     743                 :            : 
     744         [ #  # ]:          0 :                 m->pkt_len = rte_be_to_cpu_16(pi_hdr->ul.pkt_len);
     745                 :            :         } else {
     746         [ #  # ]:          0 :                 m->pkt_len = rte_be_to_cpu_16(pd_hdr->pkt_len);
     747                 :            :         }
     748                 :            : 
     749                 :          0 :         idx = (pkt_type_outer >> 12) & 0xF;
     750                 :          0 :         m->packet_type  = zxdh_outer_l2_type[idx];
     751                 :          0 :         idx = (pkt_type_outer >> 8)  & 0xF;
     752                 :          0 :         m->packet_type |= zxdh_outer_l3_type[idx];
     753                 :          0 :         idx = (pkt_type_outer >> 4)  & 0xF;
     754                 :          0 :         m->packet_type |= zxdh_outer_l4_type[idx];
     755                 :          0 :         idx = pkt_type_outer         & 0xF;
     756                 :          0 :         m->packet_type |= zxdh_tunnel_type[idx];
     757                 :            : 
     758         [ #  # ]:          0 :         if (pkt_type_inner) {
     759                 :          0 :                 idx = (pkt_type_inner >> 12) & 0xF;
     760                 :          0 :                 m->packet_type |= zxdh_inner_l2_type[idx];
     761                 :          0 :                 idx = (pkt_type_inner >> 8)  & 0xF;
     762                 :          0 :                 m->packet_type |= zxdh_inner_l3_type[idx];
     763                 :          0 :                 idx = (pkt_type_inner >> 4)  & 0xF;
     764                 :          0 :                 m->packet_type |= zxdh_inner_l4_type[idx];
     765                 :            : 
     766         [ #  # ]:          0 :                 if (hw->eth_dev->data->dev_conf.rxmode.offloads &
     767                 :            :                                 RTE_ETH_RX_OFFLOAD_OUTER_UDP_CKSUM)
     768                 :          0 :                         update_outer_rx_l4_csum(hw, pi_hdr, pd_hdr, m);
     769                 :            :         }
     770                 :          0 : }
     771                 :            : 
     772                 :            : static void
     773                 :          0 : zxdh_refill_desc_unwrap(struct zxdh_virtqueue *vq, struct rte_mbuf **cookie,
     774                 :            :                 uint16_t nb_pkts)
     775                 :            : {
     776                 :          0 :         struct zxdh_vring_packed_desc *start_dp = vq->vq_packed.ring.desc;
     777                 :            :         struct zxdh_vq_desc_extra *dxp;
     778                 :          0 :         uint16_t flags = vq->cached_flags;
     779                 :            :         int32_t i;
     780                 :            :         uint16_t idx;
     781                 :            : 
     782                 :          0 :         idx = vq->vq_avail_idx;
     783         [ #  # ]:          0 :         for (i = 0; i < nb_pkts; i++) {
     784                 :          0 :                 dxp = &vq->vq_descx[idx];
     785                 :          0 :                 dxp->cookie = (void *)cookie[i];
     786                 :          0 :                 start_dp[idx].addr = rte_mbuf_iova_get(cookie[i]) + RTE_PKTMBUF_HEADROOM;
     787                 :          0 :                 start_dp[idx].len = cookie[i]->buf_len - RTE_PKTMBUF_HEADROOM;
     788                 :            :                 zxdh_queue_store_flags_packed(&start_dp[idx], flags);
     789                 :          0 :                 idx++;
     790                 :            :         }
     791                 :          0 :         vq->vq_avail_idx += nb_pkts;
     792                 :          0 :         vq->vq_free_cnt = vq->vq_free_cnt - nb_pkts;
     793                 :          0 : }
     794                 :            : 
     795                 :            : static void
     796                 :          0 : zxdh_refill_que_descs(struct zxdh_virtqueue *vq, struct rte_eth_dev *dev)
     797                 :            : {
     798                 :            :         /* free_cnt may include mrg descs */
     799                 :            :         struct rte_mbuf *new_pkts[ZXDH_MBUF_BURST_SZ];
     800                 :          0 :         uint16_t free_cnt = RTE_MIN(ZXDH_MBUF_BURST_SZ, vq->vq_free_cnt);
     801                 :            :         struct zxdh_virtnet_rx *rxvq = &vq->rxq;
     802                 :            :         uint16_t  unwrap_cnt, left_cnt;
     803                 :            : 
     804         [ #  # ]:          0 :         if (!rte_pktmbuf_alloc_bulk(rxvq->mpool, new_pkts, free_cnt)) {
     805                 :            :                 left_cnt = free_cnt;
     806                 :            :                 unwrap_cnt = 0;
     807         [ #  # ]:          0 :                 if ((vq->vq_avail_idx + free_cnt) >= vq->vq_nentries) {
     808                 :          0 :                         unwrap_cnt = vq->vq_nentries - vq->vq_avail_idx;
     809                 :          0 :                         left_cnt = free_cnt - unwrap_cnt;
     810                 :          0 :                         zxdh_refill_desc_unwrap(vq, new_pkts, unwrap_cnt);
     811                 :          0 :                         vq->vq_avail_idx = 0;
     812                 :          0 :                         vq->cached_flags ^= ZXDH_VRING_PACKED_DESC_F_AVAIL_USED;
     813                 :            :                 }
     814         [ #  # ]:          0 :                 if (left_cnt)
     815                 :          0 :                         zxdh_refill_desc_unwrap(vq, new_pkts + unwrap_cnt, left_cnt);
     816                 :            :         } else {
     817                 :          0 :                 dev->data->rx_mbuf_alloc_failed += free_cnt;
     818                 :            :         }
     819                 :          0 : }
     820                 :            : 
     821                 :            : uint16_t
     822                 :          0 : zxdh_recv_pkts_packed(void *rx_queue, struct rte_mbuf **rx_pkts,
     823                 :            :                                 uint16_t nb_pkts)
     824                 :            : {
     825                 :            :         struct zxdh_virtnet_rx *rxvq = rx_queue;
     826                 :          0 :         struct zxdh_virtqueue *vq = rxvq->vq;
     827                 :          0 :         struct zxdh_hw *hw = vq->hw;
     828                 :            :         struct rte_mbuf *rxm = NULL;
     829                 :            :         struct rte_mbuf *prev = NULL;
     830                 :            :         struct zxdh_net_hdr_ul *header = NULL;
     831                 :          0 :         uint32_t lens[ZXDH_MBUF_BURST_SZ] = {0};
     832                 :          0 :         struct rte_mbuf *rcv_pkts[ZXDH_MBUF_BURST_SZ] = {NULL};
     833                 :            :         uint16_t len = 0;
     834                 :            :         uint32_t seg_num = 0;
     835                 :            :         uint32_t seg_res = 0;
     836                 :            :         uint16_t hdr_size = 0;
     837                 :            :         uint16_t nb_rx = 0;
     838                 :            :         uint16_t i;
     839                 :            :         uint16_t rcvd_pkt_len = 0;
     840                 :            :         uint16_t num = nb_pkts;
     841                 :            : 
     842         [ #  # ]:          0 :         if (unlikely(num > ZXDH_MBUF_BURST_SZ))
     843                 :            :                 num = ZXDH_MBUF_BURST_SZ;
     844                 :            : 
     845                 :          0 :         num = zxdh_dequeue_burst_rx_packed(vq, rcv_pkts, lens, num);
     846         [ #  # ]:          0 :         if (num == 0) {
     847                 :          0 :                 rxvq->stats.idle++;
     848                 :          0 :                 goto refill;
     849                 :            :         }
     850                 :            : 
     851         [ #  # ]:          0 :         for (i = 0; i < num; i++) {
     852                 :          0 :                 rxm = rcv_pkts[i];
     853                 :          0 :                 rx_pkts[nb_rx] = rxm;
     854                 :            :                 prev = rxm;
     855                 :          0 :                 len = lens[i];
     856                 :          0 :                 header = rte_pktmbuf_mtod(rxm, struct zxdh_net_hdr_ul *);
     857                 :          0 :                 seg_num  = header->type_hdr.num_buffers;
     858                 :            : 
     859                 :            :                 /* Private queue only handle type hdr */
     860                 :          0 :                 hdr_size = header->type_hdr.pd_len << 1;
     861   [ #  #  #  # ]:          0 :                 if (unlikely(hdr_size > lens[i] || hdr_size < ZXDH_TYPE_HDR_SIZE)) {
     862                 :          0 :                         PMD_RX_LOG(ERR, "hdr_size:%u is invalid", hdr_size);
     863                 :          0 :                         rte_pktmbuf_free(rxm);
     864                 :          0 :                         rxvq->stats.errors++;
     865                 :          0 :                         rxvq->stats.invalid_hdr_len_err++;
     866                 :          0 :                         continue;
     867                 :            :                 }
     868                 :          0 :                 rxm->data_off = RTE_PKTMBUF_HEADROOM + hdr_size;
     869                 :          0 :                 rxm->nb_segs = seg_num;
     870                 :          0 :                 rxm->ol_flags = 0;
     871                 :          0 :                 rcvd_pkt_len = len - hdr_size;
     872                 :          0 :                 rxm->data_len = rcvd_pkt_len;
     873                 :          0 :                 rxm->port = rxvq->port_id;
     874                 :            : 
     875                 :            :                 /* Update rte_mbuf according to pi/pd header */
     876                 :          0 :                 zxdh_rx_update_mbuf(hw, rxm, header);
     877                 :          0 :                 seg_res = seg_num - 1;
     878                 :            :                 /* Merge remaining segments */
     879   [ #  #  #  # ]:          0 :                 while (seg_res != 0 && i < (num - 1)) {
     880                 :          0 :                         i++;
     881                 :          0 :                         len = lens[i];
     882                 :          0 :                         rxm = rcv_pkts[i];
     883                 :          0 :                         rxm->data_len = len;
     884                 :          0 :                         rxm->data_off = RTE_PKTMBUF_HEADROOM;
     885                 :          0 :                         rcvd_pkt_len += len;
     886                 :          0 :                         prev->next = rxm;
     887                 :            :                         prev = rxm;
     888                 :          0 :                         rxm->next = NULL;
     889                 :          0 :                         seg_res--;
     890                 :            :                 }
     891                 :            : 
     892         [ #  # ]:          0 :                 if (!seg_res) {
     893         [ #  # ]:          0 :                         if (rcvd_pkt_len != rx_pkts[nb_rx]->pkt_len) {
     894                 :          0 :                                 PMD_RX_LOG(ERR, "dropped rcvd_pkt_len %d pktlen %d",
     895                 :            :                                         rcvd_pkt_len, rx_pkts[nb_rx]->pkt_len);
     896                 :          0 :                                 rte_pktmbuf_free(rx_pkts[nb_rx]);
     897                 :          0 :                                 rxvq->stats.errors++;
     898                 :          0 :                                 rxvq->stats.truncated_err++;
     899                 :          0 :                                 continue;
     900                 :            :                         }
     901                 :            :                         zxdh_update_packet_stats(&rxvq->stats, rx_pkts[nb_rx]);
     902                 :          0 :                         nb_rx++;
     903                 :            :                 }
     904                 :            :         }
     905                 :            :         /* Last packet still need merge segments */
     906         [ #  # ]:          0 :         while (seg_res != 0) {
     907                 :          0 :                 uint16_t rcv_cnt = RTE_MIN((uint16_t)seg_res, ZXDH_MBUF_BURST_SZ);
     908                 :            :                 uint16_t extra_idx = 0;
     909                 :            : 
     910                 :          0 :                 rcv_cnt = zxdh_dequeue_burst_rx_packed(vq, rcv_pkts, lens, rcv_cnt);
     911         [ #  # ]:          0 :                 if (unlikely(rcv_cnt == 0)) {
     912                 :          0 :                         PMD_RX_LOG(ERR, "No enough segments for packet");
     913                 :          0 :                         rte_pktmbuf_free(rx_pkts[nb_rx]);
     914                 :          0 :                         rxvq->stats.errors++;
     915                 :          0 :                         rxvq->stats.no_segs_err++;
     916                 :          0 :                         break;
     917                 :            :                 }
     918         [ #  # ]:          0 :                 while (extra_idx < rcv_cnt) {
     919                 :          0 :                         rxm = rcv_pkts[extra_idx];
     920                 :          0 :                         rcvd_pkt_len += (uint16_t)(lens[extra_idx]);
     921                 :          0 :                         rxm->data_len = lens[extra_idx];
     922                 :          0 :                         prev->next = rxm;
     923                 :            :                         prev = rxm;
     924                 :          0 :                         rxm->next = NULL;
     925                 :          0 :                         extra_idx++;
     926                 :            :                 }
     927                 :          0 :                 seg_res -= rcv_cnt;
     928         [ #  # ]:          0 :                 if (!seg_res) {
     929         [ #  # ]:          0 :                         if (unlikely(rcvd_pkt_len != rx_pkts[nb_rx]->pkt_len)) {
     930                 :          0 :                                 PMD_RX_LOG(ERR, "dropped rcvd_pkt_len %d pktlen %d",
     931                 :            :                                         rcvd_pkt_len, rx_pkts[nb_rx]->pkt_len);
     932                 :          0 :                                 rte_pktmbuf_free(rx_pkts[nb_rx]);
     933                 :          0 :                                 rxvq->stats.errors++;
     934                 :          0 :                                 rxvq->stats.truncated_err++;
     935                 :          0 :                                 continue;
     936                 :            :                         }
     937                 :            :                         zxdh_update_packet_stats(&rxvq->stats, rx_pkts[nb_rx]);
     938                 :          0 :                         nb_rx++;
     939                 :            :                 }
     940                 :            :         }
     941                 :          0 :         rxvq->stats.packets += nb_rx;
     942                 :            : 
     943                 :          0 : refill:
     944         [ #  # ]:          0 :         if (vq->vq_free_cnt > 0) {
     945                 :          0 :                 struct rte_eth_dev *dev = hw->eth_dev;
     946                 :          0 :                 zxdh_refill_que_descs(vq, dev);
     947                 :          0 :                 zxdh_queue_notify(vq);
     948                 :            :         }
     949                 :            : 
     950                 :          0 :         return nb_rx;
     951                 :            : }
     952                 :            : 
     953                 :            : static inline int
     954                 :          0 : zxdh_init_mbuf(struct rte_mbuf *rxm, uint16_t len,
     955                 :            :                 struct zxdh_hw *hw, struct zxdh_virtnet_rx *rxvq)
     956                 :            : {
     957                 :            :         uint16_t hdr_size = 0;
     958                 :            :         struct zxdh_net_hdr_ul *header;
     959                 :            : 
     960                 :          0 :         header = rte_pktmbuf_mtod(rxm, struct zxdh_net_hdr_ul *);
     961                 :          0 :         rxm->ol_flags = 0;
     962                 :          0 :         rxm->vlan_tci = 0;
     963                 :          0 :         rxm->vlan_tci_outer = 0;
     964                 :            : 
     965                 :          0 :         hdr_size = header->type_hdr.pd_len << 1;
     966   [ #  #  #  # ]:          0 :         if (unlikely(hdr_size > len || hdr_size < ZXDH_TYPE_HDR_SIZE ||
     967                 :            :                      header->type_hdr.num_buffers != 1)) {
     968                 :          0 :                 PMD_RX_LOG(DEBUG, "hdr_size:%u nb_segs %d is invalid",
     969                 :            :                         hdr_size, header->type_hdr.num_buffers);
     970                 :          0 :                 rte_pktmbuf_free(rxm);
     971                 :          0 :                 rxvq->stats.errors++;
     972                 :          0 :                 rxvq->stats.invalid_hdr_len_err++;
     973                 :          0 :                 return -1;
     974                 :            :         }
     975                 :          0 :         zxdh_rx_update_mbuf(hw, rxm, header);
     976                 :            : 
     977                 :          0 :         rxm->nb_segs = 1;
     978                 :          0 :         rxm->data_off = RTE_PKTMBUF_HEADROOM + hdr_size;
     979                 :          0 :         rxm->data_len = len - hdr_size;
     980                 :          0 :         rxm->port = hw->port_id;
     981                 :            : 
     982         [ #  # ]:          0 :         if (rxm->data_len != rxm->pkt_len) {
     983                 :          0 :                 PMD_RX_LOG(ERR, "dropped rcvd_pkt_len %d pktlen %d  bufaddr %p.",
     984                 :            :                                         rxm->data_len, rxm->pkt_len, rxm->buf_addr);
     985                 :          0 :                 rte_pktmbuf_free(rxm);
     986                 :          0 :                 rxvq->stats.truncated_err++;
     987                 :          0 :                 rxvq->stats.errors++;
     988                 :          0 :                 return -1;
     989                 :            :         }
     990                 :            :         return 0;
     991                 :            : }
     992                 :            : 
     993                 :            : uint16_t
     994                 :          0 : zxdh_recv_single_pkts(void *rx_queue, struct rte_mbuf **rcv_pkts, uint16_t nb_pkts)
     995                 :            : {
     996                 :            :         struct zxdh_virtnet_rx *rxvq = rx_queue;
     997                 :          0 :         struct zxdh_virtqueue *vq = rxvq->vq;
     998                 :          0 :         struct zxdh_hw *hw = vq->hw;
     999                 :            :         uint32_t lens[ZXDH_MBUF_BURST_SZ];
    1000                 :            :         uint16_t nb_rx = 0;
    1001                 :            :         uint16_t num;
    1002                 :            :         uint16_t i;
    1003                 :            : 
    1004                 :            :         num = nb_pkts;
    1005         [ #  # ]:          0 :         if (unlikely(num > ZXDH_MBUF_BURST_SZ))
    1006                 :            :                 num = ZXDH_MBUF_BURST_SZ;
    1007                 :          0 :         num = zxdh_dequeue_burst_rx_packed(vq, rcv_pkts, lens, num);
    1008         [ #  # ]:          0 :         if (num == 0) {
    1009                 :          0 :                 rxvq->stats.idle++;
    1010                 :          0 :                 goto refill;
    1011                 :            :         }
    1012                 :            : 
    1013         [ #  # ]:          0 :         for (i = 0; i < num; i++) {
    1014                 :          0 :                 struct rte_mbuf *rxm = rcv_pkts[i];
    1015                 :          0 :                 uint16_t len = lens[i];
    1016                 :            : 
    1017         [ #  # ]:          0 :                 if (unlikely(zxdh_init_mbuf(rxm, len, hw, &vq->rxq) < 0))
    1018                 :          0 :                         continue;
    1019                 :          0 :                 rcv_pkts[nb_rx] = rxm;
    1020                 :            :                 zxdh_update_packet_stats(&rxvq->stats, rxm);
    1021                 :          0 :                 nb_rx++;
    1022                 :            :         }
    1023                 :          0 :         rxvq->stats.packets += nb_rx;
    1024                 :            : 
    1025                 :          0 : refill:
    1026         [ #  # ]:          0 :         if (vq->vq_free_cnt > 0) {
    1027                 :          0 :                 struct rte_eth_dev *dev = hw->eth_dev;
    1028                 :          0 :                 zxdh_refill_que_descs(vq, dev);
    1029                 :          0 :                 zxdh_queue_notify(vq);
    1030                 :            :         }
    1031                 :          0 :         return nb_rx;
    1032                 :            : }

Generated by: LCOV version 1.14