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