Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2010-2014 Intel Corporation
3 : : */
4 : : #include <string.h>
5 : :
6 : : #include <rte_ip_frag.h>
7 : :
8 : : #include "rte_port_frag.h"
9 : :
10 : : #include "port_log.h"
11 : :
12 : : /* Max number of fragments per packet allowed */
13 : : #define RTE_PORT_FRAG_MAX_FRAGS_PER_PACKET 0x80
14 : :
15 : : #ifdef RTE_PORT_STATS_COLLECT
16 : :
17 : : #define RTE_PORT_RING_READER_FRAG_STATS_PKTS_IN_ADD(port, val) \
18 : : port->stats.n_pkts_in += val
19 : : #define RTE_PORT_RING_READER_FRAG_STATS_PKTS_DROP_ADD(port, val) \
20 : : port->stats.n_pkts_drop += val
21 : :
22 : : #else
23 : :
24 : : #define RTE_PORT_RING_READER_FRAG_STATS_PKTS_IN_ADD(port, val)
25 : : #define RTE_PORT_RING_READER_FRAG_STATS_PKTS_DROP_ADD(port, val)
26 : :
27 : : #endif
28 : :
29 : : typedef int32_t
30 : : (*frag_op)(struct rte_mbuf *pkt_in,
31 : : struct rte_mbuf **pkts_out,
32 : : uint16_t nb_pkts_out,
33 : : uint16_t mtu_size,
34 : : struct rte_mempool *pool_direct,
35 : : struct rte_mempool *pool_indirect);
36 : :
37 : : struct __rte_cache_aligned rte_port_ring_reader_frag {
38 : : struct rte_port_in_stats stats;
39 : :
40 : : /* Input parameters */
41 : : struct rte_ring *ring;
42 : : uint32_t mtu;
43 : : uint32_t metadata_size;
44 : : struct rte_mempool *pool_direct;
45 : : struct rte_mempool *pool_indirect;
46 : :
47 : : /* Internal buffers */
48 : : struct rte_mbuf *pkts[RTE_PORT_IN_BURST_SIZE_MAX];
49 : : struct rte_mbuf *frags[RTE_PORT_FRAG_MAX_FRAGS_PER_PACKET];
50 : : uint32_t n_pkts;
51 : : uint32_t pos_pkts;
52 : : uint32_t n_frags;
53 : : uint32_t pos_frags;
54 : :
55 : : frag_op f_frag;
56 : : };
57 : :
58 : : static void *
59 : 0 : rte_port_ring_reader_frag_create(void *params, int socket_id, int is_ipv4)
60 : : {
61 : : struct rte_port_ring_reader_frag_params *conf =
62 : : params;
63 : : struct rte_port_ring_reader_frag *port;
64 : :
65 : : /* Check input parameters */
66 [ # # ]: 0 : if (conf == NULL) {
67 : 0 : PORT_LOG(ERR, "%s: Parameter conf is NULL", __func__);
68 : 0 : return NULL;
69 : : }
70 [ # # ]: 0 : if (conf->ring == NULL) {
71 : 0 : PORT_LOG(ERR, "%s: Parameter ring is NULL", __func__);
72 : 0 : return NULL;
73 : : }
74 [ # # ]: 0 : if (conf->mtu == 0) {
75 : 0 : PORT_LOG(ERR, "%s: Parameter mtu is invalid", __func__);
76 : 0 : return NULL;
77 : : }
78 [ # # ]: 0 : if (conf->pool_direct == NULL) {
79 : 0 : PORT_LOG(ERR, "%s: Parameter pool_direct is NULL",
80 : : __func__);
81 : 0 : return NULL;
82 : : }
83 [ # # ]: 0 : if (conf->pool_indirect == NULL) {
84 : 0 : PORT_LOG(ERR, "%s: Parameter pool_indirect is NULL",
85 : : __func__);
86 : 0 : return NULL;
87 : : }
88 : :
89 : : /* Memory allocation */
90 : 0 : port = rte_zmalloc_socket("PORT", sizeof(*port), RTE_CACHE_LINE_SIZE,
91 : : socket_id);
92 [ # # ]: 0 : if (port == NULL) {
93 : 0 : PORT_LOG(ERR, "%s: port is NULL", __func__);
94 : 0 : return NULL;
95 : : }
96 : :
97 : : /* Initialization */
98 : 0 : port->ring = conf->ring;
99 : 0 : port->mtu = conf->mtu;
100 : 0 : port->metadata_size = conf->metadata_size;
101 : 0 : port->pool_direct = conf->pool_direct;
102 : 0 : port->pool_indirect = conf->pool_indirect;
103 : :
104 : 0 : port->n_pkts = 0;
105 : 0 : port->pos_pkts = 0;
106 : 0 : port->n_frags = 0;
107 : 0 : port->pos_frags = 0;
108 : :
109 : 0 : port->f_frag = (is_ipv4) ?
110 [ # # ]: 0 : rte_ipv4_fragment_packet : rte_ipv6_fragment_packet;
111 : :
112 : 0 : return port;
113 : : }
114 : :
115 : : static void *
116 : 0 : rte_port_ring_reader_ipv4_frag_create(void *params, int socket_id)
117 : : {
118 : 0 : return rte_port_ring_reader_frag_create(params, socket_id, 1);
119 : : }
120 : :
121 : : static void *
122 : 0 : rte_port_ring_reader_ipv6_frag_create(void *params, int socket_id)
123 : : {
124 : 0 : return rte_port_ring_reader_frag_create(params, socket_id, 0);
125 : : }
126 : :
127 : : static int
128 : 0 : rte_port_ring_reader_frag_rx(void *port,
129 : : struct rte_mbuf **pkts,
130 : : uint32_t n_pkts)
131 : : {
132 : : struct rte_port_ring_reader_frag *p =
133 : : port;
134 : : uint32_t n_pkts_out;
135 : :
136 : : n_pkts_out = 0;
137 : :
138 : : /* Get packets from the "frag" buffer */
139 [ # # ]: 0 : if (p->n_frags >= n_pkts) {
140 : 0 : memcpy(pkts, &p->frags[p->pos_frags], n_pkts * sizeof(void *));
141 : 0 : p->pos_frags += n_pkts;
142 : 0 : p->n_frags -= n_pkts;
143 : :
144 : 0 : return n_pkts;
145 : : }
146 : :
147 : 0 : memcpy(pkts, &p->frags[p->pos_frags], p->n_frags * sizeof(void *));
148 : 0 : n_pkts_out = p->n_frags;
149 : 0 : p->n_frags = 0;
150 : :
151 : : /* Look to "pkts" buffer to get more packets */
152 : : for ( ; ; ) {
153 : : struct rte_mbuf *pkt;
154 : : uint32_t n_pkts_to_provide, i;
155 : : int status;
156 : :
157 : : /* If "pkts" buffer is empty, read packet burst from ring */
158 [ # # ]: 0 : if (p->n_pkts == 0) {
159 : 0 : p->n_pkts = rte_ring_sc_dequeue_burst(p->ring,
160 : 0 : (void **) p->pkts, RTE_PORT_IN_BURST_SIZE_MAX,
161 : : NULL);
162 : : RTE_PORT_RING_READER_FRAG_STATS_PKTS_IN_ADD(p, p->n_pkts);
163 [ # # ]: 0 : if (p->n_pkts == 0)
164 : 0 : return n_pkts_out;
165 : 0 : p->pos_pkts = 0;
166 : : }
167 : :
168 : : /* Read next packet from "pkts" buffer */
169 : 0 : pkt = p->pkts[p->pos_pkts++];
170 : 0 : p->n_pkts--;
171 : :
172 : : /* If not jumbo, pass current packet to output */
173 [ # # ]: 0 : if (pkt->pkt_len <= p->mtu) {
174 : 0 : pkts[n_pkts_out++] = pkt;
175 : :
176 : : n_pkts_to_provide = n_pkts - n_pkts_out;
177 [ # # ]: 0 : if (n_pkts_to_provide == 0)
178 : 0 : return n_pkts;
179 : :
180 : 0 : continue;
181 : : }
182 : :
183 : : /* Fragment current packet into the "frags" buffer */
184 : 0 : status = p->f_frag(
185 : : pkt,
186 : 0 : p->frags,
187 : : RTE_PORT_FRAG_MAX_FRAGS_PER_PACKET,
188 : : p->mtu,
189 : : p->pool_direct,
190 : : p->pool_indirect
191 : : );
192 : :
193 [ # # ]: 0 : if (status < 0) {
194 : 0 : rte_pktmbuf_free(pkt);
195 : : RTE_PORT_RING_READER_FRAG_STATS_PKTS_DROP_ADD(p, 1);
196 : 0 : continue;
197 : : }
198 : :
199 : 0 : p->n_frags = (uint32_t) status;
200 : 0 : p->pos_frags = 0;
201 : :
202 : : /* Copy meta-data from input jumbo packet to its fragments */
203 [ # # ]: 0 : for (i = 0; i < p->n_frags; i++) {
204 : 0 : uint8_t *src =
205 : : RTE_MBUF_METADATA_UINT8_PTR(pkt, sizeof(struct rte_mbuf));
206 : 0 : uint8_t *dst =
207 : 0 : RTE_MBUF_METADATA_UINT8_PTR(p->frags[i], sizeof(struct rte_mbuf));
208 : :
209 : 0 : memcpy(dst, src, p->metadata_size);
210 : : }
211 : :
212 : : /* Free input jumbo packet */
213 : 0 : rte_pktmbuf_free(pkt);
214 : :
215 : : /* Get packets from "frag" buffer */
216 : 0 : n_pkts_to_provide = n_pkts - n_pkts_out;
217 [ # # ]: 0 : if (p->n_frags >= n_pkts_to_provide) {
218 : 0 : memcpy(&pkts[n_pkts_out], p->frags,
219 : : n_pkts_to_provide * sizeof(void *));
220 : 0 : p->n_frags -= n_pkts_to_provide;
221 : 0 : p->pos_frags += n_pkts_to_provide;
222 : :
223 : 0 : return n_pkts;
224 : : }
225 : :
226 : 0 : memcpy(&pkts[n_pkts_out], p->frags,
227 : 0 : p->n_frags * sizeof(void *));
228 : 0 : n_pkts_out += p->n_frags;
229 : 0 : p->n_frags = 0;
230 : : }
231 : : }
232 : :
233 : : static int
234 : 0 : rte_port_ring_reader_frag_free(void *port)
235 : : {
236 [ # # ]: 0 : if (port == NULL) {
237 : 0 : PORT_LOG(ERR, "%s: Parameter port is NULL", __func__);
238 : 0 : return -1;
239 : : }
240 : :
241 : 0 : rte_free(port);
242 : :
243 : 0 : return 0;
244 : : }
245 : :
246 : : static int
247 : 0 : rte_port_frag_reader_stats_read(void *port,
248 : : struct rte_port_in_stats *stats, int clear)
249 : : {
250 : : struct rte_port_ring_reader_frag *p =
251 : : port;
252 : :
253 [ # # ]: 0 : if (stats != NULL)
254 : 0 : memcpy(stats, &p->stats, sizeof(p->stats));
255 : :
256 [ # # ]: 0 : if (clear)
257 : 0 : memset(&p->stats, 0, sizeof(p->stats));
258 : :
259 : 0 : return 0;
260 : : }
261 : :
262 : : /*
263 : : * Summary of port operations
264 : : */
265 : : struct rte_port_in_ops rte_port_ring_reader_ipv4_frag_ops = {
266 : : .f_create = rte_port_ring_reader_ipv4_frag_create,
267 : : .f_free = rte_port_ring_reader_frag_free,
268 : : .f_rx = rte_port_ring_reader_frag_rx,
269 : : .f_stats = rte_port_frag_reader_stats_read,
270 : : };
271 : :
272 : : struct rte_port_in_ops rte_port_ring_reader_ipv6_frag_ops = {
273 : : .f_create = rte_port_ring_reader_ipv6_frag_create,
274 : : .f_free = rte_port_ring_reader_frag_free,
275 : : .f_rx = rte_port_ring_reader_frag_rx,
276 : : .f_stats = rte_port_frag_reader_stats_read,
277 : : };
|