blob: f50b86d5c6d0166ec98a241efd5a2ca991419563 [file] [log] [blame]
Damjan Marion0247b462016-06-08 01:37:11 +02001/*
2 * Copyright (c) 2016 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:
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
16#ifndef included_vnet_handoff_h
17#define included_vnet_handoff_h
18
19#include <vlib/vlib.h>
20#include <vnet/ethernet/ethernet.h>
21#include <vnet/ip/ip4_packet.h>
22#include <vnet/ip/ip6_packet.h>
Neale Ranns0bfe5d82016-08-25 15:29:12 +010023#include <vnet/mpls/packet.h>
Damjan Marion0247b462016-06-08 01:37:11 +020024
Dave Barachba868bb2016-08-08 09:51:21 -040025static inline u64
26ipv4_get_key (ip4_header_t * ip)
Damjan Marion0247b462016-06-08 01:37:11 +020027{
Dave Barachba868bb2016-08-08 09:51:21 -040028 u64 hash_key;
Damjan Marion0247b462016-06-08 01:37:11 +020029
Dave Barachba868bb2016-08-08 09:51:21 -040030 hash_key = *((u64 *) (&ip->address_pair)) ^ ip->protocol;
Damjan Marion0247b462016-06-08 01:37:11 +020031
Dave Barachba868bb2016-08-08 09:51:21 -040032 return hash_key;
Damjan Marion0247b462016-06-08 01:37:11 +020033}
34
Dave Barachba868bb2016-08-08 09:51:21 -040035static inline u64
36ipv6_get_key (ip6_header_t * ip)
Damjan Marion0247b462016-06-08 01:37:11 +020037{
Dave Barachba868bb2016-08-08 09:51:21 -040038 u64 hash_key;
Damjan Marion0247b462016-06-08 01:37:11 +020039
Dave Barachba868bb2016-08-08 09:51:21 -040040 hash_key = ip->src_address.as_u64[0] ^
41 rotate_left (ip->src_address.as_u64[1], 13) ^
42 rotate_left (ip->dst_address.as_u64[0], 26) ^
43 rotate_left (ip->dst_address.as_u64[1], 39) ^ ip->protocol;
Damjan Marion0247b462016-06-08 01:37:11 +020044
Dave Barachba868bb2016-08-08 09:51:21 -040045 return hash_key;
Damjan Marion0247b462016-06-08 01:37:11 +020046}
47
48#define MPLS_BOTTOM_OF_STACK_BIT_MASK 0x00000100U
49#define MPLS_LABEL_MASK 0xFFFFF000U
50
Dave Barachba868bb2016-08-08 09:51:21 -040051static inline u64
52mpls_get_key (mpls_unicast_header_t * m)
Damjan Marion0247b462016-06-08 01:37:11 +020053{
Dave Barachba868bb2016-08-08 09:51:21 -040054 u64 hash_key;
55 u8 ip_ver;
Damjan Marion0247b462016-06-08 01:37:11 +020056
57
Dave Barachba868bb2016-08-08 09:51:21 -040058 /* find the bottom of the MPLS label stack. */
59 if (PREDICT_TRUE (m->label_exp_s_ttl &
60 clib_net_to_host_u32 (MPLS_BOTTOM_OF_STACK_BIT_MASK)))
61 {
62 goto bottom_lbl_found;
63 }
64 m++;
Damjan Marion0247b462016-06-08 01:37:11 +020065
Dave Barachba868bb2016-08-08 09:51:21 -040066 if (PREDICT_TRUE (m->label_exp_s_ttl &
67 clib_net_to_host_u32 (MPLS_BOTTOM_OF_STACK_BIT_MASK)))
68 {
69 goto bottom_lbl_found;
70 }
71 m++;
Damjan Marion0247b462016-06-08 01:37:11 +020072
Dave Barachba868bb2016-08-08 09:51:21 -040073 if (m->label_exp_s_ttl &
74 clib_net_to_host_u32 (MPLS_BOTTOM_OF_STACK_BIT_MASK))
75 {
76 goto bottom_lbl_found;
77 }
78 m++;
Damjan Marion0247b462016-06-08 01:37:11 +020079
Dave Barachba868bb2016-08-08 09:51:21 -040080 if (m->label_exp_s_ttl &
81 clib_net_to_host_u32 (MPLS_BOTTOM_OF_STACK_BIT_MASK))
82 {
83 goto bottom_lbl_found;
84 }
85 m++;
Damjan Marion0247b462016-06-08 01:37:11 +020086
Dave Barachba868bb2016-08-08 09:51:21 -040087 if (m->label_exp_s_ttl &
88 clib_net_to_host_u32 (MPLS_BOTTOM_OF_STACK_BIT_MASK))
89 {
90 goto bottom_lbl_found;
91 }
Damjan Marion0247b462016-06-08 01:37:11 +020092
Dave Barachba868bb2016-08-08 09:51:21 -040093 /* the bottom label was not found - use the last label */
94 hash_key = m->label_exp_s_ttl & clib_net_to_host_u32 (MPLS_LABEL_MASK);
Damjan Marion0247b462016-06-08 01:37:11 +020095
Dave Barachba868bb2016-08-08 09:51:21 -040096 return hash_key;
Damjan Marion0247b462016-06-08 01:37:11 +020097
98bottom_lbl_found:
Dave Barachba868bb2016-08-08 09:51:21 -040099 m++;
100 ip_ver = (*((u8 *) m) >> 4);
Damjan Marion0247b462016-06-08 01:37:11 +0200101
Dave Barachba868bb2016-08-08 09:51:21 -0400102 /* find out if it is IPV4 or IPV6 header */
103 if (PREDICT_TRUE (ip_ver == 4))
104 {
105 hash_key = ipv4_get_key ((ip4_header_t *) m);
106 }
107 else if (PREDICT_TRUE (ip_ver == 6))
108 {
109 hash_key = ipv6_get_key ((ip6_header_t *) m);
110 }
111 else
112 {
113 /* use the bottom label */
114 hash_key =
115 (m - 1)->label_exp_s_ttl & clib_net_to_host_u32 (MPLS_LABEL_MASK);
116 }
Damjan Marion0247b462016-06-08 01:37:11 +0200117
Dave Barachba868bb2016-08-08 09:51:21 -0400118 return hash_key;
Damjan Marion0247b462016-06-08 01:37:11 +0200119
120}
121
Gabriel Gannec0a36c02016-11-16 16:57:00 +0100122static inline u64
123eth_get_sym_key (ethernet_header_t * h0)
124{
125 u64 hash_key;
126
127 if (PREDICT_TRUE (h0->type) == clib_host_to_net_u16 (ETHERNET_TYPE_IP4))
128 {
129 ip4_header_t *ip = (ip4_header_t *) (h0 + 1);
130 hash_key =
131 (u64) (ip->src_address.as_u32 ^
132 ip->dst_address.as_u32 ^ ip->protocol);
133 }
134 else if (h0->type == clib_host_to_net_u16 (ETHERNET_TYPE_IP6))
135 {
136 ip6_header_t *ip = (ip6_header_t *) (h0 + 1);
137 hash_key = (u64) (ip->src_address.as_u64[0] ^
138 ip->src_address.as_u64[1] ^
139 ip->dst_address.as_u64[0] ^
140 ip->dst_address.as_u64[1] ^ ip->protocol);
141 }
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800142 else if (h0->type == clib_host_to_net_u16 (ETHERNET_TYPE_MPLS))
Gabriel Gannec0a36c02016-11-16 16:57:00 +0100143 {
144 hash_key = mpls_get_key ((mpls_unicast_header_t *) (h0 + 1));
145 }
146 else
147 if (PREDICT_FALSE
148 ((h0->type == clib_host_to_net_u16 (ETHERNET_TYPE_VLAN))
149 || (h0->type == clib_host_to_net_u16 (ETHERNET_TYPE_DOT1AD))))
150 {
151 ethernet_vlan_header_t *outer = (ethernet_vlan_header_t *) (h0 + 1);
152
153 outer = (outer->type == clib_host_to_net_u16 (ETHERNET_TYPE_VLAN)) ?
154 outer + 1 : outer;
155 if (PREDICT_TRUE (outer->type) ==
156 clib_host_to_net_u16 (ETHERNET_TYPE_IP4))
157 {
158 ip4_header_t *ip = (ip4_header_t *) (outer + 1);
159 hash_key =
160 (u64) (ip->src_address.as_u32 ^
161 ip->dst_address.as_u32 ^ ip->protocol);
162 }
163 else if (outer->type == clib_host_to_net_u16 (ETHERNET_TYPE_IP6))
164 {
165 ip6_header_t *ip = (ip6_header_t *) (outer + 1);
166 hash_key =
167 (u64) (ip->src_address.as_u64[0] ^ ip->src_address.as_u64[1] ^
168 ip->dst_address.as_u64[0] ^
169 ip->dst_address.as_u64[1] ^ ip->protocol);
170 }
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800171 else if (outer->type == clib_host_to_net_u16 (ETHERNET_TYPE_MPLS))
Gabriel Gannec0a36c02016-11-16 16:57:00 +0100172 {
173 hash_key = mpls_get_key ((mpls_unicast_header_t *) (outer + 1));
174 }
175 else
176 {
177 hash_key = outer->type;
178 }
179 }
180 else
181 {
182 hash_key = 0;
183 }
184
185 return hash_key;
186}
Damjan Marion0247b462016-06-08 01:37:11 +0200187
188static inline u64
Dave Barachba868bb2016-08-08 09:51:21 -0400189eth_get_key (ethernet_header_t * h0)
Damjan Marion0247b462016-06-08 01:37:11 +0200190{
Dave Barachba868bb2016-08-08 09:51:21 -0400191 u64 hash_key;
Damjan Marion0247b462016-06-08 01:37:11 +0200192
Dave Barachba868bb2016-08-08 09:51:21 -0400193 if (PREDICT_TRUE (h0->type) == clib_host_to_net_u16 (ETHERNET_TYPE_IP4))
194 {
195 hash_key = ipv4_get_key ((ip4_header_t *) (h0 + 1));
196 }
197 else if (h0->type == clib_host_to_net_u16 (ETHERNET_TYPE_IP6))
198 {
199 hash_key = ipv6_get_key ((ip6_header_t *) (h0 + 1));
200 }
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800201 else if (h0->type == clib_host_to_net_u16 (ETHERNET_TYPE_MPLS))
Dave Barachba868bb2016-08-08 09:51:21 -0400202 {
203 hash_key = mpls_get_key ((mpls_unicast_header_t *) (h0 + 1));
204 }
205 else if ((h0->type == clib_host_to_net_u16 (ETHERNET_TYPE_VLAN)) ||
206 (h0->type == clib_host_to_net_u16 (ETHERNET_TYPE_DOT1AD)))
207 {
208 ethernet_vlan_header_t *outer = (ethernet_vlan_header_t *) (h0 + 1);
Damjan Marion0247b462016-06-08 01:37:11 +0200209
Dave Barachba868bb2016-08-08 09:51:21 -0400210 outer = (outer->type == clib_host_to_net_u16 (ETHERNET_TYPE_VLAN)) ?
211 outer + 1 : outer;
212 if (PREDICT_TRUE (outer->type) ==
213 clib_host_to_net_u16 (ETHERNET_TYPE_IP4))
214 {
215 hash_key = ipv4_get_key ((ip4_header_t *) (outer + 1));
216 }
217 else if (outer->type == clib_host_to_net_u16 (ETHERNET_TYPE_IP6))
218 {
219 hash_key = ipv6_get_key ((ip6_header_t *) (outer + 1));
220 }
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800221 else if (outer->type == clib_host_to_net_u16 (ETHERNET_TYPE_MPLS))
Dave Barachba868bb2016-08-08 09:51:21 -0400222 {
223 hash_key = mpls_get_key ((mpls_unicast_header_t *) (outer + 1));
224 }
225 else
226 {
227 hash_key = outer->type;
228 }
229 }
230 else
231 {
232 hash_key = 0;
233 }
Damjan Marion0247b462016-06-08 01:37:11 +0200234
Dave Barachba868bb2016-08-08 09:51:21 -0400235 return hash_key;
Damjan Marion0247b462016-06-08 01:37:11 +0200236}
237
238#endif /* included_vnet_handoff_h */
Dave Barachba868bb2016-08-08 09:51:21 -0400239
240/*
241 * fd.io coding-style-patch-verification: ON
242 *
243 * Local Variables:
244 * eval: (c-set-style "gnu")
245 * End:
246 */