1*2d9fd380Sjfb8856606 /* SPDX-License-Identifier: BSD-3-Clause
2*2d9fd380Sjfb8856606 * Copyright (C) 2020 Marvell.
3*2d9fd380Sjfb8856606 */
4*2d9fd380Sjfb8856606
5*2d9fd380Sjfb8856606 #include <rte_debug.h>
6*2d9fd380Sjfb8856606 #include <rte_ether.h>
7*2d9fd380Sjfb8856606 #include <rte_ethdev.h>
8*2d9fd380Sjfb8856606 #include <rte_mbuf.h>
9*2d9fd380Sjfb8856606 #include <rte_graph.h>
10*2d9fd380Sjfb8856606 #include <rte_graph_worker.h>
11*2d9fd380Sjfb8856606
12*2d9fd380Sjfb8856606 #include "pkt_cls_priv.h"
13*2d9fd380Sjfb8856606 #include "node_private.h"
14*2d9fd380Sjfb8856606
15*2d9fd380Sjfb8856606 /* Next node for each ptype, default is '0' is "pkt_drop" */
16*2d9fd380Sjfb8856606 static const uint8_t p_nxt[256] __rte_cache_aligned = {
17*2d9fd380Sjfb8856606 [RTE_PTYPE_L3_IPV4] = PKT_CLS_NEXT_IP4_LOOKUP,
18*2d9fd380Sjfb8856606
19*2d9fd380Sjfb8856606 [RTE_PTYPE_L3_IPV4_EXT] = PKT_CLS_NEXT_IP4_LOOKUP,
20*2d9fd380Sjfb8856606
21*2d9fd380Sjfb8856606 [RTE_PTYPE_L3_IPV4_EXT_UNKNOWN] = PKT_CLS_NEXT_IP4_LOOKUP,
22*2d9fd380Sjfb8856606
23*2d9fd380Sjfb8856606 [RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L2_ETHER] =
24*2d9fd380Sjfb8856606 PKT_CLS_NEXT_IP4_LOOKUP,
25*2d9fd380Sjfb8856606
26*2d9fd380Sjfb8856606 [RTE_PTYPE_L3_IPV4_EXT | RTE_PTYPE_L2_ETHER] =
27*2d9fd380Sjfb8856606 PKT_CLS_NEXT_IP4_LOOKUP,
28*2d9fd380Sjfb8856606
29*2d9fd380Sjfb8856606 [RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_L2_ETHER] =
30*2d9fd380Sjfb8856606 PKT_CLS_NEXT_IP4_LOOKUP,
31*2d9fd380Sjfb8856606 };
32*2d9fd380Sjfb8856606
33*2d9fd380Sjfb8856606 static uint16_t
pkt_cls_node_process(struct rte_graph * graph,struct rte_node * node,void ** objs,uint16_t nb_objs)34*2d9fd380Sjfb8856606 pkt_cls_node_process(struct rte_graph *graph, struct rte_node *node,
35*2d9fd380Sjfb8856606 void **objs, uint16_t nb_objs)
36*2d9fd380Sjfb8856606 {
37*2d9fd380Sjfb8856606 struct rte_mbuf *mbuf0, *mbuf1, *mbuf2, *mbuf3, **pkts;
38*2d9fd380Sjfb8856606 uint8_t l0, l1, l2, l3, last_type;
39*2d9fd380Sjfb8856606 uint16_t next_index, n_left_from;
40*2d9fd380Sjfb8856606 uint16_t held = 0, last_spec = 0;
41*2d9fd380Sjfb8856606 struct pkt_cls_node_ctx *ctx;
42*2d9fd380Sjfb8856606 void **to_next, **from;
43*2d9fd380Sjfb8856606 uint32_t i;
44*2d9fd380Sjfb8856606
45*2d9fd380Sjfb8856606 pkts = (struct rte_mbuf **)objs;
46*2d9fd380Sjfb8856606 from = objs;
47*2d9fd380Sjfb8856606 n_left_from = nb_objs;
48*2d9fd380Sjfb8856606
49*2d9fd380Sjfb8856606 for (i = OBJS_PER_CLINE; i < RTE_GRAPH_BURST_SIZE; i += OBJS_PER_CLINE)
50*2d9fd380Sjfb8856606 rte_prefetch0(&objs[i]);
51*2d9fd380Sjfb8856606
52*2d9fd380Sjfb8856606 #if RTE_GRAPH_BURST_SIZE > 64
53*2d9fd380Sjfb8856606 for (i = 0; i < 4 && i < n_left_from; i++)
54*2d9fd380Sjfb8856606 rte_prefetch0(pkts[i]);
55*2d9fd380Sjfb8856606 #endif
56*2d9fd380Sjfb8856606
57*2d9fd380Sjfb8856606 ctx = (struct pkt_cls_node_ctx *)node->ctx;
58*2d9fd380Sjfb8856606 last_type = ctx->l2l3_type;
59*2d9fd380Sjfb8856606 next_index = p_nxt[last_type];
60*2d9fd380Sjfb8856606
61*2d9fd380Sjfb8856606 /* Get stream for the speculated next node */
62*2d9fd380Sjfb8856606 to_next = rte_node_next_stream_get(graph, node,
63*2d9fd380Sjfb8856606 next_index, nb_objs);
64*2d9fd380Sjfb8856606 while (n_left_from >= 4) {
65*2d9fd380Sjfb8856606 #if RTE_GRAPH_BURST_SIZE > 64
66*2d9fd380Sjfb8856606 if (likely(n_left_from > 7)) {
67*2d9fd380Sjfb8856606 rte_prefetch0(pkts[4]);
68*2d9fd380Sjfb8856606 rte_prefetch0(pkts[5]);
69*2d9fd380Sjfb8856606 rte_prefetch0(pkts[6]);
70*2d9fd380Sjfb8856606 rte_prefetch0(pkts[7]);
71*2d9fd380Sjfb8856606 }
72*2d9fd380Sjfb8856606 #endif
73*2d9fd380Sjfb8856606
74*2d9fd380Sjfb8856606 mbuf0 = pkts[0];
75*2d9fd380Sjfb8856606 mbuf1 = pkts[1];
76*2d9fd380Sjfb8856606 mbuf2 = pkts[2];
77*2d9fd380Sjfb8856606 mbuf3 = pkts[3];
78*2d9fd380Sjfb8856606 pkts += 4;
79*2d9fd380Sjfb8856606 n_left_from -= 4;
80*2d9fd380Sjfb8856606
81*2d9fd380Sjfb8856606 l0 = mbuf0->packet_type &
82*2d9fd380Sjfb8856606 (RTE_PTYPE_L2_MASK | RTE_PTYPE_L3_MASK);
83*2d9fd380Sjfb8856606 l1 = mbuf1->packet_type &
84*2d9fd380Sjfb8856606 (RTE_PTYPE_L2_MASK | RTE_PTYPE_L3_MASK);
85*2d9fd380Sjfb8856606 l2 = mbuf2->packet_type &
86*2d9fd380Sjfb8856606 (RTE_PTYPE_L2_MASK | RTE_PTYPE_L3_MASK);
87*2d9fd380Sjfb8856606 l3 = mbuf3->packet_type &
88*2d9fd380Sjfb8856606 (RTE_PTYPE_L2_MASK | RTE_PTYPE_L3_MASK);
89*2d9fd380Sjfb8856606
90*2d9fd380Sjfb8856606 /* Check if they are destined to same
91*2d9fd380Sjfb8856606 * next node based on l2l3 packet type.
92*2d9fd380Sjfb8856606 */
93*2d9fd380Sjfb8856606 uint8_t fix_spec = (last_type ^ l0) | (last_type ^ l1) |
94*2d9fd380Sjfb8856606 (last_type ^ l2) | (last_type ^ l3);
95*2d9fd380Sjfb8856606
96*2d9fd380Sjfb8856606 if (unlikely(fix_spec)) {
97*2d9fd380Sjfb8856606 /* Copy things successfully speculated till now */
98*2d9fd380Sjfb8856606 rte_memcpy(to_next, from,
99*2d9fd380Sjfb8856606 last_spec * sizeof(from[0]));
100*2d9fd380Sjfb8856606 from += last_spec;
101*2d9fd380Sjfb8856606 to_next += last_spec;
102*2d9fd380Sjfb8856606 held += last_spec;
103*2d9fd380Sjfb8856606 last_spec = 0;
104*2d9fd380Sjfb8856606
105*2d9fd380Sjfb8856606 /* l0 */
106*2d9fd380Sjfb8856606 if (p_nxt[l0] == next_index) {
107*2d9fd380Sjfb8856606 to_next[0] = from[0];
108*2d9fd380Sjfb8856606 to_next++;
109*2d9fd380Sjfb8856606 held++;
110*2d9fd380Sjfb8856606 } else {
111*2d9fd380Sjfb8856606 rte_node_enqueue_x1(graph, node,
112*2d9fd380Sjfb8856606 p_nxt[l0], from[0]);
113*2d9fd380Sjfb8856606 }
114*2d9fd380Sjfb8856606
115*2d9fd380Sjfb8856606 /* l1 */
116*2d9fd380Sjfb8856606 if (p_nxt[l1] == next_index) {
117*2d9fd380Sjfb8856606 to_next[0] = from[1];
118*2d9fd380Sjfb8856606 to_next++;
119*2d9fd380Sjfb8856606 held++;
120*2d9fd380Sjfb8856606 } else {
121*2d9fd380Sjfb8856606 rte_node_enqueue_x1(graph, node,
122*2d9fd380Sjfb8856606 p_nxt[l1], from[1]);
123*2d9fd380Sjfb8856606 }
124*2d9fd380Sjfb8856606
125*2d9fd380Sjfb8856606 /* l2 */
126*2d9fd380Sjfb8856606 if (p_nxt[l2] == next_index) {
127*2d9fd380Sjfb8856606 to_next[0] = from[2];
128*2d9fd380Sjfb8856606 to_next++;
129*2d9fd380Sjfb8856606 held++;
130*2d9fd380Sjfb8856606 } else {
131*2d9fd380Sjfb8856606 rte_node_enqueue_x1(graph, node,
132*2d9fd380Sjfb8856606 p_nxt[l2], from[2]);
133*2d9fd380Sjfb8856606 }
134*2d9fd380Sjfb8856606
135*2d9fd380Sjfb8856606 /* l3 */
136*2d9fd380Sjfb8856606 if (p_nxt[l3] == next_index) {
137*2d9fd380Sjfb8856606 to_next[0] = from[3];
138*2d9fd380Sjfb8856606 to_next++;
139*2d9fd380Sjfb8856606 held++;
140*2d9fd380Sjfb8856606 } else {
141*2d9fd380Sjfb8856606 rte_node_enqueue_x1(graph, node,
142*2d9fd380Sjfb8856606 p_nxt[l3], from[3]);
143*2d9fd380Sjfb8856606 }
144*2d9fd380Sjfb8856606
145*2d9fd380Sjfb8856606 /* Update speculated ptype */
146*2d9fd380Sjfb8856606 if ((last_type != l3) && (l2 == l3) &&
147*2d9fd380Sjfb8856606 (next_index != p_nxt[l3])) {
148*2d9fd380Sjfb8856606 /* Put the current stream for
149*2d9fd380Sjfb8856606 * speculated ltype.
150*2d9fd380Sjfb8856606 */
151*2d9fd380Sjfb8856606 rte_node_next_stream_put(graph, node,
152*2d9fd380Sjfb8856606 next_index, held);
153*2d9fd380Sjfb8856606
154*2d9fd380Sjfb8856606 held = 0;
155*2d9fd380Sjfb8856606
156*2d9fd380Sjfb8856606 /* Get next stream for new ltype */
157*2d9fd380Sjfb8856606 next_index = p_nxt[l3];
158*2d9fd380Sjfb8856606 last_type = l3;
159*2d9fd380Sjfb8856606 to_next = rte_node_next_stream_get(graph, node,
160*2d9fd380Sjfb8856606 next_index,
161*2d9fd380Sjfb8856606 nb_objs);
162*2d9fd380Sjfb8856606 } else if (next_index == p_nxt[l3]) {
163*2d9fd380Sjfb8856606 last_type = l3;
164*2d9fd380Sjfb8856606 }
165*2d9fd380Sjfb8856606
166*2d9fd380Sjfb8856606 from += 4;
167*2d9fd380Sjfb8856606 } else {
168*2d9fd380Sjfb8856606 last_spec += 4;
169*2d9fd380Sjfb8856606 }
170*2d9fd380Sjfb8856606 }
171*2d9fd380Sjfb8856606
172*2d9fd380Sjfb8856606 while (n_left_from > 0) {
173*2d9fd380Sjfb8856606 mbuf0 = pkts[0];
174*2d9fd380Sjfb8856606
175*2d9fd380Sjfb8856606 pkts += 1;
176*2d9fd380Sjfb8856606 n_left_from -= 1;
177*2d9fd380Sjfb8856606
178*2d9fd380Sjfb8856606 l0 = mbuf0->packet_type &
179*2d9fd380Sjfb8856606 (RTE_PTYPE_L2_MASK | RTE_PTYPE_L3_MASK);
180*2d9fd380Sjfb8856606 if (unlikely((l0 != last_type) &&
181*2d9fd380Sjfb8856606 (p_nxt[l0] != next_index))) {
182*2d9fd380Sjfb8856606 /* Copy things successfully speculated till now */
183*2d9fd380Sjfb8856606 rte_memcpy(to_next, from,
184*2d9fd380Sjfb8856606 last_spec * sizeof(from[0]));
185*2d9fd380Sjfb8856606 from += last_spec;
186*2d9fd380Sjfb8856606 to_next += last_spec;
187*2d9fd380Sjfb8856606 held += last_spec;
188*2d9fd380Sjfb8856606 last_spec = 0;
189*2d9fd380Sjfb8856606
190*2d9fd380Sjfb8856606 rte_node_enqueue_x1(graph, node,
191*2d9fd380Sjfb8856606 p_nxt[l0], from[0]);
192*2d9fd380Sjfb8856606 from += 1;
193*2d9fd380Sjfb8856606 } else {
194*2d9fd380Sjfb8856606 last_spec += 1;
195*2d9fd380Sjfb8856606 }
196*2d9fd380Sjfb8856606 }
197*2d9fd380Sjfb8856606
198*2d9fd380Sjfb8856606 /* !!! Home run !!! */
199*2d9fd380Sjfb8856606 if (likely(last_spec == nb_objs)) {
200*2d9fd380Sjfb8856606 rte_node_next_stream_move(graph, node, next_index);
201*2d9fd380Sjfb8856606 return nb_objs;
202*2d9fd380Sjfb8856606 }
203*2d9fd380Sjfb8856606
204*2d9fd380Sjfb8856606 held += last_spec;
205*2d9fd380Sjfb8856606 /* Copy things successfully speculated till now */
206*2d9fd380Sjfb8856606 rte_memcpy(to_next, from, last_spec * sizeof(from[0]));
207*2d9fd380Sjfb8856606 rte_node_next_stream_put(graph, node, next_index, held);
208*2d9fd380Sjfb8856606
209*2d9fd380Sjfb8856606 ctx->l2l3_type = last_type;
210*2d9fd380Sjfb8856606 return nb_objs;
211*2d9fd380Sjfb8856606 }
212*2d9fd380Sjfb8856606
213*2d9fd380Sjfb8856606 /* Packet Classification Node */
214*2d9fd380Sjfb8856606 struct rte_node_register pkt_cls_node = {
215*2d9fd380Sjfb8856606 .process = pkt_cls_node_process,
216*2d9fd380Sjfb8856606 .name = "pkt_cls",
217*2d9fd380Sjfb8856606
218*2d9fd380Sjfb8856606 .nb_edges = PKT_CLS_NEXT_MAX,
219*2d9fd380Sjfb8856606 .next_nodes = {
220*2d9fd380Sjfb8856606 /* Pkt drop node starts at '0' */
221*2d9fd380Sjfb8856606 [PKT_CLS_NEXT_PKT_DROP] = "pkt_drop",
222*2d9fd380Sjfb8856606 [PKT_CLS_NEXT_IP4_LOOKUP] = "ip4_lookup",
223*2d9fd380Sjfb8856606 },
224*2d9fd380Sjfb8856606 };
225*2d9fd380Sjfb8856606 RTE_NODE_REGISTER(pkt_cls_node);
226