xref: /f-stack/dpdk/lib/librte_node/pkt_cls.c (revision 2d9fd380)
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