summaryrefslogtreecommitdiffstats
path: root/src/spdk/dpdk/drivers/net/nfb/nfb_rx.h
blob: cf3899b2fb7d298258d89670d98b265066db68bf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
/* SPDX-License-Identifier: BSD-3-Clause
 * Copyright(c) 2019 Cesnet
 * Copyright(c) 2019 Netcope Technologies, a.s. <info@netcope.com>
 * All rights reserved.
 */

#ifndef _NFB_RX_H_
#define _NFB_RX_H_

#include <nfb/nfb.h>
#include <nfb/ndp.h>

#include <rte_mbuf.h>
#include <rte_ethdev.h>

#define NFB_TIMESTAMP_FLAG (1 << 0)

struct ndp_rx_queue {
	struct nfb_device *nfb;	     /* nfb dev structure */
	struct ndp_queue *queue;     /* rx queue */
	uint16_t rx_queue_id;	     /* index */
	uint8_t in_port;	     /* port */
	uint8_t flags;               /* setup flags */

	struct rte_mempool *mb_pool; /* memory pool to allocate packets */
	uint16_t buf_size;           /* mbuf size */

	volatile uint64_t rx_pkts;   /* packets read */
	volatile uint64_t rx_bytes;  /* bytes read */
	volatile uint64_t err_pkts;  /* erroneous packets */
};

/**
 * Initialize ndp_rx_queue structure
 *
 * @param nfb
 *   Pointer to nfb device structure.
 * @param rx_queue_id
 *   RX queue index.
 * @param port_id
 *   Device [external] port identifier.
 * @param mb_pool
 *   Memory pool for buffer allocations.
 * @param[out] rxq
 *   Pointer to ndp_rx_queue output structure
 * @return
 *   0 on success, a negative errno value otherwise.
 */
int
nfb_eth_rx_queue_init(struct nfb_device *nfb,
	uint16_t rx_queue_id,
	uint16_t port_id,
	struct rte_mempool *mb_pool,
	struct ndp_rx_queue *rxq);

/**
 * DPDK callback to setup a RX queue for use.
 *
 * @param dev
 *   Pointer to Ethernet device structure.
 * @param idx
 *   RX queue index.
 * @param desc
 *   Number of descriptors to configure in queue.
 * @param socket
 *   NUMA socket on which memory must be allocated.
 * @param[in] conf
 *   Thresholds parameters.
 * @param mb_pool
 *   Memory pool for buffer allocations.
 *
 * @return
 *   0 on success, a negative errno value otherwise.
 */
int
nfb_eth_rx_queue_setup(struct rte_eth_dev *dev,
	uint16_t rx_queue_id,
	uint16_t nb_rx_desc __rte_unused,
	unsigned int socket_id,
	const struct rte_eth_rxconf *rx_conf __rte_unused,
	struct rte_mempool *mb_pool);

/**
 * DPDK callback to release a RX queue.
 *
 * @param dpdk_rxq
 *   Generic RX queue pointer.
 */
void
nfb_eth_rx_queue_release(void *q);

/**
 * Start traffic on Rx queue.
 *
 * @param dev
 *   Pointer to Ethernet device structure.
 * @param txq_id
 *   RX queue index.
 * @return
 *   0 on success, a negative errno value otherwise.
 */
int
nfb_eth_rx_queue_start(struct rte_eth_dev *dev, uint16_t rxq_id);

/**
 * Stop traffic on Rx queue.
 *
 * @param dev
 *   Pointer to Ethernet device structure.
 * @param txq_id
 *   RX queue index.
 */
int
nfb_eth_rx_queue_stop(struct rte_eth_dev *dev, uint16_t rxq_id);

/**
 * DPDK callback for RX.
 *
 * @param dpdk_rxq
 *   Generic pointer to RX queue structure.
 * @param[out] bufs
 *   Array to store received packets.
 * @param nb_pkts
 *   Maximum number of packets in array.
 *
 * @return
 *   Number of packets successfully received (<= nb_pkts).
 */
static __rte_always_inline uint16_t
nfb_eth_ndp_rx(void *queue,
	struct rte_mbuf **bufs,
	uint16_t nb_pkts)
{
	struct ndp_rx_queue *ndp = queue;
	uint8_t timestamping_enabled;
	uint16_t packet_size;
	uint64_t num_bytes = 0;
	uint16_t num_rx;
	unsigned int i;

	const uint16_t buf_size = ndp->buf_size;

	struct rte_mbuf *mbuf;
	struct ndp_packet packets[nb_pkts];

	struct rte_mbuf *mbufs[nb_pkts];

	if (unlikely(ndp->queue == NULL || nb_pkts == 0)) {
		RTE_LOG(ERR, PMD, "RX invalid arguments!\n");
		return 0;
	}

	timestamping_enabled = ndp->flags & NFB_TIMESTAMP_FLAG;

	/* returns either all or nothing */
	i = rte_pktmbuf_alloc_bulk(ndp->mb_pool, mbufs, nb_pkts);
	if (unlikely(i != 0))
		return 0;

	num_rx = ndp_rx_burst_get(ndp->queue, packets, nb_pkts);

	if (unlikely(num_rx != nb_pkts)) {
		for (i = num_rx; i < nb_pkts; i++)
			rte_pktmbuf_free(mbufs[i]);
	}

	nb_pkts = num_rx;

	num_rx = 0;
	/*
	 * Reads the given number of packets from NDP queue given
	 * by queue and copies the packet data into a newly allocated mbuf
	 * to return.
	 */
	for (i = 0; i < nb_pkts; ++i) {
		mbuf = mbufs[i];

		/* get the space available for data in the mbuf */
		packet_size = packets[i].data_length;

		if (likely(packet_size <= buf_size)) {
			/* NDP packet will fit in one mbuf, go ahead and copy */
			rte_memcpy(rte_pktmbuf_mtod(mbuf, void *),
				packets[i].data, packet_size);

			mbuf->data_len = (uint16_t)packet_size;

			mbuf->pkt_len = packet_size;
			mbuf->port = ndp->in_port;
			mbuf->ol_flags = 0;

			if (timestamping_enabled) {
				/* nanoseconds */
				mbuf->timestamp =
					rte_le_to_cpu_32(*((uint32_t *)
					(packets[i].header + 4)));
				mbuf->timestamp <<= 32;
				/* seconds */
				mbuf->timestamp |=
					rte_le_to_cpu_32(*((uint32_t *)
					(packets[i].header + 8)));
				mbuf->ol_flags |= PKT_RX_TIMESTAMP;
			}

			bufs[num_rx++] = mbuf;
			num_bytes += packet_size;
		} else {
			/*
			 * NDP packet will not fit in one mbuf,
			 * scattered mode is not enabled, drop packet
			 */
			rte_pktmbuf_free(mbuf);
		}
	}

	ndp_rx_burst_put(ndp->queue);

	ndp->rx_pkts += num_rx;
	ndp->rx_bytes += num_bytes;
	return num_rx;
}

#endif /* _NFB_RX_H_ */