2 * Copyright (c) 2021 Cisco and/or its affiliates.
3 * 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:
7 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 #include <vlib/vlib.h>
17 #include <vnet/ethernet/ethernet.h>
18 #include <vnet/hash/hash.h>
19 #include <vnet/ip/ip4_packet.h>
20 #include <vnet/ip/ip6_packet.h>
21 #include <vnet/mpls/packet.h>
22 #include <vppinfra/crc32.h>
23 #include <vppinfra/xxhash.h>
28 #ifdef clib_crc32c_uses_intrinsics
29 return clib_crc32c ((u8 *) &key, sizeof (key));
31 return clib_xxhash (key);
36 ipv4_get_key (ip4_header_t * ip)
40 hash_key = *((u64 *) (&ip->address_pair)) ^ ip->protocol;
46 ipv6_get_key (ip6_header_t * ip)
50 hash_key = ip->src_address.as_u64[0] ^
51 rotate_left (ip->src_address.as_u64[1], 13) ^
52 rotate_left (ip->dst_address.as_u64[0], 26) ^
53 rotate_left (ip->dst_address.as_u64[1], 39) ^ ip->protocol;
58 #define MPLS_BOTTOM_OF_STACK_BIT_MASK 0x00000100U
59 #define MPLS_LABEL_MASK 0xFFFFF000U
62 mpls_get_key (mpls_unicast_header_t * m)
68 /* find the bottom of the MPLS label stack. */
69 if (PREDICT_TRUE (m->label_exp_s_ttl &
70 clib_net_to_host_u32 (MPLS_BOTTOM_OF_STACK_BIT_MASK)))
72 goto bottom_lbl_found;
76 if (PREDICT_TRUE (m->label_exp_s_ttl &
77 clib_net_to_host_u32 (MPLS_BOTTOM_OF_STACK_BIT_MASK)))
79 goto bottom_lbl_found;
83 if (m->label_exp_s_ttl &
84 clib_net_to_host_u32 (MPLS_BOTTOM_OF_STACK_BIT_MASK))
86 goto bottom_lbl_found;
90 if (m->label_exp_s_ttl &
91 clib_net_to_host_u32 (MPLS_BOTTOM_OF_STACK_BIT_MASK))
93 goto bottom_lbl_found;
97 if (m->label_exp_s_ttl &
98 clib_net_to_host_u32 (MPLS_BOTTOM_OF_STACK_BIT_MASK))
100 goto bottom_lbl_found;
103 /* the bottom label was not found - use the last label */
104 hash_key = m->label_exp_s_ttl & clib_net_to_host_u32 (MPLS_LABEL_MASK);
110 ip_ver = (*((u8 *) m) >> 4);
112 /* find out if it is IPV4 or IPV6 header */
113 if (PREDICT_TRUE (ip_ver == 4))
115 hash_key = ipv4_get_key ((ip4_header_t *) m);
117 else if (PREDICT_TRUE (ip_ver == 6))
119 hash_key = ipv6_get_key ((ip6_header_t *) m);
123 /* use the bottom label */
125 (m - 1)->label_exp_s_ttl & clib_net_to_host_u32 (MPLS_LABEL_MASK);
133 eth_get_sym_key (ethernet_header_t * h0)
137 if (PREDICT_TRUE (h0->type) == clib_host_to_net_u16 (ETHERNET_TYPE_IP4))
139 ip4_header_t *ip = (ip4_header_t *) (h0 + 1);
141 (u64) (ip->src_address.as_u32 ^
142 ip->dst_address.as_u32 ^ ip->protocol);
144 else if (h0->type == clib_host_to_net_u16 (ETHERNET_TYPE_IP6))
146 ip6_header_t *ip = (ip6_header_t *) (h0 + 1);
147 hash_key = (u64) (ip->src_address.as_u64[0] ^
148 ip->src_address.as_u64[1] ^
149 ip->dst_address.as_u64[0] ^
150 ip->dst_address.as_u64[1] ^ ip->protocol);
152 else if (h0->type == clib_host_to_net_u16 (ETHERNET_TYPE_MPLS))
154 hash_key = mpls_get_key ((mpls_unicast_header_t *) (h0 + 1));
158 ((h0->type == clib_host_to_net_u16 (ETHERNET_TYPE_VLAN))
159 || (h0->type == clib_host_to_net_u16 (ETHERNET_TYPE_DOT1AD))))
161 ethernet_vlan_header_t *outer = (ethernet_vlan_header_t *) (h0 + 1);
163 outer = (outer->type == clib_host_to_net_u16 (ETHERNET_TYPE_VLAN)) ?
165 if (PREDICT_TRUE (outer->type) ==
166 clib_host_to_net_u16 (ETHERNET_TYPE_IP4))
168 ip4_header_t *ip = (ip4_header_t *) (outer + 1);
170 (u64) (ip->src_address.as_u32 ^
171 ip->dst_address.as_u32 ^ ip->protocol);
173 else if (outer->type == clib_host_to_net_u16 (ETHERNET_TYPE_IP6))
175 ip6_header_t *ip = (ip6_header_t *) (outer + 1);
177 (u64) (ip->src_address.as_u64[0] ^ ip->src_address.as_u64[1] ^
178 ip->dst_address.as_u64[0] ^
179 ip->dst_address.as_u64[1] ^ ip->protocol);
181 else if (outer->type == clib_host_to_net_u16 (ETHERNET_TYPE_MPLS))
183 hash_key = mpls_get_key ((mpls_unicast_header_t *) (outer + 1));
187 hash_key = outer->type;
199 eth_get_key (ethernet_header_t * h0)
203 if (PREDICT_TRUE (h0->type) == clib_host_to_net_u16 (ETHERNET_TYPE_IP4))
205 hash_key = ipv4_get_key ((ip4_header_t *) (h0 + 1));
207 else if (h0->type == clib_host_to_net_u16 (ETHERNET_TYPE_IP6))
209 hash_key = ipv6_get_key ((ip6_header_t *) (h0 + 1));
211 else if (h0->type == clib_host_to_net_u16 (ETHERNET_TYPE_MPLS))
213 hash_key = mpls_get_key ((mpls_unicast_header_t *) (h0 + 1));
215 else if ((h0->type == clib_host_to_net_u16 (ETHERNET_TYPE_VLAN)) ||
216 (h0->type == clib_host_to_net_u16 (ETHERNET_TYPE_DOT1AD)))
218 ethernet_vlan_header_t *outer = (ethernet_vlan_header_t *) (h0 + 1);
220 outer = (outer->type == clib_host_to_net_u16 (ETHERNET_TYPE_VLAN)) ?
222 if (PREDICT_TRUE (outer->type) ==
223 clib_host_to_net_u16 (ETHERNET_TYPE_IP4))
225 hash_key = ipv4_get_key ((ip4_header_t *) (outer + 1));
227 else if (outer->type == clib_host_to_net_u16 (ETHERNET_TYPE_IP6))
229 hash_key = ipv6_get_key ((ip6_header_t *) (outer + 1));
231 else if (outer->type == clib_host_to_net_u16 (ETHERNET_TYPE_MPLS))
233 hash_key = mpls_get_key ((mpls_unicast_header_t *) (outer + 1));
237 hash_key = outer->type;
249 handoff_eth_func (void **p, u32 *hash, u32 n_packets)
251 u32 n_left_from = n_packets;
253 while (n_left_from >= 8)
257 clib_prefetch_load (p[4]);
258 clib_prefetch_load (p[5]);
259 clib_prefetch_load (p[6]);
260 clib_prefetch_load (p[7]);
262 key[0] = eth_get_key ((ethernet_header_t *) p[0]);
263 key[1] = eth_get_key ((ethernet_header_t *) p[1]);
264 key[2] = eth_get_key ((ethernet_header_t *) p[2]);
265 key[3] = eth_get_key ((ethernet_header_t *) p[3]);
267 hash[0] = ho_hash (key[0]);
268 hash[1] = ho_hash (key[1]);
269 hash[2] = ho_hash (key[2]);
270 hash[3] = ho_hash (key[3]);
277 while (n_left_from > 0)
281 key = eth_get_key ((ethernet_header_t *) p[0]);
282 hash[0] = ho_hash (key);
290 VNET_REGISTER_HASH_FUNCTION (handoff_eth, static) = {
291 .name = "handoff-eth",
292 .description = "Ethernet/IPv4/IPv6/MPLS headers",
294 .function[VNET_HASH_FN_TYPE_ETHERNET] = handoff_eth_func,
298 handoff_eth_sym_func (void **p, u32 *hash, u32 n_packets)
300 u32 n_left_from = n_packets;
302 while (n_left_from >= 8)
306 clib_prefetch_load (p[4]);
307 clib_prefetch_load (p[5]);
308 clib_prefetch_load (p[6]);
309 clib_prefetch_load (p[7]);
311 key[0] = eth_get_sym_key ((ethernet_header_t *) p[0]);
312 key[1] = eth_get_sym_key ((ethernet_header_t *) p[1]);
313 key[2] = eth_get_sym_key ((ethernet_header_t *) p[2]);
314 key[3] = eth_get_sym_key ((ethernet_header_t *) p[3]);
316 hash[0] = ho_hash (key[0]);
317 hash[1] = ho_hash (key[1]);
318 hash[2] = ho_hash (key[2]);
319 hash[3] = ho_hash (key[3]);
326 while (n_left_from > 0)
330 key = eth_get_sym_key ((ethernet_header_t *) p[0]);
331 hash[0] = ho_hash (key);
339 VNET_REGISTER_HASH_FUNCTION (handoff_eth_sym, static) = {
340 .name = "handoff-eth-sym",
341 .description = "Ethernet/IPv4/IPv6/MPLS headers Symmetric",
343 .function[VNET_HASH_FN_TYPE_ETHERNET] = handoff_eth_sym_func,
347 * fd.io coding-style-patch-verification: ON
350 * eval: (c-set-style "gnu")