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