blob: 2cdb19440c6f278eb640ec0330a53b4978c37ec9 [file] [log] [blame]
Mohsin Kazmi41b23bc2021-06-30 18:26:25 +00001/*
2 * SPDX-License-Identifier: Apache-2.0
3 * Copyright(c) 2021 Cisco Systems, Inc.
4 */
5
6#include <vnet/vnet.h>
7#include <vnet/ethernet/ethernet.h>
8#include <vnet/ip/ip4_packet.h>
9#include <vnet/ip/ip6_packet.h>
Mohsin Kazmi41b23bc2021-06-30 18:26:25 +000010#include <vnet/hash/hash.h>
11#include <vppinfra/crc32.h>
12
Damjan Marion26abb602021-10-31 20:18:13 +010013#ifdef clib_crc32c_uses_intrinsics
14
Mohsin Kazmi41b23bc2021-06-30 18:26:25 +000015static const u8 l4_mask_bits[256] = {
16 [IP_PROTOCOL_ICMP] = 16, [IP_PROTOCOL_IGMP] = 8,
17 [IP_PROTOCOL_TCP] = 32, [IP_PROTOCOL_UDP] = 32,
18 [IP_PROTOCOL_IPSEC_ESP] = 32, [IP_PROTOCOL_IPSEC_AH] = 32,
19 [IP_PROTOCOL_ICMP6] = 16,
20};
21
Damjan Marion271daab2021-11-12 16:00:24 +010022static_always_inline u32
23compute_ip6_key (ip6_header_t *ip)
Mohsin Kazmi41b23bc2021-06-30 18:26:25 +000024{
Damjan Marion271daab2021-11-12 16:00:24 +010025 u32 hash = 0, l4hdr;
Mohsin Kazmi41b23bc2021-06-30 18:26:25 +000026 u8 pr;
Damjan Marion271daab2021-11-12 16:00:24 +010027 /* dst + src ip as u64 */
28 hash = clib_crc32c_u64 (hash, *(u64u *) ((u8 *) ip + 8));
29 hash = clib_crc32c_u64 (hash, *(u64u *) ((u8 *) ip + 16));
30 hash = clib_crc32c_u64 (hash, *(u64u *) ((u8 *) ip + 24));
31 hash = clib_crc32c_u64 (hash, *(u64u *) ((u8 *) ip + 32));
Mohsin Kazmi41b23bc2021-06-30 18:26:25 +000032 pr = ip->protocol;
Damjan Marion271daab2021-11-12 16:00:24 +010033 l4hdr = *(u32 *) ip6_next_header (ip) & pow2_mask (l4_mask_bits[pr]);
34 /* protocol + l4 hdr */
35 return clib_crc32c_u64 (hash, ((u64) pr << 32) | l4hdr);
Mohsin Kazmi41b23bc2021-06-30 18:26:25 +000036}
37
Damjan Marion271daab2021-11-12 16:00:24 +010038static_always_inline u32
39compute_ip4_key (ip4_header_t *ip)
Mohsin Kazmi41b23bc2021-06-30 18:26:25 +000040{
Damjan Marion271daab2021-11-12 16:00:24 +010041 u32 hash = 0, l4hdr;
Mohsin Kazmi41b23bc2021-06-30 18:26:25 +000042 u8 pr;
Damjan Marion271daab2021-11-12 16:00:24 +010043 /* dst + src ip as u64 */
44 hash = clib_crc32c_u64 (0, *(u64 *) ((u8 *) ip + 12));
Mohsin Kazmi41b23bc2021-06-30 18:26:25 +000045 pr = ip->protocol;
Damjan Marion271daab2021-11-12 16:00:24 +010046 l4hdr = *(u32 *) ip4_next_header (ip) & pow2_mask (l4_mask_bits[pr]);
47 /* protocol + l4 hdr */
48 return clib_crc32c_u64 (hash, ((u64) pr << 32) | l4hdr);
Mohsin Kazmi41b23bc2021-06-30 18:26:25 +000049}
Damjan Marion271daab2021-11-12 16:00:24 +010050static_always_inline u32
51compute_ip_key (void *p)
Mohsin Kazmi41b23bc2021-06-30 18:26:25 +000052{
53 if ((((u8 *) p)[0] & 0xf0) == 0x40)
Damjan Marion271daab2021-11-12 16:00:24 +010054 return compute_ip4_key (p);
Mohsin Kazmi41b23bc2021-06-30 18:26:25 +000055 else if ((((u8 *) p)[0] & 0xf0) == 0x60)
Damjan Marion271daab2021-11-12 16:00:24 +010056 return compute_ip6_key (p);
57 return 0;
Mohsin Kazmi41b23bc2021-06-30 18:26:25 +000058}
59
60void
61vnet_crc32c_5tuple_ip_func (void **p, u32 *hash, u32 n_packets)
62{
63 u32 n_left_from = n_packets;
64
65 while (n_left_from >= 8)
66 {
Mohsin Kazmi41b23bc2021-06-30 18:26:25 +000067 clib_prefetch_load (p[4]);
68 clib_prefetch_load (p[5]);
69 clib_prefetch_load (p[6]);
70 clib_prefetch_load (p[7]);
71
Damjan Marion271daab2021-11-12 16:00:24 +010072 hash[0] = compute_ip_key (p[0]);
73 hash[1] = compute_ip_key (p[1]);
74 hash[2] = compute_ip_key (p[2]);
75 hash[3] = compute_ip_key (p[3]);
Mohsin Kazmi41b23bc2021-06-30 18:26:25 +000076
77 hash += 4;
78 n_left_from -= 4;
79 p += 4;
80 }
81
82 while (n_left_from > 0)
83 {
Damjan Marion271daab2021-11-12 16:00:24 +010084 hash[0] = compute_ip_key (p[0]);
Mohsin Kazmi41b23bc2021-06-30 18:26:25 +000085
86 hash += 1;
87 n_left_from -= 1;
88 p += 1;
89 }
90}
91
Damjan Marion271daab2021-11-12 16:00:24 +010092static_always_inline u32
93compute_ethernet_key (void *p)
Mohsin Kazmi41b23bc2021-06-30 18:26:25 +000094{
95 u16 ethertype = 0, l2hdr_sz = 0;
96
97 ethernet_header_t *eh = (ethernet_header_t *) p;
98 ethertype = clib_net_to_host_u16 (eh->type);
99 l2hdr_sz = sizeof (ethernet_header_t);
100
101 if (ethernet_frame_is_tagged (ethertype))
102 {
103 ethernet_vlan_header_t *vlan = (ethernet_vlan_header_t *) (eh + 1);
104
105 ethertype = clib_net_to_host_u16 (vlan->type);
106 l2hdr_sz += sizeof (*vlan);
107 while (ethernet_frame_is_tagged (ethertype))
108 {
109 vlan++;
110 ethertype = clib_net_to_host_u16 (vlan->type);
111 l2hdr_sz += sizeof (*vlan);
112 }
113 }
114
115 if (ethertype == ETHERNET_TYPE_IP4)
116 {
117 ip4_header_t *ip4 = (ip4_header_t *) (p + l2hdr_sz);
Damjan Marion271daab2021-11-12 16:00:24 +0100118 return compute_ip4_key (ip4);
Mohsin Kazmi41b23bc2021-06-30 18:26:25 +0000119 }
120 else if (ethertype == ETHERNET_TYPE_IP6)
121 {
122 ip6_header_t *ip6 = (ip6_header_t *) (p + l2hdr_sz);
Damjan Marion271daab2021-11-12 16:00:24 +0100123 return compute_ip6_key (ip6);
Mohsin Kazmi41b23bc2021-06-30 18:26:25 +0000124 }
Damjan Marion271daab2021-11-12 16:00:24 +0100125 return 0;
Mohsin Kazmi41b23bc2021-06-30 18:26:25 +0000126}
127
128void
129vnet_crc32c_5tuple_ethernet_func (void **p, u32 *hash, u32 n_packets)
130{
131 u32 n_left_from = n_packets;
132
133 while (n_left_from >= 8)
134 {
Mohsin Kazmi41b23bc2021-06-30 18:26:25 +0000135 clib_prefetch_load (p[4]);
136 clib_prefetch_load (p[5]);
137 clib_prefetch_load (p[6]);
138 clib_prefetch_load (p[7]);
139
Damjan Marion271daab2021-11-12 16:00:24 +0100140 hash[0] = compute_ethernet_key (p[0]);
141 hash[1] = compute_ethernet_key (p[1]);
142 hash[2] = compute_ethernet_key (p[2]);
143 hash[3] = compute_ethernet_key (p[3]);
Mohsin Kazmi41b23bc2021-06-30 18:26:25 +0000144
145 hash += 4;
146 n_left_from -= 4;
147 p += 4;
148 }
149
150 while (n_left_from > 0)
151 {
Damjan Marion271daab2021-11-12 16:00:24 +0100152 hash[0] = compute_ethernet_key (p[0]);
Mohsin Kazmi41b23bc2021-06-30 18:26:25 +0000153
154 hash += 1;
155 n_left_from -= 1;
156 p += 1;
157 }
158}
159
160VNET_REGISTER_HASH_FUNCTION (crc32c_5tuple, static) = {
161 .name = "crc32c-5tuple",
162 .description = "IPv4/IPv6 header and TCP/UDP ports",
163 .priority = 50,
164 .function[VNET_HASH_FN_TYPE_ETHERNET] = vnet_crc32c_5tuple_ethernet_func,
165 .function[VNET_HASH_FN_TYPE_IP] = vnet_crc32c_5tuple_ip_func,
166};
Damjan Marion26abb602021-10-31 20:18:13 +0100167
168#endif