4 * Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
17 * * Neither the name of Intel Corporation nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 #include <rte_ether.h>
36 #include <rte_ip_frag.h>
37 #include <rte_memory.h>
39 #include "rte_port_frag.h"
41 /* Max number of fragments per packet allowed */
42 #define RTE_PORT_FRAG_MAX_FRAGS_PER_PACKET 0x80
44 #ifdef RTE_PORT_STATS_COLLECT
46 #define RTE_PORT_RING_READER_FRAG_STATS_PKTS_IN_ADD(port, val) \
47 port->stats.n_pkts_in += val
48 #define RTE_PORT_RING_READER_FRAG_STATS_PKTS_DROP_ADD(port, val) \
49 port->stats.n_pkts_drop += val
53 #define RTE_PORT_RING_READER_FRAG_STATS_PKTS_IN_ADD(port, val)
54 #define RTE_PORT_RING_READER_FRAG_STATS_PKTS_DROP_ADD(port, val)
59 (*frag_op
)(struct rte_mbuf
*pkt_in
,
60 struct rte_mbuf
**pkts_out
,
63 struct rte_mempool
*pool_direct
,
64 struct rte_mempool
*pool_indirect
);
66 struct rte_port_ring_reader_frag
{
67 struct rte_port_in_stats stats
;
69 /* Input parameters */
70 struct rte_ring
*ring
;
72 uint32_t metadata_size
;
73 struct rte_mempool
*pool_direct
;
74 struct rte_mempool
*pool_indirect
;
76 /* Internal buffers */
77 struct rte_mbuf
*pkts
[RTE_PORT_IN_BURST_SIZE_MAX
];
78 struct rte_mbuf
*frags
[RTE_PORT_FRAG_MAX_FRAGS_PER_PACKET
];
85 } __rte_cache_aligned
;
88 rte_port_ring_reader_frag_create(void *params
, int socket_id
, int is_ipv4
)
90 struct rte_port_ring_reader_frag_params
*conf
=
91 (struct rte_port_ring_reader_frag_params
*) params
;
92 struct rte_port_ring_reader_frag
*port
;
94 /* Check input parameters */
96 RTE_LOG(ERR
, PORT
, "%s: Parameter conf is NULL\n", __func__
);
99 if (conf
->ring
== NULL
) {
100 RTE_LOG(ERR
, PORT
, "%s: Parameter ring is NULL\n", __func__
);
103 if (conf
->mtu
== 0) {
104 RTE_LOG(ERR
, PORT
, "%s: Parameter mtu is invalid\n", __func__
);
107 if (conf
->pool_direct
== NULL
) {
108 RTE_LOG(ERR
, PORT
, "%s: Parameter pool_direct is NULL\n",
112 if (conf
->pool_indirect
== NULL
) {
113 RTE_LOG(ERR
, PORT
, "%s: Parameter pool_indirect is NULL\n",
118 /* Memory allocation */
119 port
= rte_zmalloc_socket("PORT", sizeof(*port
), RTE_CACHE_LINE_SIZE
,
122 RTE_LOG(ERR
, PORT
, "%s: port is NULL\n", __func__
);
127 port
->ring
= conf
->ring
;
128 port
->mtu
= conf
->mtu
;
129 port
->metadata_size
= conf
->metadata_size
;
130 port
->pool_direct
= conf
->pool_direct
;
131 port
->pool_indirect
= conf
->pool_indirect
;
138 port
->f_frag
= (is_ipv4
) ?
139 rte_ipv4_fragment_packet
: rte_ipv6_fragment_packet
;
145 rte_port_ring_reader_ipv4_frag_create(void *params
, int socket_id
)
147 return rte_port_ring_reader_frag_create(params
, socket_id
, 1);
151 rte_port_ring_reader_ipv6_frag_create(void *params
, int socket_id
)
153 return rte_port_ring_reader_frag_create(params
, socket_id
, 0);
157 rte_port_ring_reader_frag_rx(void *port
,
158 struct rte_mbuf
**pkts
,
161 struct rte_port_ring_reader_frag
*p
=
162 (struct rte_port_ring_reader_frag
*) port
;
167 /* Get packets from the "frag" buffer */
168 if (p
->n_frags
>= n_pkts
) {
169 memcpy(pkts
, &p
->frags
[p
->pos_frags
], n_pkts
* sizeof(void *));
170 p
->pos_frags
+= n_pkts
;
171 p
->n_frags
-= n_pkts
;
176 memcpy(pkts
, &p
->frags
[p
->pos_frags
], p
->n_frags
* sizeof(void *));
177 n_pkts_out
= p
->n_frags
;
180 /* Look to "pkts" buffer to get more packets */
182 struct rte_mbuf
*pkt
;
183 uint32_t n_pkts_to_provide
, i
;
186 /* If "pkts" buffer is empty, read packet burst from ring */
187 if (p
->n_pkts
== 0) {
188 p
->n_pkts
= rte_ring_sc_dequeue_burst(p
->ring
,
189 (void **) p
->pkts
, RTE_PORT_IN_BURST_SIZE_MAX
);
190 RTE_PORT_RING_READER_FRAG_STATS_PKTS_IN_ADD(p
, p
->n_pkts
);
196 /* Read next packet from "pkts" buffer */
197 pkt
= p
->pkts
[p
->pos_pkts
++];
200 /* If not jumbo, pass current packet to output */
201 if (pkt
->pkt_len
<= p
->mtu
) {
202 pkts
[n_pkts_out
++] = pkt
;
204 n_pkts_to_provide
= n_pkts
- n_pkts_out
;
205 if (n_pkts_to_provide
== 0)
211 /* Fragment current packet into the "frags" buffer */
215 RTE_PORT_FRAG_MAX_FRAGS_PER_PACKET
,
222 rte_pktmbuf_free(pkt
);
223 RTE_PORT_RING_READER_FRAG_STATS_PKTS_DROP_ADD(p
, 1);
227 p
->n_frags
= (uint32_t) status
;
230 /* Copy meta-data from input jumbo packet to its fragments */
231 for (i
= 0; i
< p
->n_frags
; i
++) {
233 RTE_MBUF_METADATA_UINT8_PTR(pkt
, sizeof(struct rte_mbuf
));
235 RTE_MBUF_METADATA_UINT8_PTR(p
->frags
[i
], sizeof(struct rte_mbuf
));
237 memcpy(dst
, src
, p
->metadata_size
);
240 /* Free input jumbo packet */
241 rte_pktmbuf_free(pkt
);
243 /* Get packets from "frag" buffer */
244 n_pkts_to_provide
= n_pkts
- n_pkts_out
;
245 if (p
->n_frags
>= n_pkts_to_provide
) {
246 memcpy(&pkts
[n_pkts_out
], p
->frags
,
247 n_pkts_to_provide
* sizeof(void *));
248 p
->n_frags
-= n_pkts_to_provide
;
249 p
->pos_frags
+= n_pkts_to_provide
;
254 memcpy(&pkts
[n_pkts_out
], p
->frags
,
255 p
->n_frags
* sizeof(void *));
256 n_pkts_out
+= p
->n_frags
;
262 rte_port_ring_reader_frag_free(void *port
)
265 RTE_LOG(ERR
, PORT
, "%s: Parameter port is NULL\n", __func__
);
275 rte_port_frag_reader_stats_read(void *port
,
276 struct rte_port_in_stats
*stats
, int clear
)
278 struct rte_port_ring_reader_frag
*p
=
279 (struct rte_port_ring_reader_frag
*) port
;
282 memcpy(stats
, &p
->stats
, sizeof(p
->stats
));
285 memset(&p
->stats
, 0, sizeof(p
->stats
));
291 * Summary of port operations
293 struct rte_port_in_ops rte_port_ring_reader_ipv4_frag_ops
= {
294 .f_create
= rte_port_ring_reader_ipv4_frag_create
,
295 .f_free
= rte_port_ring_reader_frag_free
,
296 .f_rx
= rte_port_ring_reader_frag_rx
,
297 .f_stats
= rte_port_frag_reader_stats_read
,
300 struct rte_port_in_ops rte_port_ring_reader_ipv6_frag_ops
= {
301 .f_create
= rte_port_ring_reader_ipv6_frag_create
,
302 .f_free
= rte_port_ring_reader_frag_free
,
303 .f_rx
= rte_port_ring_reader_frag_rx
,
304 .f_stats
= rte_port_frag_reader_stats_read
,