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 : : }
|