Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(C) 2020 Marvell International Ltd.
3 : : */
4 : :
5 : : #ifndef __INCLUDE_IP4_LOOKUP_SSE_H__
6 : : #define __INCLUDE_IP4_LOOKUP_SSE_H__
7 : :
8 : : /* X86 SSE */
9 : : static uint16_t
10 : 0 : ip4_lookup_node_process_vec(struct rte_graph *graph, struct rte_node *node,
11 : : void **objs, uint16_t nb_objs)
12 : : {
13 : : struct rte_mbuf *mbuf0, *mbuf1, *mbuf2, *mbuf3, **pkts;
14 : 0 : struct rte_lpm *lpm = IP4_LOOKUP_NODE_LPM(node->ctx);
15 : 0 : const int dyn = IP4_LOOKUP_NODE_PRIV1_OFF(node->ctx);
16 : : rte_edge_t next0, next1, next2, next3, next_index;
17 : : struct rte_ipv4_hdr *ipv4_hdr;
18 : : uint32_t ip0, ip1, ip2, ip3;
19 : : void **to_next, **from;
20 : : uint16_t last_spec = 0;
21 : : uint16_t n_left_from;
22 : : uint16_t held = 0;
23 : : uint32_t drop_nh;
24 : : rte_xmm_t dst;
25 : : __m128i dip; /* SSE register */
26 : : int rc, i;
27 : :
28 : : /* Speculative next */
29 : : next_index = RTE_NODE_IP4_LOOKUP_NEXT_REWRITE;
30 : : /* Drop node */
31 : : drop_nh = ((uint32_t)RTE_NODE_IP4_LOOKUP_NEXT_PKT_DROP) << 16;
32 : :
33 : : pkts = (struct rte_mbuf **)objs;
34 : : from = objs;
35 : : n_left_from = nb_objs;
36 : :
37 [ # # ]: 0 : if (n_left_from >= 4) {
38 [ # # ]: 0 : for (i = 0; i < 4; i++)
39 : 0 : rte_prefetch0(rte_pktmbuf_mtod_offset(pkts[i], void *,
40 : : sizeof(struct rte_ether_hdr)));
41 : : }
42 : :
43 : : /* Get stream for the speculated next node */
44 : 0 : to_next = rte_node_next_stream_get(graph, node, next_index, nb_objs);
45 [ # # ]: 0 : while (n_left_from >= 4) {
46 : : /* Prefetch next-next mbufs */
47 [ # # ]: 0 : if (likely(n_left_from > 11)) {
48 : 0 : rte_prefetch0(pkts[8]);
49 : 0 : rte_prefetch0(pkts[9]);
50 : 0 : rte_prefetch0(pkts[10]);
51 : 0 : rte_prefetch0(pkts[11]);
52 : : }
53 : :
54 : : /* Prefetch next mbuf data */
55 [ # # ]: 0 : if (likely(n_left_from > 7)) {
56 : 0 : rte_prefetch0(rte_pktmbuf_mtod_offset(pkts[4], void *,
57 : : sizeof(struct rte_ether_hdr)));
58 : 0 : rte_prefetch0(rte_pktmbuf_mtod_offset(pkts[5], void *,
59 : : sizeof(struct rte_ether_hdr)));
60 : 0 : rte_prefetch0(rte_pktmbuf_mtod_offset(pkts[6], void *,
61 : : sizeof(struct rte_ether_hdr)));
62 : 0 : rte_prefetch0(rte_pktmbuf_mtod_offset(pkts[7], void *,
63 : : sizeof(struct rte_ether_hdr)));
64 : : }
65 : :
66 : 0 : mbuf0 = pkts[0];
67 : 0 : mbuf1 = pkts[1];
68 : 0 : mbuf2 = pkts[2];
69 : 0 : mbuf3 = pkts[3];
70 : :
71 : 0 : pkts += 4;
72 : 0 : n_left_from -= 4;
73 : :
74 : : /* Extract DIP of mbuf0 */
75 : 0 : ipv4_hdr = rte_pktmbuf_mtod_offset(mbuf0, struct rte_ipv4_hdr *,
76 : : sizeof(struct rte_ether_hdr));
77 : 0 : ip0 = ipv4_hdr->dst_addr;
78 : : /* Extract cksum, ttl as ipv4 hdr is in cache */
79 : 0 : node_mbuf_priv1(mbuf0, dyn)->cksum = ipv4_hdr->hdr_checksum;
80 : 0 : node_mbuf_priv1(mbuf0, dyn)->ttl = ipv4_hdr->time_to_live;
81 : :
82 : : /* Extract DIP of mbuf1 */
83 : 0 : ipv4_hdr = rte_pktmbuf_mtod_offset(mbuf1, struct rte_ipv4_hdr *,
84 : : sizeof(struct rte_ether_hdr));
85 : 0 : ip1 = ipv4_hdr->dst_addr;
86 : : /* Extract cksum, ttl as ipv4 hdr is in cache */
87 : 0 : node_mbuf_priv1(mbuf1, dyn)->cksum = ipv4_hdr->hdr_checksum;
88 : 0 : node_mbuf_priv1(mbuf1, dyn)->ttl = ipv4_hdr->time_to_live;
89 : :
90 : : /* Extract DIP of mbuf2 */
91 : 0 : ipv4_hdr = rte_pktmbuf_mtod_offset(mbuf2, struct rte_ipv4_hdr *,
92 : : sizeof(struct rte_ether_hdr));
93 : 0 : ip2 = ipv4_hdr->dst_addr;
94 : : /* Extract cksum, ttl as ipv4 hdr is in cache */
95 : 0 : node_mbuf_priv1(mbuf2, dyn)->cksum = ipv4_hdr->hdr_checksum;
96 : 0 : node_mbuf_priv1(mbuf2, dyn)->ttl = ipv4_hdr->time_to_live;
97 : :
98 : : /* Extract DIP of mbuf3 */
99 : 0 : ipv4_hdr = rte_pktmbuf_mtod_offset(mbuf3, struct rte_ipv4_hdr *,
100 : : sizeof(struct rte_ether_hdr));
101 : 0 : ip3 = ipv4_hdr->dst_addr;
102 : :
103 : : /* Prepare for lookup x4 */
104 : 0 : dip = _mm_set_epi32(ip3, ip2, ip1, ip0);
105 : :
106 : : /* Byte swap 4 IPV4 addresses. */
107 : : const __m128i bswap_mask = _mm_set_epi8(
108 : : 12, 13, 14, 15, 8, 9, 10, 11, 4, 5, 6, 7, 0, 1, 2, 3);
109 : : dip = _mm_shuffle_epi8(dip, bswap_mask);
110 : :
111 : : /* Extract cksum, ttl as ipv4 hdr is in cache */
112 : 0 : node_mbuf_priv1(mbuf3, dyn)->cksum = ipv4_hdr->hdr_checksum;
113 : 0 : node_mbuf_priv1(mbuf3, dyn)->ttl = ipv4_hdr->time_to_live;
114 : :
115 : : /* Perform LPM lookup to get NH and next node */
116 : 0 : rte_lpm_lookupx4(lpm, dip, dst.u32, drop_nh);
117 : :
118 [ # # ]: 0 : NODE_INCREMENT_XSTAT_ID(node, 0, dst.u16[1] == (drop_nh >> 16), 1);
119 [ # # ]: 0 : NODE_INCREMENT_XSTAT_ID(node, 0, dst.u16[3] == (drop_nh >> 16), 1);
120 [ # # ]: 0 : NODE_INCREMENT_XSTAT_ID(node, 0, dst.u16[5] == (drop_nh >> 16), 1);
121 [ # # ]: 0 : NODE_INCREMENT_XSTAT_ID(node, 0, dst.u16[7] == (drop_nh >> 16), 1);
122 : :
123 : : /* Extract next node id and NH */
124 : 0 : node_mbuf_priv1(mbuf0, dyn)->nh = dst.u32[0] & 0xFFFF;
125 : 0 : next0 = (dst.u32[0] >> 16);
126 : :
127 : 0 : node_mbuf_priv1(mbuf1, dyn)->nh = dst.u32[1] & 0xFFFF;
128 : 0 : next1 = (dst.u32[1] >> 16);
129 : :
130 : 0 : node_mbuf_priv1(mbuf2, dyn)->nh = dst.u32[2] & 0xFFFF;
131 : 0 : next2 = (dst.u32[2] >> 16);
132 : :
133 : 0 : node_mbuf_priv1(mbuf3, dyn)->nh = dst.u32[3] & 0xFFFF;
134 : 0 : next3 = (dst.u32[3] >> 16);
135 : :
136 : : /* Enqueue four to next node */
137 : 0 : rte_edge_t fix_spec =
138 : : (next_index ^ next0) | (next_index ^ next1) |
139 : : (next_index ^ next2) | (next_index ^ next3);
140 : :
141 [ # # ]: 0 : if (unlikely(fix_spec)) {
142 : : /* Copy things successfully speculated till now */
143 [ # # ]: 0 : rte_memcpy(to_next, from, last_spec * sizeof(from[0]));
144 : 0 : from += last_spec;
145 : 0 : to_next += last_spec;
146 : 0 : held += last_spec;
147 : : last_spec = 0;
148 : :
149 : : /* Next0 */
150 [ # # ]: 0 : if (next_index == next0) {
151 : 0 : to_next[0] = from[0];
152 : 0 : to_next++;
153 : 0 : held++;
154 : : } else {
155 : 0 : rte_node_enqueue_x1(graph, node, next0,
156 : : from[0]);
157 : : }
158 : :
159 : : /* Next1 */
160 [ # # ]: 0 : if (next_index == next1) {
161 : 0 : to_next[0] = from[1];
162 : 0 : to_next++;
163 : 0 : held++;
164 : : } else {
165 : 0 : rte_node_enqueue_x1(graph, node, next1,
166 : : from[1]);
167 : : }
168 : :
169 : : /* Next2 */
170 [ # # ]: 0 : if (next_index == next2) {
171 : 0 : to_next[0] = from[2];
172 : 0 : to_next++;
173 : 0 : held++;
174 : : } else {
175 : 0 : rte_node_enqueue_x1(graph, node, next2,
176 : : from[2]);
177 : : }
178 : :
179 : : /* Next3 */
180 [ # # ]: 0 : if (next_index == next3) {
181 : 0 : to_next[0] = from[3];
182 : 0 : to_next++;
183 : 0 : held++;
184 : : } else {
185 : 0 : rte_node_enqueue_x1(graph, node, next3,
186 : : from[3]);
187 : : }
188 : :
189 : 0 : from += 4;
190 : :
191 : : } else {
192 : 0 : last_spec += 4;
193 : : }
194 : : }
195 : :
196 [ # # ]: 0 : while (n_left_from > 0) {
197 : : uint32_t next_hop;
198 : :
199 : 0 : mbuf0 = pkts[0];
200 : :
201 : 0 : pkts += 1;
202 : 0 : n_left_from -= 1;
203 : :
204 : : /* Extract DIP of mbuf0 */
205 : 0 : ipv4_hdr = rte_pktmbuf_mtod_offset(mbuf0, struct rte_ipv4_hdr *,
206 : : sizeof(struct rte_ether_hdr));
207 : : /* Extract cksum, ttl as ipv4 hdr is in cache */
208 [ # # ]: 0 : node_mbuf_priv1(mbuf0, dyn)->cksum = ipv4_hdr->hdr_checksum;
209 : 0 : node_mbuf_priv1(mbuf0, dyn)->ttl = ipv4_hdr->time_to_live;
210 : :
211 [ # # ]: 0 : rc = rte_lpm_lookup(lpm, rte_be_to_cpu_32(ipv4_hdr->dst_addr),
212 : : &next_hop);
213 : : next_hop = (rc == 0) ? next_hop : drop_nh;
214 [ # # ]: 0 : NODE_INCREMENT_XSTAT_ID(node, 0, rc != 0, 1);
215 : :
216 : 0 : node_mbuf_priv1(mbuf0, dyn)->nh = next_hop & 0xFFFF;
217 : 0 : next0 = (next_hop >> 16);
218 : :
219 [ # # ]: 0 : if (unlikely(next_index ^ next0)) {
220 : : /* Copy things successfully speculated till now */
221 [ # # ]: 0 : rte_memcpy(to_next, from, last_spec * sizeof(from[0]));
222 : 0 : from += last_spec;
223 : 0 : to_next += last_spec;
224 : 0 : held += last_spec;
225 : : last_spec = 0;
226 : :
227 : 0 : rte_node_enqueue_x1(graph, node, next0, from[0]);
228 : 0 : from += 1;
229 : : } else {
230 : 0 : last_spec += 1;
231 : : }
232 : : }
233 : :
234 : : /* !!! Home run !!! */
235 [ # # ]: 0 : if (likely(last_spec == nb_objs)) {
236 : 0 : rte_node_next_stream_move(graph, node, next_index);
237 : 0 : return nb_objs;
238 : : }
239 : :
240 : 0 : held += last_spec;
241 : : /* Copy things successfully speculated till now */
242 [ # # ]: 0 : rte_memcpy(to_next, from, last_spec * sizeof(from[0]));
243 : : rte_node_next_stream_put(graph, node, next_index, held);
244 : :
245 : : return nb_objs;
246 : : }
247 : :
248 : : #endif /* __INCLUDE_IP4_LOOKUP_SSE_H__ */
|