blob: 13fc12ce6ea72620d14157b9523c1f55d4d0e31d [file] [log] [blame]
Damjan Marion0247b462016-06-08 01:37:11 +02001/*
Florin Coras943a4b02021-10-27 15:17:47 -07002 * Copyright (c) 2021 Cisco and/or its affiliates.
Damjan Marion0247b462016-06-08 01:37:11 +02003 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
Damjan Marion0247b462016-06-08 01:37:11 +020016#include <vlib/vlib.h>
17#include <vnet/ethernet/ethernet.h>
Florin Coras943a4b02021-10-27 15:17:47 -070018#include <vnet/hash/hash.h>
Damjan Marion0247b462016-06-08 01:37:11 +020019#include <vnet/ip/ip4_packet.h>
20#include <vnet/ip/ip6_packet.h>
Neale Ranns0bfe5d82016-08-25 15:29:12 +010021#include <vnet/mpls/packet.h>
Florin Coras943a4b02021-10-27 15:17:47 -070022#include <vppinfra/crc32.h>
Damjan Marion0247b462016-06-08 01:37:11 +020023
Dave Barachba868bb2016-08-08 09:51:21 -040024static inline u64
25ipv4_get_key (ip4_header_t * ip)
Damjan Marion0247b462016-06-08 01:37:11 +020026{
Dave Barachba868bb2016-08-08 09:51:21 -040027 u64 hash_key;
Damjan Marion0247b462016-06-08 01:37:11 +020028
Dave Barachba868bb2016-08-08 09:51:21 -040029 hash_key = *((u64 *) (&ip->address_pair)) ^ ip->protocol;
Damjan Marion0247b462016-06-08 01:37:11 +020030
Dave Barachba868bb2016-08-08 09:51:21 -040031 return hash_key;
Damjan Marion0247b462016-06-08 01:37:11 +020032}
33
Dave Barachba868bb2016-08-08 09:51:21 -040034static inline u64
35ipv6_get_key (ip6_header_t * ip)
Damjan Marion0247b462016-06-08 01:37:11 +020036{
Dave Barachba868bb2016-08-08 09:51:21 -040037 u64 hash_key;
Damjan Marion0247b462016-06-08 01:37:11 +020038
Dave Barachba868bb2016-08-08 09:51:21 -040039 hash_key = ip->src_address.as_u64[0] ^
40 rotate_left (ip->src_address.as_u64[1], 13) ^
41 rotate_left (ip->dst_address.as_u64[0], 26) ^
42 rotate_left (ip->dst_address.as_u64[1], 39) ^ ip->protocol;
Damjan Marion0247b462016-06-08 01:37:11 +020043
Dave Barachba868bb2016-08-08 09:51:21 -040044 return hash_key;
Damjan Marion0247b462016-06-08 01:37:11 +020045}
46
47#define MPLS_BOTTOM_OF_STACK_BIT_MASK 0x00000100U
48#define MPLS_LABEL_MASK 0xFFFFF000U
49
Dave Barachba868bb2016-08-08 09:51:21 -040050static inline u64
51mpls_get_key (mpls_unicast_header_t * m)
Damjan Marion0247b462016-06-08 01:37:11 +020052{
Dave Barachba868bb2016-08-08 09:51:21 -040053 u64 hash_key;
54 u8 ip_ver;
Damjan Marion0247b462016-06-08 01:37:11 +020055
56
Dave Barachba868bb2016-08-08 09:51:21 -040057 /* find the bottom of the MPLS label stack. */
58 if (PREDICT_TRUE (m->label_exp_s_ttl &
59 clib_net_to_host_u32 (MPLS_BOTTOM_OF_STACK_BIT_MASK)))
60 {
61 goto bottom_lbl_found;
62 }
63 m++;
Damjan Marion0247b462016-06-08 01:37:11 +020064
Dave Barachba868bb2016-08-08 09:51:21 -040065 if (PREDICT_TRUE (m->label_exp_s_ttl &
66 clib_net_to_host_u32 (MPLS_BOTTOM_OF_STACK_BIT_MASK)))
67 {
68 goto bottom_lbl_found;
69 }
70 m++;
Damjan Marion0247b462016-06-08 01:37:11 +020071
Dave Barachba868bb2016-08-08 09:51:21 -040072 if (m->label_exp_s_ttl &
73 clib_net_to_host_u32 (MPLS_BOTTOM_OF_STACK_BIT_MASK))
74 {
75 goto bottom_lbl_found;
76 }
77 m++;
Damjan Marion0247b462016-06-08 01:37:11 +020078
Dave Barachba868bb2016-08-08 09:51:21 -040079 if (m->label_exp_s_ttl &
80 clib_net_to_host_u32 (MPLS_BOTTOM_OF_STACK_BIT_MASK))
81 {
82 goto bottom_lbl_found;
83 }
84 m++;
Damjan Marion0247b462016-06-08 01:37:11 +020085
Dave Barachba868bb2016-08-08 09:51:21 -040086 if (m->label_exp_s_ttl &
87 clib_net_to_host_u32 (MPLS_BOTTOM_OF_STACK_BIT_MASK))
88 {
89 goto bottom_lbl_found;
90 }
Damjan Marion0247b462016-06-08 01:37:11 +020091
Dave Barachba868bb2016-08-08 09:51:21 -040092 /* the bottom label was not found - use the last label */
93 hash_key = m->label_exp_s_ttl & clib_net_to_host_u32 (MPLS_LABEL_MASK);
Damjan Marion0247b462016-06-08 01:37:11 +020094
Dave Barachba868bb2016-08-08 09:51:21 -040095 return hash_key;
Damjan Marion0247b462016-06-08 01:37:11 +020096
97bottom_lbl_found:
Dave Barachba868bb2016-08-08 09:51:21 -040098 m++;
99 ip_ver = (*((u8 *) m) >> 4);
Damjan Marion0247b462016-06-08 01:37:11 +0200100
Dave Barachba868bb2016-08-08 09:51:21 -0400101 /* find out if it is IPV4 or IPV6 header */
102 if (PREDICT_TRUE (ip_ver == 4))
103 {
104 hash_key = ipv4_get_key ((ip4_header_t *) m);
105 }
106 else if (PREDICT_TRUE (ip_ver == 6))
107 {
108 hash_key = ipv6_get_key ((ip6_header_t *) m);
109 }
110 else
111 {
112 /* use the bottom label */
113 hash_key =
114 (m - 1)->label_exp_s_ttl & clib_net_to_host_u32 (MPLS_LABEL_MASK);
115 }
Damjan Marion0247b462016-06-08 01:37:11 +0200116
Dave Barachba868bb2016-08-08 09:51:21 -0400117 return hash_key;
Damjan Marion0247b462016-06-08 01:37:11 +0200118
119}
120
Gabriel Gannec0a36c02016-11-16 16:57:00 +0100121static inline u64
122eth_get_sym_key (ethernet_header_t * h0)
123{
124 u64 hash_key;
125
126 if (PREDICT_TRUE (h0->type) == clib_host_to_net_u16 (ETHERNET_TYPE_IP4))
127 {
128 ip4_header_t *ip = (ip4_header_t *) (h0 + 1);
129 hash_key =
130 (u64) (ip->src_address.as_u32 ^
131 ip->dst_address.as_u32 ^ ip->protocol);
132 }
133 else if (h0->type == clib_host_to_net_u16 (ETHERNET_TYPE_IP6))
134 {
135 ip6_header_t *ip = (ip6_header_t *) (h0 + 1);
136 hash_key = (u64) (ip->src_address.as_u64[0] ^
137 ip->src_address.as_u64[1] ^
138 ip->dst_address.as_u64[0] ^
139 ip->dst_address.as_u64[1] ^ ip->protocol);
140 }
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800141 else if (h0->type == clib_host_to_net_u16 (ETHERNET_TYPE_MPLS))
Gabriel Gannec0a36c02016-11-16 16:57:00 +0100142 {
143 hash_key = mpls_get_key ((mpls_unicast_header_t *) (h0 + 1));
144 }
145 else
146 if (PREDICT_FALSE
147 ((h0->type == clib_host_to_net_u16 (ETHERNET_TYPE_VLAN))
148 || (h0->type == clib_host_to_net_u16 (ETHERNET_TYPE_DOT1AD))))
149 {
150 ethernet_vlan_header_t *outer = (ethernet_vlan_header_t *) (h0 + 1);
151
152 outer = (outer->type == clib_host_to_net_u16 (ETHERNET_TYPE_VLAN)) ?
153 outer + 1 : outer;
154 if (PREDICT_TRUE (outer->type) ==
155 clib_host_to_net_u16 (ETHERNET_TYPE_IP4))
156 {
157 ip4_header_t *ip = (ip4_header_t *) (outer + 1);
158 hash_key =
159 (u64) (ip->src_address.as_u32 ^
160 ip->dst_address.as_u32 ^ ip->protocol);
161 }
162 else if (outer->type == clib_host_to_net_u16 (ETHERNET_TYPE_IP6))
163 {
164 ip6_header_t *ip = (ip6_header_t *) (outer + 1);
165 hash_key =
166 (u64) (ip->src_address.as_u64[0] ^ ip->src_address.as_u64[1] ^
167 ip->dst_address.as_u64[0] ^
168 ip->dst_address.as_u64[1] ^ ip->protocol);
169 }
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800170 else if (outer->type == clib_host_to_net_u16 (ETHERNET_TYPE_MPLS))
Gabriel Gannec0a36c02016-11-16 16:57:00 +0100171 {
172 hash_key = mpls_get_key ((mpls_unicast_header_t *) (outer + 1));
173 }
174 else
175 {
176 hash_key = outer->type;
177 }
178 }
179 else
180 {
181 hash_key = 0;
182 }
183
184 return hash_key;
185}
Damjan Marion0247b462016-06-08 01:37:11 +0200186
187static inline u64
Dave Barachba868bb2016-08-08 09:51:21 -0400188eth_get_key (ethernet_header_t * h0)
Damjan Marion0247b462016-06-08 01:37:11 +0200189{
Dave Barachba868bb2016-08-08 09:51:21 -0400190 u64 hash_key;
Damjan Marion0247b462016-06-08 01:37:11 +0200191
Dave Barachba868bb2016-08-08 09:51:21 -0400192 if (PREDICT_TRUE (h0->type) == clib_host_to_net_u16 (ETHERNET_TYPE_IP4))
193 {
194 hash_key = ipv4_get_key ((ip4_header_t *) (h0 + 1));
195 }
196 else if (h0->type == clib_host_to_net_u16 (ETHERNET_TYPE_IP6))
197 {
198 hash_key = ipv6_get_key ((ip6_header_t *) (h0 + 1));
199 }
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800200 else if (h0->type == clib_host_to_net_u16 (ETHERNET_TYPE_MPLS))
Dave Barachba868bb2016-08-08 09:51:21 -0400201 {
202 hash_key = mpls_get_key ((mpls_unicast_header_t *) (h0 + 1));
203 }
204 else if ((h0->type == clib_host_to_net_u16 (ETHERNET_TYPE_VLAN)) ||
205 (h0->type == clib_host_to_net_u16 (ETHERNET_TYPE_DOT1AD)))
206 {
207 ethernet_vlan_header_t *outer = (ethernet_vlan_header_t *) (h0 + 1);
Damjan Marion0247b462016-06-08 01:37:11 +0200208
Dave Barachba868bb2016-08-08 09:51:21 -0400209 outer = (outer->type == clib_host_to_net_u16 (ETHERNET_TYPE_VLAN)) ?
210 outer + 1 : outer;
211 if (PREDICT_TRUE (outer->type) ==
212 clib_host_to_net_u16 (ETHERNET_TYPE_IP4))
213 {
214 hash_key = ipv4_get_key ((ip4_header_t *) (outer + 1));
215 }
216 else if (outer->type == clib_host_to_net_u16 (ETHERNET_TYPE_IP6))
217 {
218 hash_key = ipv6_get_key ((ip6_header_t *) (outer + 1));
219 }
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800220 else if (outer->type == clib_host_to_net_u16 (ETHERNET_TYPE_MPLS))
Dave Barachba868bb2016-08-08 09:51:21 -0400221 {
222 hash_key = mpls_get_key ((mpls_unicast_header_t *) (outer + 1));
223 }
224 else
225 {
226 hash_key = outer->type;
227 }
228 }
229 else
230 {
231 hash_key = 0;
232 }
Damjan Marion0247b462016-06-08 01:37:11 +0200233
Dave Barachba868bb2016-08-08 09:51:21 -0400234 return hash_key;
Damjan Marion0247b462016-06-08 01:37:11 +0200235}
236
Florin Coras943a4b02021-10-27 15:17:47 -0700237void
238handoff_eth_crc32c_func (void **p, u32 *hash, u32 n_packets)
239{
240 u32 n_left_from = n_packets;
241
242 while (n_left_from >= 8)
243 {
244 u64 key[4] = {};
245
246 clib_prefetch_load (p[4]);
247 clib_prefetch_load (p[5]);
248 clib_prefetch_load (p[6]);
249 clib_prefetch_load (p[7]);
250
251 key[0] = eth_get_key ((ethernet_header_t *) p[0]);
252 key[1] = eth_get_key ((ethernet_header_t *) p[1]);
253 key[2] = eth_get_key ((ethernet_header_t *) p[2]);
254 key[3] = eth_get_key ((ethernet_header_t *) p[3]);
255
256 hash[0] = clib_crc32c ((u8 *) &key[0], sizeof (key[0]));
257 hash[1] = clib_crc32c ((u8 *) &key[1], sizeof (key[1]));
258 hash[2] = clib_crc32c ((u8 *) &key[2], sizeof (key[2]));
259 hash[3] = clib_crc32c ((u8 *) &key[3], sizeof (key[3]));
260
261 hash += 4;
262 n_left_from -= 4;
263 p += 4;
264 }
265
266 while (n_left_from > 0)
267 {
268 u64 key;
269
270 key = eth_get_key ((ethernet_header_t *) p[0]);
271 hash[0] = clib_crc32c ((u8 *) &key, sizeof (key));
272
273 hash += 1;
274 n_left_from -= 1;
275 p += 1;
276 }
277}
278
279VNET_REGISTER_HASH_FUNCTION (handoff_eth_crc32c, static) = {
280 .name = "handoff-eth-crc32c",
281 .description = "Ethernet/IPv4/IPv6/MPLS headers",
282 .priority = 2,
283 .function[VNET_HASH_FN_TYPE_ETHERNET] = handoff_eth_crc32c_func,
284};
285
286void
287handoff_eth_sym_crc32c_func (void **p, u32 *hash, u32 n_packets)
288{
289 u32 n_left_from = n_packets;
290
291 while (n_left_from >= 8)
292 {
293 u64 key[4] = {};
294
295 clib_prefetch_load (p[4]);
296 clib_prefetch_load (p[5]);
297 clib_prefetch_load (p[6]);
298 clib_prefetch_load (p[7]);
299
300 key[0] = eth_get_sym_key ((ethernet_header_t *) p[0]);
301 key[1] = eth_get_sym_key ((ethernet_header_t *) p[1]);
302 key[2] = eth_get_sym_key ((ethernet_header_t *) p[2]);
303 key[3] = eth_get_sym_key ((ethernet_header_t *) p[3]);
304
305 hash[0] = clib_crc32c ((u8 *) &key[0], sizeof (key[0]));
306 hash[1] = clib_crc32c ((u8 *) &key[1], sizeof (key[1]));
307 hash[2] = clib_crc32c ((u8 *) &key[2], sizeof (key[2]));
308 hash[3] = clib_crc32c ((u8 *) &key[3], sizeof (key[3]));
309
310 hash += 4;
311 n_left_from -= 4;
312 p += 4;
313 }
314
315 while (n_left_from > 0)
316 {
317 u64 key;
318
319 key = eth_get_sym_key ((ethernet_header_t *) p[0]);
320 hash[0] = clib_crc32c ((u8 *) &key, sizeof (key));
321
322 hash += 1;
323 n_left_from -= 1;
324 p += 1;
325 }
326}
327
328VNET_REGISTER_HASH_FUNCTION (handoff_eth_sym_crc32c, static) = {
329 .name = "handoff-eth-sym-crc32c",
330 .description = "Ethernet/IPv4/IPv6/MPLS headers Symmetric",
331 .priority = 1,
332 .function[VNET_HASH_FN_TYPE_ETHERNET] = handoff_eth_sym_crc32c_func,
333};
Dave Barachba868bb2016-08-08 09:51:21 -0400334
335/*
336 * fd.io coding-style-patch-verification: ON
337 *
338 * Local Variables:
339 * eval: (c-set-style "gnu")
340 * End:
341 */