1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2019 Cesnet 3 * Copyright(c) 2019 Netcope Technologies, a.s. <[email protected]> 4 * All rights reserved. 5 */ 6 7 #ifndef _NFB_RX_H_ 8 #define _NFB_RX_H_ 9 10 #include <nfb/nfb.h> 11 #include <nfb/ndp.h> 12 13 #include <rte_mbuf.h> 14 #include <rte_mbuf_dyn.h> 15 #include <rte_ethdev.h> 16 17 #define NFB_TIMESTAMP_FLAG (1 << 0) 18 19 extern uint64_t nfb_timestamp_rx_dynflag; 20 extern int nfb_timestamp_dynfield_offset; 21 22 static inline rte_mbuf_timestamp_t * 23 nfb_timestamp_dynfield(struct rte_mbuf *mbuf) 24 { 25 return RTE_MBUF_DYNFIELD(mbuf, 26 nfb_timestamp_dynfield_offset, rte_mbuf_timestamp_t *); 27 } 28 29 struct ndp_rx_queue { 30 struct nfb_device *nfb; /* nfb dev structure */ 31 struct ndp_queue *queue; /* rx queue */ 32 uint16_t rx_queue_id; /* index */ 33 uint8_t in_port; /* port */ 34 uint8_t flags; /* setup flags */ 35 36 struct rte_mempool *mb_pool; /* memory pool to allocate packets */ 37 uint16_t buf_size; /* mbuf size */ 38 39 volatile uint64_t rx_pkts; /* packets read */ 40 volatile uint64_t rx_bytes; /* bytes read */ 41 volatile uint64_t err_pkts; /* erroneous packets */ 42 }; 43 44 /** 45 * Initialize ndp_rx_queue structure 46 * 47 * @param nfb 48 * Pointer to nfb device structure. 49 * @param rx_queue_id 50 * RX queue index. 51 * @param port_id 52 * Device [external] port identifier. 53 * @param mb_pool 54 * Memory pool for buffer allocations. 55 * @param[out] rxq 56 * Pointer to ndp_rx_queue output structure 57 * @return 58 * 0 on success, a negative errno value otherwise. 59 */ 60 int 61 nfb_eth_rx_queue_init(struct nfb_device *nfb, 62 uint16_t rx_queue_id, 63 uint16_t port_id, 64 struct rte_mempool *mb_pool, 65 struct ndp_rx_queue *rxq); 66 67 /** 68 * DPDK callback to setup a RX queue for use. 69 * 70 * @param dev 71 * Pointer to Ethernet device structure. 72 * @param idx 73 * RX queue index. 74 * @param desc 75 * Number of descriptors to configure in queue. 76 * @param socket 77 * NUMA socket on which memory must be allocated. 78 * @param[in] conf 79 * Thresholds parameters. 80 * @param mb_pool 81 * Memory pool for buffer allocations. 82 * 83 * @return 84 * 0 on success, a negative errno value otherwise. 85 */ 86 int 87 nfb_eth_rx_queue_setup(struct rte_eth_dev *dev, 88 uint16_t rx_queue_id, 89 uint16_t nb_rx_desc __rte_unused, 90 unsigned int socket_id, 91 const struct rte_eth_rxconf *rx_conf __rte_unused, 92 struct rte_mempool *mb_pool); 93 94 /** 95 * DPDK callback to release a RX queue. 96 * 97 * @param dev 98 * Pointer to Ethernet device structure. 99 * @param qid 100 * Receive queue index. 101 */ 102 void 103 nfb_eth_rx_queue_release(struct rte_eth_dev *dev, uint16_t qid); 104 105 /** 106 * Start traffic on Rx queue. 107 * 108 * @param dev 109 * Pointer to Ethernet device structure. 110 * @param txq_id 111 * RX queue index. 112 * @return 113 * 0 on success, a negative errno value otherwise. 114 */ 115 int 116 nfb_eth_rx_queue_start(struct rte_eth_dev *dev, uint16_t rxq_id); 117 118 /** 119 * Stop traffic on Rx queue. 120 * 121 * @param dev 122 * Pointer to Ethernet device structure. 123 * @param txq_id 124 * RX queue index. 125 */ 126 int 127 nfb_eth_rx_queue_stop(struct rte_eth_dev *dev, uint16_t rxq_id); 128 129 /** 130 * DPDK callback for RX. 131 * 132 * @param dpdk_rxq 133 * Generic pointer to RX queue structure. 134 * @param[out] bufs 135 * Array to store received packets. 136 * @param nb_pkts 137 * Maximum number of packets in array. 138 * 139 * @return 140 * Number of packets successfully received (<= nb_pkts). 141 */ 142 static __rte_always_inline uint16_t 143 nfb_eth_ndp_rx(void *queue, 144 struct rte_mbuf **bufs, 145 uint16_t nb_pkts) 146 { 147 struct ndp_rx_queue *ndp = queue; 148 uint8_t timestamping_enabled; 149 uint16_t packet_size; 150 uint64_t num_bytes = 0; 151 uint16_t num_rx; 152 unsigned int i; 153 154 const uint16_t buf_size = ndp->buf_size; 155 156 struct rte_mbuf *mbuf; 157 struct ndp_packet packets[nb_pkts]; 158 159 struct rte_mbuf *mbufs[nb_pkts]; 160 161 if (unlikely(ndp->queue == NULL || nb_pkts == 0)) { 162 RTE_LOG(ERR, PMD, "RX invalid arguments!\n"); 163 return 0; 164 } 165 166 timestamping_enabled = ndp->flags & NFB_TIMESTAMP_FLAG; 167 168 /* returns either all or nothing */ 169 i = rte_pktmbuf_alloc_bulk(ndp->mb_pool, mbufs, nb_pkts); 170 if (unlikely(i != 0)) 171 return 0; 172 173 num_rx = ndp_rx_burst_get(ndp->queue, packets, nb_pkts); 174 175 if (unlikely(num_rx != nb_pkts)) { 176 for (i = num_rx; i < nb_pkts; i++) 177 rte_pktmbuf_free(mbufs[i]); 178 } 179 180 nb_pkts = num_rx; 181 182 num_rx = 0; 183 /* 184 * Reads the given number of packets from NDP queue given 185 * by queue and copies the packet data into a newly allocated mbuf 186 * to return. 187 */ 188 for (i = 0; i < nb_pkts; ++i) { 189 mbuf = mbufs[i]; 190 191 /* get the space available for data in the mbuf */ 192 packet_size = packets[i].data_length; 193 194 if (likely(packet_size <= buf_size)) { 195 /* NDP packet will fit in one mbuf, go ahead and copy */ 196 rte_memcpy(rte_pktmbuf_mtod(mbuf, void *), 197 packets[i].data, packet_size); 198 199 mbuf->data_len = (uint16_t)packet_size; 200 201 mbuf->pkt_len = packet_size; 202 mbuf->port = ndp->in_port; 203 mbuf->ol_flags = 0; 204 205 if (timestamping_enabled) { 206 rte_mbuf_timestamp_t timestamp; 207 208 /* nanoseconds */ 209 timestamp = 210 rte_le_to_cpu_32(*((uint32_t *) 211 (packets[i].header + 4))); 212 timestamp <<= 32; 213 /* seconds */ 214 timestamp |= 215 rte_le_to_cpu_32(*((uint32_t *) 216 (packets[i].header + 8))); 217 *nfb_timestamp_dynfield(mbuf) = timestamp; 218 mbuf->ol_flags |= nfb_timestamp_rx_dynflag; 219 } 220 221 bufs[num_rx++] = mbuf; 222 num_bytes += packet_size; 223 } else { 224 /* 225 * NDP packet will not fit in one mbuf, 226 * scattered mode is not enabled, drop packet 227 */ 228 rte_pktmbuf_free(mbuf); 229 } 230 } 231 232 ndp_rx_burst_put(ndp->queue); 233 234 ndp->rx_pkts += num_rx; 235 ndp->rx_bytes += num_bytes; 236 return num_rx; 237 } 238 239 #endif /* _NFB_RX_H_ */ 240