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>
25 ipv4_get_key (ip4_header_t * ip)
29 hash_key = *((u64 *) (&ip->address_pair)) ^ ip->protocol;
35 ipv6_get_key (ip6_header_t * ip)
39 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;
47 #define MPLS_BOTTOM_OF_STACK_BIT_MASK 0x00000100U
48 #define MPLS_LABEL_MASK 0xFFFFF000U
51 mpls_get_key (mpls_unicast_header_t * m)
57 /* 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)))
61 goto bottom_lbl_found;
65 if (PREDICT_TRUE (m->label_exp_s_ttl &
66 clib_net_to_host_u32 (MPLS_BOTTOM_OF_STACK_BIT_MASK)))
68 goto bottom_lbl_found;
72 if (m->label_exp_s_ttl &
73 clib_net_to_host_u32 (MPLS_BOTTOM_OF_STACK_BIT_MASK))
75 goto bottom_lbl_found;
79 if (m->label_exp_s_ttl &
80 clib_net_to_host_u32 (MPLS_BOTTOM_OF_STACK_BIT_MASK))
82 goto bottom_lbl_found;
86 if (m->label_exp_s_ttl &
87 clib_net_to_host_u32 (MPLS_BOTTOM_OF_STACK_BIT_MASK))
89 goto bottom_lbl_found;
92 /* 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);
99 ip_ver = (*((u8 *) m) >> 4);
101 /* find out if it is IPV4 or IPV6 header */
102 if (PREDICT_TRUE (ip_ver == 4))
104 hash_key = ipv4_get_key ((ip4_header_t *) m);
106 else if (PREDICT_TRUE (ip_ver == 6))
108 hash_key = ipv6_get_key ((ip6_header_t *) m);
112 /* use the bottom label */
114 (m - 1)->label_exp_s_ttl & clib_net_to_host_u32 (MPLS_LABEL_MASK);
122 eth_get_sym_key (ethernet_header_t * h0)
126 if (PREDICT_TRUE (h0->type) == clib_host_to_net_u16 (ETHERNET_TYPE_IP4))
128 ip4_header_t *ip = (ip4_header_t *) (h0 + 1);
130 (u64) (ip->src_address.as_u32 ^
131 ip->dst_address.as_u32 ^ ip->protocol);
133 else if (h0->type == clib_host_to_net_u16 (ETHERNET_TYPE_IP6))
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);
141 else if (h0->type == clib_host_to_net_u16 (ETHERNET_TYPE_MPLS))
143 hash_key = mpls_get_key ((mpls_unicast_header_t *) (h0 + 1));
147 ((h0->type == clib_host_to_net_u16 (ETHERNET_TYPE_VLAN))
148 || (h0->type == clib_host_to_net_u16 (ETHERNET_TYPE_DOT1AD))))
150 ethernet_vlan_header_t *outer = (ethernet_vlan_header_t *) (h0 + 1);
152 outer = (outer->type == clib_host_to_net_u16 (ETHERNET_TYPE_VLAN)) ?
154 if (PREDICT_TRUE (outer->type) ==
155 clib_host_to_net_u16 (ETHERNET_TYPE_IP4))
157 ip4_header_t *ip = (ip4_header_t *) (outer + 1);
159 (u64) (ip->src_address.as_u32 ^
160 ip->dst_address.as_u32 ^ ip->protocol);
162 else if (outer->type == clib_host_to_net_u16 (ETHERNET_TYPE_IP6))
164 ip6_header_t *ip = (ip6_header_t *) (outer + 1);
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);
170 else if (outer->type == clib_host_to_net_u16 (ETHERNET_TYPE_MPLS))
172 hash_key = mpls_get_key ((mpls_unicast_header_t *) (outer + 1));
176 hash_key = outer->type;
188 eth_get_key (ethernet_header_t * h0)
192 if (PREDICT_TRUE (h0->type) == clib_host_to_net_u16 (ETHERNET_TYPE_IP4))
194 hash_key = ipv4_get_key ((ip4_header_t *) (h0 + 1));
196 else if (h0->type == clib_host_to_net_u16 (ETHERNET_TYPE_IP6))
198 hash_key = ipv6_get_key ((ip6_header_t *) (h0 + 1));
200 else if (h0->type == clib_host_to_net_u16 (ETHERNET_TYPE_MPLS))
202 hash_key = mpls_get_key ((mpls_unicast_header_t *) (h0 + 1));
204 else if ((h0->type == clib_host_to_net_u16 (ETHERNET_TYPE_VLAN)) ||
205 (h0->type == clib_host_to_net_u16 (ETHERNET_TYPE_DOT1AD)))
207 ethernet_vlan_header_t *outer = (ethernet_vlan_header_t *) (h0 + 1);
209 outer = (outer->type == clib_host_to_net_u16 (ETHERNET_TYPE_VLAN)) ?
211 if (PREDICT_TRUE (outer->type) ==
212 clib_host_to_net_u16 (ETHERNET_TYPE_IP4))
214 hash_key = ipv4_get_key ((ip4_header_t *) (outer + 1));
216 else if (outer->type == clib_host_to_net_u16 (ETHERNET_TYPE_IP6))
218 hash_key = ipv6_get_key ((ip6_header_t *) (outer + 1));
220 else if (outer->type == clib_host_to_net_u16 (ETHERNET_TYPE_MPLS))
222 hash_key = mpls_get_key ((mpls_unicast_header_t *) (outer + 1));
226 hash_key = outer->type;
238 handoff_eth_crc32c_func (void **p, u32 *hash, u32 n_packets)
240 u32 n_left_from = n_packets;
242 while (n_left_from >= 8)
246 clib_prefetch_load (p[4]);
247 clib_prefetch_load (p[5]);
248 clib_prefetch_load (p[6]);
249 clib_prefetch_load (p[7]);
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]);
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]));
266 while (n_left_from > 0)
270 key = eth_get_key ((ethernet_header_t *) p[0]);
271 hash[0] = clib_crc32c ((u8 *) &key, sizeof (key));
279 VNET_REGISTER_HASH_FUNCTION (handoff_eth_crc32c, static) = {
280 .name = "handoff-eth-crc32c",
281 .description = "Ethernet/IPv4/IPv6/MPLS headers",
283 .function[VNET_HASH_FN_TYPE_ETHERNET] = handoff_eth_crc32c_func,
287 handoff_eth_sym_crc32c_func (void **p, u32 *hash, u32 n_packets)
289 u32 n_left_from = n_packets;
291 while (n_left_from >= 8)
295 clib_prefetch_load (p[4]);
296 clib_prefetch_load (p[5]);
297 clib_prefetch_load (p[6]);
298 clib_prefetch_load (p[7]);
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]);
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]));
315 while (n_left_from > 0)
319 key = eth_get_sym_key ((ethernet_header_t *) p[0]);
320 hash[0] = clib_crc32c ((u8 *) &key, sizeof (key));
328 VNET_REGISTER_HASH_FUNCTION (handoff_eth_sym_crc32c, static) = {
329 .name = "handoff-eth-sym-crc32c",
330 .description = "Ethernet/IPv4/IPv6/MPLS headers Symmetric",
332 .function[VNET_HASH_FN_TYPE_ETHERNET] = handoff_eth_sym_crc32c_func,
336 * fd.io coding-style-patch-verification: ON
339 * eval: (c-set-style "gnu")