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_GOOD 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 : :
59 : : /* Outer/Inner L2 type */
60 : : #define ZXDH_PD_L2TYPE_MASK 0xf000
61 : : #define ZXDH_PTYPE_L2_ETHER 0x1000
62 : : #define ZXDH_PTYPE_L2_ETHER_TIMESYNC 0x2000
63 : : #define ZXDH_PTYPE_L2_ETHER_ARP 0x3000
64 : : #define ZXDH_PTYPE_L2_ETHER_LLDP 0x4000
65 : : #define ZXDH_PTYPE_L2_ETHER_NSH 0x5000
66 : : #define ZXDH_PTYPE_L2_ETHER_VLAN 0x6000
67 : : #define ZXDH_PTYPE_L2_ETHER_QINQ 0x7000
68 : : #define ZXDH_PTYPE_L2_ETHER_PPPOE 0x8000
69 : : #define ZXDH_PTYPE_L2_ETHER_FCOE 0x9000
70 : : #define ZXDH_PTYPE_L2_ETHER_MPLS 0xa000
71 : :
72 : : /* Outer/Inner L3 type */
73 : : #define ZXDH_PD_L3TYPE_MASK 0x0f00
74 : : #define ZXDH_PTYPE_L3_IPV4 0x0100
75 : : #define ZXDH_PTYPE_L3_IPV4_EXT 0x0200
76 : : #define ZXDH_PTYPE_L3_IPV6 0x0300
77 : : #define ZXDH_PTYPE_L3_IPV4_EXT_UNKNOWN 0x0400
78 : : #define ZXDH_PTYPE_L3_IPV6_EXT 0x0500
79 : : #define ZXDH_PTYPE_L3_IPV6_EXT_UNKNOWN 0x0600
80 : :
81 : : /* Outer/Inner L4 type */
82 : : #define ZXDH_PD_L4TYPE_MASK 0x00f0
83 : : #define ZXDH_PTYPE_L4_TCP 0x0010
84 : : #define ZXDH_PTYPE_L4_UDP 0x0020
85 : : #define ZXDH_PTYPE_L4_FRAG 0x0030
86 : : #define ZXDH_PTYPE_L4_SCTP 0x0040
87 : : #define ZXDH_PTYPE_L4_ICMP 0x0050
88 : : #define ZXDH_PTYPE_L4_NONFRAG 0x0060
89 : : #define ZXDH_PTYPE_L4_IGMP 0x0070
90 : :
91 : : #define ZXDH_TX_MAX_SEGS 31
92 : : #define ZXDH_RX_MAX_SEGS 31
93 : :
94 : : #define ZXDH_PI_LRO_FLAG 0x00000001
95 : :
96 : : #define ZXDH_MIN_MSS 64
97 : : #define ZXDH_VLAN_ID_MASK 0xfff
98 : :
99 : : #define ZXDH_MTU_MSS_UNIT_SHIFTBIT 2
100 : : #define ZXDH_MTU_MSS_MASK 0xFFF
101 : : #define ZXDH_PD_HDR_SIZE_MAX 256
102 : :
103 : : /* error code */
104 : : #define ZXDH_UDP_CSUM_ERR 0x0020
105 : : #define ZXDH_TCP_CSUM_ERR 0x0040
106 : : #define ZXDH_IPV4_CSUM_ERR 0x0100
107 : :
108 : : #define ZXDH_DTPOFFLOAD_MASK ( \
109 : : RTE_MBUF_F_TX_IP_CKSUM | \
110 : : RTE_MBUF_F_TX_L4_MASK | \
111 : : RTE_MBUF_F_TX_TCP_SEG | \
112 : : RTE_MBUF_F_TX_SEC_OFFLOAD | \
113 : : RTE_MBUF_F_TX_UDP_SEG)
114 : :
115 : : uint32_t zxdh_outer_l2_type[16] = {
116 : : 0,
117 : : RTE_PTYPE_L2_ETHER,
118 : : RTE_PTYPE_L2_ETHER_TIMESYNC,
119 : : RTE_PTYPE_L2_ETHER_ARP,
120 : : RTE_PTYPE_L2_ETHER_LLDP,
121 : : RTE_PTYPE_L2_ETHER_NSH,
122 : : RTE_PTYPE_L2_ETHER_VLAN,
123 : : RTE_PTYPE_L2_ETHER_QINQ,
124 : : RTE_PTYPE_L2_ETHER_PPPOE,
125 : : RTE_PTYPE_L2_ETHER_FCOE,
126 : : RTE_PTYPE_L2_ETHER_MPLS,
127 : : };
128 : :
129 : : uint32_t zxdh_outer_l3_type[16] = {
130 : : 0,
131 : : RTE_PTYPE_L3_IPV4,
132 : : RTE_PTYPE_L3_IPV4_EXT,
133 : : RTE_PTYPE_L3_IPV6,
134 : : RTE_PTYPE_L3_IPV4_EXT_UNKNOWN,
135 : : RTE_PTYPE_L3_IPV6_EXT,
136 : : RTE_PTYPE_L3_IPV6_EXT_UNKNOWN,
137 : : };
138 : :
139 : : uint32_t zxdh_outer_l4_type[16] = {
140 : : 0,
141 : : RTE_PTYPE_L4_TCP,
142 : : RTE_PTYPE_L4_UDP,
143 : : RTE_PTYPE_L4_FRAG,
144 : : RTE_PTYPE_L4_SCTP,
145 : : RTE_PTYPE_L4_ICMP,
146 : : RTE_PTYPE_L4_NONFRAG,
147 : : RTE_PTYPE_L4_IGMP,
148 : : };
149 : :
150 : : uint32_t zxdh_tunnel_type[16] = {
151 : : 0,
152 : : RTE_PTYPE_TUNNEL_IP,
153 : : RTE_PTYPE_TUNNEL_GRE,
154 : : RTE_PTYPE_TUNNEL_VXLAN,
155 : : RTE_PTYPE_TUNNEL_NVGRE,
156 : : RTE_PTYPE_TUNNEL_GENEVE,
157 : : RTE_PTYPE_TUNNEL_GRENAT,
158 : : RTE_PTYPE_TUNNEL_GTPC,
159 : : RTE_PTYPE_TUNNEL_GTPU,
160 : : RTE_PTYPE_TUNNEL_ESP,
161 : : RTE_PTYPE_TUNNEL_L2TP,
162 : : RTE_PTYPE_TUNNEL_VXLAN_GPE,
163 : : RTE_PTYPE_TUNNEL_MPLS_IN_GRE,
164 : : RTE_PTYPE_TUNNEL_MPLS_IN_UDP,
165 : : };
166 : :
167 : : uint32_t zxdh_inner_l2_type[16] = {
168 : : 0,
169 : : RTE_PTYPE_INNER_L2_ETHER,
170 : : 0,
171 : : 0,
172 : : 0,
173 : : 0,
174 : : RTE_PTYPE_INNER_L2_ETHER_VLAN,
175 : : RTE_PTYPE_INNER_L2_ETHER_QINQ,
176 : : 0,
177 : : 0,
178 : : 0,
179 : : };
180 : :
181 : : uint32_t zxdh_inner_l3_type[16] = {
182 : : 0,
183 : : RTE_PTYPE_INNER_L3_IPV4,
184 : : RTE_PTYPE_INNER_L3_IPV4_EXT,
185 : : RTE_PTYPE_INNER_L3_IPV6,
186 : : RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN,
187 : : RTE_PTYPE_INNER_L3_IPV6_EXT,
188 : : RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN,
189 : : };
190 : :
191 : : uint32_t zxdh_inner_l4_type[16] = {
192 : : 0,
193 : : RTE_PTYPE_INNER_L4_TCP,
194 : : RTE_PTYPE_INNER_L4_UDP,
195 : : RTE_PTYPE_INNER_L4_FRAG,
196 : : RTE_PTYPE_INNER_L4_SCTP,
197 : : RTE_PTYPE_INNER_L4_ICMP,
198 : : 0,
199 : : 0,
200 : : };
201 : :
202 : : static void
203 : 0 : zxdh_xmit_cleanup_inorder_packed(struct zxdh_virtqueue *vq, int32_t num)
204 : : {
205 : : uint16_t used_idx = 0;
206 : : uint16_t id = 0;
207 : : uint16_t curr_id = 0;
208 : : uint16_t free_cnt = 0;
209 : 0 : uint16_t size = vq->vq_nentries;
210 : 0 : struct zxdh_vring_packed_desc *desc = vq->vq_packed.ring.desc;
211 : : struct zxdh_vq_desc_extra *dxp = NULL;
212 : :
213 : 0 : used_idx = vq->vq_used_cons_idx;
214 : : /* desc_is_used has a load-acquire or rte_io_rmb inside
215 : : * and wait for used desc in virtqueue.
216 : : */
217 [ # # ]: 0 : while (num > 0 && zxdh_desc_used(&desc[used_idx], vq)) {
218 : 0 : id = desc[used_idx].id;
219 : : do {
220 : : curr_id = used_idx;
221 : 0 : dxp = &vq->vq_descx[used_idx];
222 : 0 : used_idx += dxp->ndescs;
223 : 0 : free_cnt += dxp->ndescs;
224 : 0 : num -= dxp->ndescs;
225 [ # # ]: 0 : if (used_idx >= size) {
226 : 0 : used_idx -= size;
227 : 0 : vq->vq_packed.used_wrap_counter ^= 1;
228 : : }
229 [ # # ]: 0 : if (dxp->cookie != NULL) {
230 : 0 : rte_pktmbuf_free(dxp->cookie);
231 : 0 : dxp->cookie = NULL;
232 : : }
233 [ # # ]: 0 : } while (curr_id != id);
234 : : }
235 : 0 : vq->vq_used_cons_idx = used_idx;
236 : 0 : vq->vq_free_cnt += free_cnt;
237 : 0 : }
238 : :
239 : : static inline uint16_t
240 : : zxdh_get_mtu(struct zxdh_virtqueue *vq)
241 : : {
242 : 0 : struct rte_eth_dev *eth_dev = vq->hw->eth_dev;
243 : :
244 : 0 : return eth_dev->data->mtu;
245 : : }
246 : :
247 : : static void
248 : 0 : zxdh_xmit_fill_net_hdr(struct zxdh_virtqueue *vq, struct rte_mbuf *cookie,
249 : : struct zxdh_net_hdr_dl *hdr)
250 : : {
251 : : uint16_t mtu_or_mss = 0;
252 : : uint16_t pkt_flag_lw16 = ZXDH_NO_IPID_UPDATE;
253 : : uint16_t l3_offset;
254 : : uint8_t pcode = ZXDH_PCODE_NO_IP_PKT_TYPE;
255 : : uint8_t l3_ptype = ZXDH_PI_L3TYPE_NOIP;
256 : : struct zxdh_pi_hdr *pi_hdr = NULL;
257 : : struct zxdh_pd_hdr_dl *pd_hdr = NULL;
258 : 0 : struct zxdh_hw *hw = vq->hw;
259 : 0 : struct zxdh_net_hdr_dl *net_hdr_dl = &g_net_hdr_dl[hw->port_id];
260 : 0 : uint8_t hdr_len = hw->dl_net_hdr_len;
261 : : uint32_t ol_flag = 0;
262 : :
263 [ # # ]: 0 : rte_memcpy(hdr, net_hdr_dl, hdr_len);
264 [ # # ]: 0 : if (hw->has_tx_offload) {
265 : : pi_hdr = &hdr->pipd_hdr_dl.pi_hdr;
266 : 0 : pd_hdr = &hdr->pipd_hdr_dl.pd_hdr;
267 : :
268 : : pcode = ZXDH_PCODE_IP_PKT_TYPE;
269 [ # # ]: 0 : if (cookie->ol_flags & RTE_MBUF_F_TX_IPV6)
270 : : l3_ptype = ZXDH_PI_L3TYPE_IPV6;
271 [ # # ]: 0 : else if (cookie->ol_flags & RTE_MBUF_F_TX_IPV4)
272 : : l3_ptype = ZXDH_PI_L3TYPE_IP;
273 : : else
274 : : pcode = ZXDH_PCODE_NO_IP_PKT_TYPE;
275 : :
276 [ # # ]: 0 : if (cookie->ol_flags & RTE_MBUF_F_TX_TCP_SEG) {
277 : 0 : mtu_or_mss = (cookie->tso_segsz >= ZXDH_MIN_MSS)
278 : : ? cookie->tso_segsz
279 : : : ZXDH_MIN_MSS;
280 : 0 : pi_hdr->pkt_flag_hi8 |= ZXDH_TX_TCPUDP_CKSUM_CAL;
281 : : pkt_flag_lw16 |= ZXDH_NO_IP_FRAGMENT | ZXDH_TX_IP_CKSUM_CAL;
282 : : pcode = ZXDH_PCODE_TCP_PKT_TYPE;
283 [ # # ]: 0 : } else if (cookie->ol_flags & RTE_MBUF_F_TX_UDP_SEG) {
284 : : mtu_or_mss = zxdh_get_mtu(vq);
285 : 0 : mtu_or_mss = (mtu_or_mss >= ZXDH_MIN_MSS) ? mtu_or_mss : ZXDH_MIN_MSS;
286 : : pkt_flag_lw16 |= ZXDH_TX_IP_CKSUM_CAL;
287 : 0 : pi_hdr->pkt_flag_hi8 |= ZXDH_NO_TCP_FRAGMENT | ZXDH_TX_TCPUDP_CKSUM_CAL;
288 : : pcode = ZXDH_PCODE_UDP_PKT_TYPE;
289 : : } else {
290 : : pkt_flag_lw16 |= ZXDH_NO_IP_FRAGMENT;
291 : 0 : pi_hdr->pkt_flag_hi8 |= ZXDH_NO_TCP_FRAGMENT;
292 : : }
293 : :
294 [ # # ]: 0 : if (cookie->ol_flags & RTE_MBUF_F_TX_IP_CKSUM)
295 : 0 : pkt_flag_lw16 |= ZXDH_TX_IP_CKSUM_CAL;
296 : :
297 [ # # ]: 0 : if ((cookie->ol_flags & RTE_MBUF_F_TX_UDP_CKSUM) ==
298 : : RTE_MBUF_F_TX_UDP_CKSUM){
299 : : pcode = ZXDH_PCODE_UDP_PKT_TYPE;
300 : 0 : pi_hdr->pkt_flag_hi8 |= ZXDH_TX_TCPUDP_CKSUM_CAL;
301 [ # # ]: 0 : } else if ((cookie->ol_flags & RTE_MBUF_F_TX_TCP_CKSUM) ==
302 : : RTE_MBUF_F_TX_TCP_CKSUM) {
303 : : pcode = ZXDH_PCODE_TCP_PKT_TYPE;
304 : 0 : pi_hdr->pkt_flag_hi8 |= ZXDH_TX_TCPUDP_CKSUM_CAL;
305 : : }
306 : :
307 : 0 : pkt_flag_lw16 |= (mtu_or_mss >> ZXDH_MTU_MSS_UNIT_SHIFTBIT) & ZXDH_MTU_MSS_MASK;
308 [ # # ]: 0 : pi_hdr->pkt_flag_lw16 = rte_be_to_cpu_16(pkt_flag_lw16);
309 : 0 : pi_hdr->pkt_type = l3_ptype | ZXDH_PKT_FORM_CPU | pcode;
310 : :
311 : 0 : l3_offset = hdr_len + cookie->l2_len;
312 [ # # ]: 0 : l3_offset += (cookie->ol_flags & RTE_MBUF_F_TX_TUNNEL_MASK) ?
313 : 0 : cookie->outer_l2_len + cookie->outer_l3_len : 0;
314 [ # # ]: 0 : pi_hdr->l3_offset = rte_be_to_cpu_16(l3_offset);
315 [ # # ]: 0 : pi_hdr->l4_offset = rte_be_to_cpu_16(l3_offset + cookie->l3_len);
316 [ # # ]: 0 : if (cookie->ol_flags & RTE_MBUF_F_TX_OUTER_IP_CKSUM)
317 : : ol_flag |= ZXDH_PD_OFFLOAD_OUTER_IPCSUM;
318 : : } else {
319 : 0 : pd_hdr = &hdr->pd_hdr;
320 : : }
321 : :
322 [ # # ]: 0 : if (cookie->ol_flags & (RTE_MBUF_F_TX_VLAN | RTE_MBUF_F_TX_QINQ)) {
323 : 0 : ol_flag |= ZXDH_PD_OFFLOAD_CVLAN_INSERT;
324 [ # # ]: 0 : pd_hdr->cvlan_insert = rte_be_to_cpu_16(cookie->vlan_tci);
325 [ # # ]: 0 : if (unlikely(cookie->ol_flags & RTE_MBUF_F_TX_QINQ)) {
326 : 0 : ol_flag |= ZXDH_PD_OFFLOAD_SVLAN_INSERT;
327 [ # # ]: 0 : pd_hdr->svlan_insert = rte_be_to_cpu_16(cookie->vlan_tci_outer);
328 : : }
329 : : }
330 : :
331 [ # # ]: 0 : pd_hdr->ol_flag = rte_be_to_cpu_16(ol_flag);
332 : 0 : }
333 : :
334 : : static inline void
335 : 0 : zxdh_enqueue_xmit_packed_fast(struct zxdh_virtnet_tx *txvq,
336 : : struct rte_mbuf *cookie)
337 : : {
338 : 0 : struct zxdh_virtqueue *vq = txvq->vq;
339 : 0 : uint16_t id = vq->vq_avail_idx;
340 : 0 : struct zxdh_vq_desc_extra *dxp = &vq->vq_descx[id];
341 : 0 : uint16_t flags = vq->vq_packed.cached_flags;
342 : : struct zxdh_net_hdr_dl *hdr = NULL;
343 : 0 : uint8_t hdr_len = vq->hw->dl_net_hdr_len;
344 : 0 : struct zxdh_vring_packed_desc *dp = &vq->vq_packed.ring.desc[id];
345 : :
346 : 0 : dxp->ndescs = 1;
347 : 0 : dxp->cookie = cookie;
348 : 0 : hdr = rte_pktmbuf_mtod_offset(cookie, struct zxdh_net_hdr_dl *, -hdr_len);
349 : 0 : zxdh_xmit_fill_net_hdr(vq, cookie, hdr);
350 : :
351 : 0 : dp->addr = rte_pktmbuf_iova(cookie) - hdr_len;
352 : 0 : dp->len = cookie->data_len + hdr_len;
353 : 0 : dp->id = id;
354 [ # # ]: 0 : if (++vq->vq_avail_idx >= vq->vq_nentries) {
355 : 0 : vq->vq_avail_idx -= vq->vq_nentries;
356 : 0 : vq->vq_packed.cached_flags ^= ZXDH_VRING_PACKED_DESC_F_AVAIL_USED;
357 : : }
358 : 0 : vq->vq_free_cnt--;
359 : : zxdh_queue_store_flags_packed(dp, flags);
360 : 0 : }
361 : :
362 : : static inline void
363 : 0 : zxdh_enqueue_xmit_packed(struct zxdh_virtnet_tx *txvq,
364 : : struct rte_mbuf *cookie,
365 : : uint16_t needed)
366 : : {
367 : 0 : struct zxdh_tx_region *txr = txvq->zxdh_net_hdr_mz->addr;
368 : 0 : struct zxdh_virtqueue *vq = txvq->vq;
369 : 0 : uint16_t id = vq->vq_avail_idx;
370 : 0 : struct zxdh_vq_desc_extra *dxp = &vq->vq_descx[id];
371 : : uint16_t head_idx = vq->vq_avail_idx;
372 : : uint16_t idx = head_idx;
373 : 0 : struct zxdh_vring_packed_desc *start_dp = vq->vq_packed.ring.desc;
374 : 0 : struct zxdh_vring_packed_desc *head_dp = &vq->vq_packed.ring.desc[idx];
375 : : struct zxdh_net_hdr_dl *hdr = NULL;
376 : :
377 : 0 : uint16_t head_flags = cookie->next ? ZXDH_VRING_DESC_F_NEXT : 0;
378 : 0 : uint8_t hdr_len = vq->hw->dl_net_hdr_len;
379 : :
380 : 0 : dxp->ndescs = needed;
381 : 0 : dxp->cookie = cookie;
382 : 0 : head_flags |= vq->vq_packed.cached_flags;
383 : :
384 : 0 : start_dp[idx].addr = txvq->zxdh_net_hdr_mem + RTE_PTR_DIFF(&txr[idx].tx_hdr, txr);
385 : 0 : start_dp[idx].len = hdr_len;
386 : 0 : head_flags |= ZXDH_VRING_DESC_F_NEXT;
387 : : hdr = (void *)&txr[idx].tx_hdr;
388 : :
389 : : rte_prefetch1(hdr);
390 : 0 : idx++;
391 [ # # ]: 0 : if (idx >= vq->vq_nentries) {
392 : 0 : idx -= vq->vq_nentries;
393 : 0 : vq->vq_packed.cached_flags ^= ZXDH_VRING_PACKED_DESC_F_AVAIL_USED;
394 : : }
395 : :
396 : 0 : zxdh_xmit_fill_net_hdr(vq, cookie, hdr);
397 : :
398 : : do {
399 : 0 : start_dp[idx].addr = rte_pktmbuf_iova(cookie);
400 : 0 : start_dp[idx].len = cookie->data_len;
401 : 0 : start_dp[idx].id = id;
402 [ # # ]: 0 : if (likely(idx != head_idx)) {
403 : 0 : uint16_t flags = cookie->next ? ZXDH_VRING_DESC_F_NEXT : 0;
404 : :
405 : 0 : flags |= vq->vq_packed.cached_flags;
406 : 0 : start_dp[idx].flags = flags;
407 : : }
408 : :
409 : 0 : idx++;
410 [ # # ]: 0 : if (idx >= vq->vq_nentries) {
411 : 0 : idx -= vq->vq_nentries;
412 : 0 : vq->vq_packed.cached_flags ^= ZXDH_VRING_PACKED_DESC_F_AVAIL_USED;
413 : : }
414 [ # # ]: 0 : } while ((cookie = cookie->next) != NULL);
415 : :
416 : 0 : vq->vq_free_cnt = (uint16_t)(vq->vq_free_cnt - needed);
417 : 0 : vq->vq_avail_idx = idx;
418 : :
419 : : zxdh_queue_store_flags_packed(head_dp, head_flags);
420 : 0 : }
421 : :
422 : : static void
423 : : zxdh_update_packet_stats(struct zxdh_virtnet_stats *stats, struct rte_mbuf *mbuf)
424 : : {
425 : 0 : uint32_t s = mbuf->pkt_len;
426 : :
427 : 0 : stats->bytes += s;
428 : : #ifdef QUEUE_XSTAT
429 : : if (s == 64) {
430 : : stats->size_bins[1]++;
431 : : } else if (s > 64 && s < 1024) {
432 : : uint32_t bin;
433 : :
434 : : /* count zeros, and offset into correct bin */
435 : : bin = (sizeof(s) * 8) - rte_clz32(s) - 5;
436 : : stats->size_bins[bin]++;
437 : : } else {
438 : : if (s < 64)
439 : : stats->size_bins[0]++;
440 : : else if (s < 1519)
441 : : stats->size_bins[6]++;
442 : : else
443 : : stats->size_bins[7]++;
444 : : }
445 : :
446 : : ea = rte_pktmbuf_mtod(mbuf, struct rte_ether_addr *);
447 : : if (rte_is_multicast_ether_addr(ea)) {
448 : : if (rte_is_broadcast_ether_addr(ea))
449 : : stats->broadcast++;
450 : : else
451 : : stats->multicast++;
452 : : }
453 : : #endif
454 : : }
455 : :
456 : : static void
457 : 0 : zxdh_xmit_flush(struct zxdh_virtqueue *vq)
458 : : {
459 : : uint16_t id = 0;
460 : : uint16_t curr_id = 0;
461 : : uint16_t free_cnt = 0;
462 : 0 : uint16_t size = vq->vq_nentries;
463 : 0 : struct zxdh_vring_packed_desc *desc = vq->vq_packed.ring.desc;
464 : : struct zxdh_vq_desc_extra *dxp = NULL;
465 : 0 : uint16_t used_idx = vq->vq_used_cons_idx;
466 : :
467 : : /*
468 : : * The function desc_is_used performs a load-acquire operation
469 : : * or calls rte_io_rmb to ensure memory consistency. It waits
470 : : * for a used descriptor in the virtqueue.
471 : : */
472 : 0 : while (desc_is_used(&desc[used_idx], vq)) {
473 : 0 : id = desc[used_idx].id;
474 : : do {
475 : : curr_id = used_idx;
476 : 0 : dxp = &vq->vq_descx[used_idx];
477 : 0 : used_idx += dxp->ndescs;
478 : 0 : free_cnt += dxp->ndescs;
479 [ # # ]: 0 : if (used_idx >= size) {
480 : 0 : used_idx -= size;
481 : 0 : vq->vq_packed.used_wrap_counter ^= 1;
482 : : }
483 [ # # ]: 0 : if (dxp->cookie != NULL) {
484 : 0 : rte_pktmbuf_free(dxp->cookie);
485 : 0 : dxp->cookie = NULL;
486 : : }
487 [ # # ]: 0 : } while (curr_id != id);
488 : : }
489 : 0 : vq->vq_used_cons_idx = used_idx;
490 : 0 : vq->vq_free_cnt += free_cnt;
491 : 0 : }
492 : :
493 : : uint16_t
494 : 0 : zxdh_xmit_pkts_packed(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
495 : : {
496 : : struct zxdh_virtnet_tx *txvq = tx_queue;
497 : 0 : struct zxdh_virtqueue *vq = txvq->vq;
498 : : uint16_t nb_tx = 0;
499 : :
500 : 0 : zxdh_xmit_flush(vq);
501 : :
502 [ # # ]: 0 : for (nb_tx = 0; nb_tx < nb_pkts; nb_tx++) {
503 : 0 : struct rte_mbuf *txm = tx_pkts[nb_tx];
504 : : int32_t can_push = 0;
505 : : int32_t slots = 0;
506 : : int32_t need = 0;
507 : :
508 : : rte_prefetch0(txm);
509 : : /* optimize ring usage */
510 [ # # ]: 0 : if (rte_mbuf_refcnt_read(txm) == 1 &&
511 [ # # ]: 0 : RTE_MBUF_DIRECT(txm) &&
512 [ # # ]: 0 : txm->nb_segs == 1 &&
513 [ # # ]: 0 : txm->data_off >= ZXDH_DL_NET_HDR_SIZE) {
514 : : can_push = 1;
515 : : }
516 : : /**
517 : : * How many main ring entries are needed to this Tx?
518 : : * indirect => 1
519 : : * any_layout => number of segments
520 : : * default => number of segments + 1
521 : : **/
522 : 0 : slots = txm->nb_segs + !can_push;
523 : 0 : need = slots - vq->vq_free_cnt;
524 : : /* Positive value indicates it need free vring descriptors */
525 [ # # ]: 0 : if (unlikely(need > 0)) {
526 : 0 : zxdh_xmit_cleanup_inorder_packed(vq, need);
527 : 0 : need = slots - vq->vq_free_cnt;
528 [ # # ]: 0 : if (unlikely(need > 0)) {
529 : 0 : PMD_TX_LOG(ERR,
530 : : " No enough %d free tx descriptors to transmit."
531 : : "freecnt %d",
532 : : need,
533 : : vq->vq_free_cnt);
534 : 0 : break;
535 : : }
536 : : }
537 : :
538 : : /* Enqueue Packet buffers */
539 [ # # ]: 0 : if (can_push)
540 : 0 : zxdh_enqueue_xmit_packed_fast(txvq, txm);
541 : : else
542 : 0 : zxdh_enqueue_xmit_packed(txvq, txm, slots);
543 : : zxdh_update_packet_stats(&txvq->stats, txm);
544 : : }
545 : 0 : txvq->stats.packets += nb_tx;
546 [ # # ]: 0 : if (likely(nb_tx))
547 : : zxdh_queue_notify(vq);
548 : 0 : return nb_tx;
549 : : }
550 : :
551 : 0 : static inline int dl_net_hdr_check(struct rte_mbuf *m, struct zxdh_hw *hw)
552 : : {
553 [ # # # # ]: 0 : if ((m->ol_flags & ZXDH_DTPOFFLOAD_MASK) && !hw->has_tx_offload) {
554 : 0 : PMD_TX_LOG(ERR, "port:[%d], vfid[%d]. "
555 : : "not support tx_offload", hw->port_id, hw->vfid);
556 : 0 : return -EINVAL;
557 : : }
558 : : return 0;
559 : : }
560 : :
561 : 0 : uint16_t zxdh_xmit_pkts_prepare(void *tx_queue, struct rte_mbuf **tx_pkts,
562 : : uint16_t nb_pkts)
563 : : {
564 : : struct zxdh_virtnet_tx *txvq = tx_queue;
565 : 0 : struct zxdh_hw *hw = txvq->vq->hw;
566 : : uint16_t nb_tx;
567 : :
568 [ # # ]: 0 : for (nb_tx = 0; nb_tx < nb_pkts; nb_tx++) {
569 : 0 : struct rte_mbuf *m = tx_pkts[nb_tx];
570 : : int32_t error;
571 : :
572 : : #ifdef RTE_LIBRTE_ETHDEV_DEBUG
573 : : error = rte_validate_tx_offload(m);
574 : : if (unlikely(error)) {
575 : : rte_errno = -error;
576 : : break;
577 : : }
578 : : #endif
579 : :
580 : : error = rte_net_intel_cksum_prepare(m);
581 [ # # ]: 0 : if (unlikely(error)) {
582 : 0 : rte_errno = -error;
583 : 0 : break;
584 : : }
585 [ # # ]: 0 : if (m->nb_segs > ZXDH_TX_MAX_SEGS) {
586 : 0 : PMD_TX_LOG(ERR, "%d segs dropped", m->nb_segs);
587 : 0 : txvq->stats.truncated_err += nb_pkts - nb_tx;
588 : 0 : rte_errno = ENOMEM;
589 : 0 : break;
590 : : }
591 : :
592 : 0 : error = dl_net_hdr_check(m, hw);
593 [ # # ]: 0 : if (unlikely(error)) {
594 : 0 : rte_errno = ENOTSUP;
595 : 0 : txvq->stats.errors += nb_pkts - nb_tx;
596 : 0 : txvq->stats.offload_cfg_err += nb_pkts - nb_tx;
597 : 0 : break;
598 : : }
599 : : }
600 : 0 : return nb_tx;
601 : : }
602 : :
603 : : static uint16_t
604 : 0 : zxdh_dequeue_burst_rx_packed(struct zxdh_virtqueue *vq,
605 : : struct rte_mbuf **rx_pkts,
606 : : uint32_t *len,
607 : : uint16_t num)
608 : : {
609 : 0 : struct zxdh_vring_packed_desc *desc = vq->vq_packed.ring.desc;
610 : : struct rte_mbuf *cookie = NULL;
611 : : uint16_t i, used_idx;
612 : : uint16_t id;
613 : :
614 [ # # ]: 0 : for (i = 0; i < num; i++) {
615 : 0 : used_idx = vq->vq_used_cons_idx;
616 : : /**
617 : : * desc_is_used has a load-acquire or rte_io_rmb inside
618 : : * and wait for used desc in virtqueue.
619 : : */
620 : 0 : if (!zxdh_desc_used(&desc[used_idx], vq))
621 : 0 : return i;
622 : 0 : len[i] = desc[used_idx].len;
623 : 0 : id = desc[used_idx].id;
624 : 0 : cookie = (struct rte_mbuf *)vq->vq_descx[id].cookie;
625 : 0 : vq->vq_descx[id].cookie = NULL;
626 [ # # ]: 0 : if (unlikely(cookie == NULL)) {
627 : 0 : PMD_RX_LOG(ERR,
628 : : "vring descriptor with no mbuf cookie at %u", vq->vq_used_cons_idx);
629 : 0 : break;
630 : : }
631 : : rte_prefetch0(cookie);
632 : : rte_packet_prefetch(rte_pktmbuf_mtod(cookie, void *));
633 : 0 : rx_pkts[i] = cookie;
634 : 0 : vq->vq_free_cnt++;
635 : 0 : vq->vq_used_cons_idx++;
636 [ # # ]: 0 : if (vq->vq_used_cons_idx >= vq->vq_nentries) {
637 : 0 : vq->vq_used_cons_idx -= vq->vq_nentries;
638 : 0 : vq->vq_packed.used_wrap_counter ^= 1;
639 : : }
640 : : }
641 : : return i;
642 : : }
643 : :
644 : : static inline void
645 : 0 : zxdh_rx_update_mbuf(struct rte_mbuf *m, struct zxdh_net_hdr_ul *hdr)
646 : : {
647 : 0 : uint8_t has_pi = (uint64_t)(hdr->type_hdr.pd_len << 1) > ZXDH_UL_NOPI_HDR_SIZE_MAX;
648 [ # # ]: 0 : struct zxdh_pd_hdr_ul *pd_hdr = has_pi ? &hdr->pipd_hdr_ul.pd_hdr : &hdr->pd_hdr;
649 [ # # ]: 0 : uint32_t pkt_flag = ntohl(pd_hdr->pkt_flag);
650 : : uint32_t idx = 0;
651 [ # # ]: 0 : uint32_t striped_vlan_tci = rte_be_to_cpu_32(pd_hdr->striped_vlan_tci);
652 [ # # ]: 0 : uint16_t pkt_type_outer = rte_be_to_cpu_16(pd_hdr->pkt_type_out);
653 [ # # ]: 0 : uint16_t pkt_type_inner = rte_be_to_cpu_16(pd_hdr->pkt_type_in);
654 : :
655 [ # # ]: 0 : if (unlikely(pkt_flag & (ZXDH_MBUF_F_RX_1588_PTP | ZXDH_MBUF_F_RX_1588_TMST))) {
656 [ # # ]: 0 : if (pkt_flag & ZXDH_MBUF_F_RX_1588_PTP)
657 : 0 : m->ol_flags |= RTE_MBUF_F_RX_IEEE1588_PTP;
658 [ # # ]: 0 : if (pkt_flag & ZXDH_MBUF_F_RX_1588_TMST)
659 : 0 : m->ol_flags |= RTE_MBUF_F_RX_IEEE1588_TMST;
660 : : }
661 : :
662 [ # # ]: 0 : if (pkt_flag & ZXDH_MBUF_F_RX_VLAN_STRIPPED) {
663 : 0 : m->ol_flags |= (RTE_MBUF_F_RX_VLAN_STRIPPED | RTE_MBUF_F_RX_VLAN);
664 [ # # ]: 0 : m->vlan_tci = (unlikely(pkt_flag & ZXDH_MBUF_F_RX_QINQ))
665 : 0 : ? (striped_vlan_tci >> 16) & ZXDH_VLAN_ID_MASK
666 : 0 : : striped_vlan_tci & ZXDH_VLAN_ID_MASK;
667 : : }
668 : :
669 [ # # ]: 0 : if (unlikely(pkt_flag & ZXDH_MBUF_F_RX_QINQ_STRIPPED)) {
670 : : /*
671 : : * When PKT_RX_QINQ_STRIPPED is set and PKT_RX_VLAN_STRIPPED is unset:
672 : : * - Only the outer VLAN is removed from the packet data.
673 : : * - Both TCI values are saved: the inner TCI in mbuf->vlan_tci and
674 : : * the outer TCI in mbuf->vlan_tci_outer.
675 : : *
676 : : * When PKT_RX_QINQ is set, PKT_RX_VLAN must also be set, and the inner
677 : : * TCI is saved in mbuf->vlan_tci.
678 : : */
679 : 0 : m->ol_flags |= (RTE_MBUF_F_RX_QINQ_STRIPPED | RTE_MBUF_F_RX_QINQ);
680 : 0 : m->ol_flags |= (RTE_MBUF_F_RX_VLAN_STRIPPED | RTE_MBUF_F_RX_VLAN);
681 : 0 : m->vlan_tci = striped_vlan_tci & ZXDH_VLAN_ID_MASK;
682 : 0 : m->vlan_tci_outer = (striped_vlan_tci >> 16) & ZXDH_VLAN_ID_MASK;
683 : : }
684 : :
685 : : /* rss hash/fd handle */
686 [ # # ]: 0 : if (pkt_flag & ZXDH_MBUF_F_RX_RSS_HASH) {
687 [ # # ]: 0 : m->hash.rss = rte_be_to_cpu_32(pd_hdr->rss_hash);
688 : 0 : m->ol_flags |= RTE_MBUF_F_RX_RSS_HASH;
689 : : }
690 [ # # ]: 0 : if (pkt_flag & ZXDH_MBUF_F_RX_FDIR) {
691 : 0 : m->ol_flags |= RTE_MBUF_F_RX_FDIR;
692 [ # # ]: 0 : if (pkt_flag & ZXDH_MBUF_F_RX_FDIR_ID) {
693 [ # # ]: 0 : m->hash.fdir.hi = rte_be_to_cpu_32(pd_hdr->fd);
694 : 0 : m->ol_flags |= RTE_MBUF_F_RX_FDIR_ID;
695 [ # # ]: 0 : } else if ((pkt_flag & ZXDH_MBUF_F_RX_FDIR_FLX_MASK) == FELX_4BYTE) {
696 [ # # ]: 0 : m->hash.fdir.hi = rte_be_to_cpu_32(pd_hdr->fd);
697 : 0 : m->ol_flags |= RTE_MBUF_F_RX_FDIR_FLX;
698 [ # # ]: 0 : } else if (((pkt_flag & ZXDH_MBUF_F_RX_FDIR_FLX_MASK) == FELX_8BYTE)) {
699 [ # # ]: 0 : m->hash.fdir.hi = rte_be_to_cpu_32(pd_hdr->rss_hash);
700 [ # # ]: 0 : m->hash.fdir.lo = rte_be_to_cpu_32(pd_hdr->fd);
701 : 0 : m->ol_flags |= RTE_MBUF_F_RX_FDIR_FLX;
702 : : }
703 : : }
704 : : /* checksum handle */
705 [ # # ]: 0 : if (pkt_flag & ZXDH_MBUF_F_RX_OUTER_IP_CKSUM_BAD)
706 : 0 : m->ol_flags |= RTE_MBUF_F_RX_OUTER_IP_CKSUM_BAD;
707 [ # # ]: 0 : if (pkt_flag & ZXDH_MBUF_F_RX_OUTER_L4_CKSUM_GOOD)
708 : 0 : m->ol_flags |= RTE_MBUF_F_RX_OUTER_L4_CKSUM_GOOD;
709 : :
710 [ # # ]: 0 : if (has_pi) {
711 : : struct zxdh_pi_hdr *pi_hdr = &hdr->pipd_hdr_ul.pi_hdr;
712 : 0 : uint16_t pkt_type_masked = pi_hdr->pkt_type & ZXDH_PCODE_MASK;
713 [ # # ]: 0 : uint16_t err_code = rte_be_to_cpu_16(pi_hdr->ul.err_code);
714 : :
715 : 0 : bool is_ip_pkt =
716 [ # # # # ]: 0 : (pi_hdr->pkt_type == ZXDH_PCODE_IP_PKT_TYPE) ||
717 : : ((pi_hdr->pkt_type & ZXDH_PI_L3TYPE_MASK) == ZXDH_PI_L3TYPE_IP);
718 : :
719 : 0 : bool is_l4_pkt =
720 : 0 : (pkt_type_masked == ZXDH_PCODE_UDP_PKT_TYPE) ||
721 [ # # # # ]: 0 : (pkt_type_masked == ZXDH_PCODE_NO_REASSMBLE_TCP_PKT_TYPE) ||
722 : : (pkt_type_masked == ZXDH_PCODE_TCP_PKT_TYPE);
723 : :
724 [ # # # # ]: 0 : if (is_ip_pkt && (pi_hdr->pkt_flag_hi8 & ZXDH_RX_IP_CKSUM_VERIFY)) {
725 [ # # ]: 0 : if (err_code & ZXDH_IPV4_CSUM_ERR)
726 : 0 : m->ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_BAD;
727 : : else
728 : 0 : m->ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_GOOD;
729 : : }
730 : :
731 [ # # # # ]: 0 : if (is_l4_pkt && (pi_hdr->pkt_flag_hi8 & ZXDH_RX_TCPUDP_CKSUM_VERIFY)) {
732 [ # # ]: 0 : if (err_code & (ZXDH_TCP_CSUM_ERR | ZXDH_UDP_CSUM_ERR))
733 : 0 : m->ol_flags |= RTE_MBUF_F_RX_L4_CKSUM_BAD;
734 : : else
735 : 0 : m->ol_flags |= RTE_MBUF_F_RX_L4_CKSUM_GOOD;
736 : : }
737 : :
738 [ # # ]: 0 : if (ntohl(pi_hdr->ul.lro_flag) & ZXDH_PI_LRO_FLAG)
739 : 0 : m->ol_flags |= RTE_MBUF_F_RX_LRO;
740 : :
741 [ # # ]: 0 : m->pkt_len = rte_be_to_cpu_16(pi_hdr->ul.pkt_len);
742 : : } else {
743 [ # # ]: 0 : m->pkt_len = rte_be_to_cpu_16(pd_hdr->pkt_len);
744 : : }
745 : :
746 : 0 : idx = (pkt_type_outer >> 12) & 0xF;
747 : 0 : m->packet_type = zxdh_outer_l2_type[idx];
748 : 0 : idx = (pkt_type_outer >> 8) & 0xF;
749 : 0 : m->packet_type |= zxdh_outer_l3_type[idx];
750 : 0 : idx = (pkt_type_outer >> 4) & 0xF;
751 : 0 : m->packet_type |= zxdh_outer_l4_type[idx];
752 : 0 : idx = pkt_type_outer & 0xF;
753 : 0 : m->packet_type |= zxdh_tunnel_type[idx];
754 : :
755 [ # # ]: 0 : if (pkt_type_inner) {
756 : 0 : idx = (pkt_type_inner >> 12) & 0xF;
757 : 0 : m->packet_type |= zxdh_inner_l2_type[idx];
758 : 0 : idx = (pkt_type_inner >> 8) & 0xF;
759 : 0 : m->packet_type |= zxdh_inner_l3_type[idx];
760 : 0 : idx = (pkt_type_inner >> 4) & 0xF;
761 : 0 : m->packet_type |= zxdh_inner_l4_type[idx];
762 : : }
763 : :
764 : 0 : }
765 : :
766 : 0 : static void zxdh_discard_rxbuf(struct zxdh_virtqueue *vq, struct rte_mbuf *m)
767 : : {
768 : : int32_t error = 0;
769 : : /*
770 : : * Requeue the discarded mbuf. This should always be
771 : : * successful since it was just dequeued.
772 : : */
773 : 0 : error = zxdh_enqueue_recv_refill_packed(vq, &m, 1);
774 [ # # ]: 0 : if (unlikely(error)) {
775 : 0 : PMD_RX_LOG(ERR, "cannot enqueue discarded mbuf");
776 : 0 : rte_pktmbuf_free(m);
777 : : }
778 : 0 : }
779 : :
780 : : uint16_t
781 : 0 : zxdh_recv_pkts_packed(void *rx_queue, struct rte_mbuf **rx_pkts,
782 : : uint16_t nb_pkts)
783 : : {
784 : : struct zxdh_virtnet_rx *rxvq = rx_queue;
785 : 0 : struct zxdh_virtqueue *vq = rxvq->vq;
786 : 0 : struct zxdh_hw *hw = vq->hw;
787 : : struct rte_mbuf *rxm = NULL;
788 : : struct rte_mbuf *prev = NULL;
789 : : struct zxdh_net_hdr_ul *header = NULL;
790 : 0 : uint32_t lens[ZXDH_MBUF_BURST_SZ] = {0};
791 : 0 : struct rte_mbuf *rcv_pkts[ZXDH_MBUF_BURST_SZ] = {NULL};
792 : : uint16_t len = 0;
793 : : uint32_t seg_num = 0;
794 : : uint32_t seg_res = 0;
795 : : uint32_t error = 0;
796 : : uint16_t hdr_size = 0;
797 : : uint16_t nb_rx = 0;
798 : : uint16_t i;
799 : : uint16_t rcvd_pkt_len = 0;
800 : : uint16_t num = nb_pkts;
801 : :
802 [ # # ]: 0 : if (unlikely(num > ZXDH_MBUF_BURST_SZ))
803 : : num = ZXDH_MBUF_BURST_SZ;
804 : :
805 : 0 : num = zxdh_dequeue_burst_rx_packed(vq, rcv_pkts, lens, num);
806 [ # # ]: 0 : if (num == 0) {
807 : 0 : rxvq->stats.idle++;
808 : 0 : goto refill;
809 : : }
810 : :
811 [ # # ]: 0 : for (i = 0; i < num; i++) {
812 : 0 : rxm = rcv_pkts[i];
813 : 0 : rx_pkts[nb_rx] = rxm;
814 : : prev = rxm;
815 : 0 : len = lens[i];
816 : 0 : header = rte_pktmbuf_mtod(rxm, struct zxdh_net_hdr_ul *);
817 : :
818 : 0 : seg_num = header->type_hdr.num_buffers;
819 : :
820 : : /* Private queue only handle type hdr */
821 : : hdr_size = ZXDH_TYPE_HDR_SIZE;
822 : 0 : rxm->pkt_len = ((header->type_hdr.port & 0x7f) << 8) +
823 : 0 : header->type_hdr.pd_len;
824 : 0 : rxm->data_off += hdr_size;
825 : 0 : rxm->nb_segs = seg_num;
826 : 0 : rxm->ol_flags = 0;
827 : 0 : rcvd_pkt_len = len - hdr_size;
828 : 0 : rxm->data_len = rcvd_pkt_len;
829 : 0 : rxm->port = rxvq->port_id;
830 : :
831 : : /* Update rte_mbuf according to pi/pd header */
832 : 0 : zxdh_rx_update_mbuf(rxm, header);
833 : 0 : seg_res = seg_num - 1;
834 : : /* Merge remaining segments */
835 [ # # # # ]: 0 : while (seg_res != 0 && i < (num - 1)) {
836 : 0 : i++;
837 : 0 : len = lens[i];
838 : 0 : rxm = rcv_pkts[i];
839 : 0 : rxm->data_len = len;
840 : 0 : rcvd_pkt_len += len;
841 : 0 : prev->next = rxm;
842 : : prev = rxm;
843 : 0 : rxm->next = NULL;
844 : 0 : seg_res -= 1;
845 : : }
846 : :
847 [ # # ]: 0 : if (!seg_res) {
848 [ # # ]: 0 : if (rcvd_pkt_len != rx_pkts[nb_rx]->pkt_len) {
849 : 0 : PMD_RX_LOG(ERR, "dropped rcvd_pkt_len %d pktlen %d",
850 : : rcvd_pkt_len, rx_pkts[nb_rx]->pkt_len);
851 : 0 : zxdh_discard_rxbuf(vq, rx_pkts[nb_rx]);
852 : 0 : rxvq->stats.errors++;
853 : 0 : rxvq->stats.truncated_err++;
854 : 0 : continue;
855 : : }
856 : : zxdh_update_packet_stats(&rxvq->stats, rx_pkts[nb_rx]);
857 : 0 : nb_rx++;
858 : : }
859 : : }
860 : : /* Last packet still need merge segments */
861 [ # # ]: 0 : while (seg_res != 0) {
862 : 0 : uint16_t rcv_cnt = RTE_MIN((uint16_t)seg_res, ZXDH_MBUF_BURST_SZ);
863 : : uint16_t extra_idx = 0;
864 : :
865 : 0 : rcv_cnt = zxdh_dequeue_burst_rx_packed(vq, rcv_pkts, lens, rcv_cnt);
866 [ # # ]: 0 : if (unlikely(rcv_cnt == 0)) {
867 : 0 : PMD_RX_LOG(ERR, "No enough segments for packet");
868 : 0 : rte_pktmbuf_free(rx_pkts[nb_rx]);
869 : 0 : rxvq->stats.errors++;
870 : 0 : rxvq->stats.no_segs_err++;
871 : 0 : break;
872 : : }
873 [ # # ]: 0 : while (extra_idx < rcv_cnt) {
874 : 0 : rxm = rcv_pkts[extra_idx];
875 : 0 : rcvd_pkt_len += (uint16_t)(lens[extra_idx]);
876 : 0 : rxm->data_len = lens[extra_idx];
877 : 0 : prev->next = rxm;
878 : : prev = rxm;
879 : 0 : rxm->next = NULL;
880 : 0 : extra_idx += 1;
881 : : }
882 : 0 : seg_res -= rcv_cnt;
883 [ # # ]: 0 : if (!seg_res) {
884 [ # # ]: 0 : if (unlikely(rcvd_pkt_len != rx_pkts[nb_rx]->pkt_len)) {
885 : 0 : PMD_RX_LOG(ERR, "dropped rcvd_pkt_len %d pktlen %d",
886 : : rcvd_pkt_len, rx_pkts[nb_rx]->pkt_len);
887 : 0 : zxdh_discard_rxbuf(vq, rx_pkts[nb_rx]);
888 : 0 : rxvq->stats.errors++;
889 : 0 : rxvq->stats.truncated_err++;
890 : 0 : continue;
891 : : }
892 : : zxdh_update_packet_stats(&rxvq->stats, rx_pkts[nb_rx]);
893 : 0 : nb_rx++;
894 : : }
895 : : }
896 : 0 : rxvq->stats.packets += nb_rx;
897 : :
898 [ # # ]: 0 : refill:
899 : : /* Allocate new mbuf for the used descriptor */
900 [ # # ]: 0 : if (likely(!zxdh_queue_full(vq))) {
901 : : /* free_cnt may include mrg descs */
902 : : uint16_t free_cnt = vq->vq_free_cnt;
903 : 0 : struct rte_mbuf *new_pkts[free_cnt];
904 : :
905 [ # # ]: 0 : if (!rte_pktmbuf_alloc_bulk(rxvq->mpool, new_pkts, free_cnt)) {
906 : 0 : error = zxdh_enqueue_recv_refill_packed(vq, new_pkts, free_cnt);
907 [ # # ]: 0 : if (unlikely(error)) {
908 [ # # ]: 0 : for (i = 0; i < free_cnt; i++)
909 : 0 : rte_pktmbuf_free(new_pkts[i]);
910 : : }
911 : :
912 [ # # ]: 0 : if (unlikely(zxdh_queue_kick_prepare_packed(vq)))
913 : : zxdh_queue_notify(vq);
914 : : } else {
915 : 0 : struct rte_eth_dev *dev = hw->eth_dev;
916 : :
917 : 0 : dev->data->rx_mbuf_alloc_failed += free_cnt;
918 : : }
919 : : }
920 : 0 : return nb_rx;
921 : : }
|