blob: 04ba8bfbc024150e2f9d3c644a52c68d6907aa2f [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 -040025typedef enum
26{
Damjan Marion0247b462016-06-08 01:37:11 +020027 HANDOFF_DISPATCH_NEXT_IP4_INPUT,
28 HANDOFF_DISPATCH_NEXT_IP6_INPUT,
29 HANDOFF_DISPATCH_NEXT_MPLS_INPUT,
30 HANDOFF_DISPATCH_NEXT_ETHERNET_INPUT,
31 HANDOFF_DISPATCH_NEXT_DROP,
32 HANDOFF_DISPATCH_N_NEXT,
33} handoff_dispatch_next_t;
34
Damjan Marion0247b462016-06-08 01:37:11 +020035
Dave Barachba868bb2016-08-08 09:51:21 -040036static inline u64
37ipv4_get_key (ip4_header_t * ip)
Damjan Marion0247b462016-06-08 01:37:11 +020038{
Dave Barachba868bb2016-08-08 09:51:21 -040039 u64 hash_key;
Damjan Marion0247b462016-06-08 01:37:11 +020040
Dave Barachba868bb2016-08-08 09:51:21 -040041 hash_key = *((u64 *) (&ip->address_pair)) ^ ip->protocol;
Damjan Marion0247b462016-06-08 01:37:11 +020042
Dave Barachba868bb2016-08-08 09:51:21 -040043 return hash_key;
Damjan Marion0247b462016-06-08 01:37:11 +020044}
45
Dave Barachba868bb2016-08-08 09:51:21 -040046static inline u64
47ipv6_get_key (ip6_header_t * ip)
Damjan Marion0247b462016-06-08 01:37:11 +020048{
Dave Barachba868bb2016-08-08 09:51:21 -040049 u64 hash_key;
Damjan Marion0247b462016-06-08 01:37:11 +020050
Dave Barachba868bb2016-08-08 09:51:21 -040051 hash_key = ip->src_address.as_u64[0] ^
52 rotate_left (ip->src_address.as_u64[1], 13) ^
53 rotate_left (ip->dst_address.as_u64[0], 26) ^
54 rotate_left (ip->dst_address.as_u64[1], 39) ^ ip->protocol;
Damjan Marion0247b462016-06-08 01:37:11 +020055
Dave Barachba868bb2016-08-08 09:51:21 -040056 return hash_key;
Damjan Marion0247b462016-06-08 01:37:11 +020057}
58
59#define MPLS_BOTTOM_OF_STACK_BIT_MASK 0x00000100U
60#define MPLS_LABEL_MASK 0xFFFFF000U
61
Dave Barachba868bb2016-08-08 09:51:21 -040062static inline u64
63mpls_get_key (mpls_unicast_header_t * m)
Damjan Marion0247b462016-06-08 01:37:11 +020064{
Dave Barachba868bb2016-08-08 09:51:21 -040065 u64 hash_key;
66 u8 ip_ver;
Damjan Marion0247b462016-06-08 01:37:11 +020067
68
Dave Barachba868bb2016-08-08 09:51:21 -040069 /* find the bottom of the MPLS label stack. */
70 if (PREDICT_TRUE (m->label_exp_s_ttl &
71 clib_net_to_host_u32 (MPLS_BOTTOM_OF_STACK_BIT_MASK)))
72 {
73 goto bottom_lbl_found;
74 }
75 m++;
Damjan Marion0247b462016-06-08 01:37:11 +020076
Dave Barachba868bb2016-08-08 09:51:21 -040077 if (PREDICT_TRUE (m->label_exp_s_ttl &
78 clib_net_to_host_u32 (MPLS_BOTTOM_OF_STACK_BIT_MASK)))
79 {
80 goto bottom_lbl_found;
81 }
82 m++;
Damjan Marion0247b462016-06-08 01:37:11 +020083
Dave Barachba868bb2016-08-08 09:51:21 -040084 if (m->label_exp_s_ttl &
85 clib_net_to_host_u32 (MPLS_BOTTOM_OF_STACK_BIT_MASK))
86 {
87 goto bottom_lbl_found;
88 }
89 m++;
Damjan Marion0247b462016-06-08 01:37:11 +020090
Dave Barachba868bb2016-08-08 09:51:21 -040091 if (m->label_exp_s_ttl &
92 clib_net_to_host_u32 (MPLS_BOTTOM_OF_STACK_BIT_MASK))
93 {
94 goto bottom_lbl_found;
95 }
96 m++;
Damjan Marion0247b462016-06-08 01:37:11 +020097
Dave Barachba868bb2016-08-08 09:51:21 -040098 if (m->label_exp_s_ttl &
99 clib_net_to_host_u32 (MPLS_BOTTOM_OF_STACK_BIT_MASK))
100 {
101 goto bottom_lbl_found;
102 }
Damjan Marion0247b462016-06-08 01:37:11 +0200103
Dave Barachba868bb2016-08-08 09:51:21 -0400104 /* the bottom label was not found - use the last label */
105 hash_key = m->label_exp_s_ttl & clib_net_to_host_u32 (MPLS_LABEL_MASK);
Damjan Marion0247b462016-06-08 01:37:11 +0200106
Dave Barachba868bb2016-08-08 09:51:21 -0400107 return hash_key;
Damjan Marion0247b462016-06-08 01:37:11 +0200108
109bottom_lbl_found:
Dave Barachba868bb2016-08-08 09:51:21 -0400110 m++;
111 ip_ver = (*((u8 *) m) >> 4);
Damjan Marion0247b462016-06-08 01:37:11 +0200112
Dave Barachba868bb2016-08-08 09:51:21 -0400113 /* find out if it is IPV4 or IPV6 header */
114 if (PREDICT_TRUE (ip_ver == 4))
115 {
116 hash_key = ipv4_get_key ((ip4_header_t *) m);
117 }
118 else if (PREDICT_TRUE (ip_ver == 6))
119 {
120 hash_key = ipv6_get_key ((ip6_header_t *) m);
121 }
122 else
123 {
124 /* use the bottom label */
125 hash_key =
126 (m - 1)->label_exp_s_ttl & clib_net_to_host_u32 (MPLS_LABEL_MASK);
127 }
Damjan Marion0247b462016-06-08 01:37:11 +0200128
Dave Barachba868bb2016-08-08 09:51:21 -0400129 return hash_key;
Damjan Marion0247b462016-06-08 01:37:11 +0200130
131}
132
Gabriel Gannec0a36c02016-11-16 16:57:00 +0100133static inline u64
134eth_get_sym_key (ethernet_header_t * h0)
135{
136 u64 hash_key;
137
138 if (PREDICT_TRUE (h0->type) == clib_host_to_net_u16 (ETHERNET_TYPE_IP4))
139 {
140 ip4_header_t *ip = (ip4_header_t *) (h0 + 1);
141 hash_key =
142 (u64) (ip->src_address.as_u32 ^
143 ip->dst_address.as_u32 ^ ip->protocol);
144 }
145 else if (h0->type == clib_host_to_net_u16 (ETHERNET_TYPE_IP6))
146 {
147 ip6_header_t *ip = (ip6_header_t *) (h0 + 1);
148 hash_key = (u64) (ip->src_address.as_u64[0] ^
149 ip->src_address.as_u64[1] ^
150 ip->dst_address.as_u64[0] ^
151 ip->dst_address.as_u64[1] ^ ip->protocol);
152 }
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800153 else if (h0->type == clib_host_to_net_u16 (ETHERNET_TYPE_MPLS))
Gabriel Gannec0a36c02016-11-16 16:57:00 +0100154 {
155 hash_key = mpls_get_key ((mpls_unicast_header_t *) (h0 + 1));
156 }
157 else
158 if (PREDICT_FALSE
159 ((h0->type == clib_host_to_net_u16 (ETHERNET_TYPE_VLAN))
160 || (h0->type == clib_host_to_net_u16 (ETHERNET_TYPE_DOT1AD))))
161 {
162 ethernet_vlan_header_t *outer = (ethernet_vlan_header_t *) (h0 + 1);
163
164 outer = (outer->type == clib_host_to_net_u16 (ETHERNET_TYPE_VLAN)) ?
165 outer + 1 : outer;
166 if (PREDICT_TRUE (outer->type) ==
167 clib_host_to_net_u16 (ETHERNET_TYPE_IP4))
168 {
169 ip4_header_t *ip = (ip4_header_t *) (outer + 1);
170 hash_key =
171 (u64) (ip->src_address.as_u32 ^
172 ip->dst_address.as_u32 ^ ip->protocol);
173 }
174 else if (outer->type == clib_host_to_net_u16 (ETHERNET_TYPE_IP6))
175 {
176 ip6_header_t *ip = (ip6_header_t *) (outer + 1);
177 hash_key =
178 (u64) (ip->src_address.as_u64[0] ^ ip->src_address.as_u64[1] ^
179 ip->dst_address.as_u64[0] ^
180 ip->dst_address.as_u64[1] ^ ip->protocol);
181 }
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800182 else if (outer->type == clib_host_to_net_u16 (ETHERNET_TYPE_MPLS))
Gabriel Gannec0a36c02016-11-16 16:57:00 +0100183 {
184 hash_key = mpls_get_key ((mpls_unicast_header_t *) (outer + 1));
185 }
186 else
187 {
188 hash_key = outer->type;
189 }
190 }
191 else
192 {
193 hash_key = 0;
194 }
195
196 return hash_key;
197}
Damjan Marion0247b462016-06-08 01:37:11 +0200198
199static inline u64
Dave Barachba868bb2016-08-08 09:51:21 -0400200eth_get_key (ethernet_header_t * h0)
Damjan Marion0247b462016-06-08 01:37:11 +0200201{
Dave Barachba868bb2016-08-08 09:51:21 -0400202 u64 hash_key;
Damjan Marion0247b462016-06-08 01:37:11 +0200203
Dave Barachba868bb2016-08-08 09:51:21 -0400204 if (PREDICT_TRUE (h0->type) == clib_host_to_net_u16 (ETHERNET_TYPE_IP4))
205 {
206 hash_key = ipv4_get_key ((ip4_header_t *) (h0 + 1));
207 }
208 else if (h0->type == clib_host_to_net_u16 (ETHERNET_TYPE_IP6))
209 {
210 hash_key = ipv6_get_key ((ip6_header_t *) (h0 + 1));
211 }
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800212 else if (h0->type == clib_host_to_net_u16 (ETHERNET_TYPE_MPLS))
Dave Barachba868bb2016-08-08 09:51:21 -0400213 {
214 hash_key = mpls_get_key ((mpls_unicast_header_t *) (h0 + 1));
215 }
216 else if ((h0->type == clib_host_to_net_u16 (ETHERNET_TYPE_VLAN)) ||
217 (h0->type == clib_host_to_net_u16 (ETHERNET_TYPE_DOT1AD)))
218 {
219 ethernet_vlan_header_t *outer = (ethernet_vlan_header_t *) (h0 + 1);
Damjan Marion0247b462016-06-08 01:37:11 +0200220
Dave Barachba868bb2016-08-08 09:51:21 -0400221 outer = (outer->type == clib_host_to_net_u16 (ETHERNET_TYPE_VLAN)) ?
222 outer + 1 : outer;
223 if (PREDICT_TRUE (outer->type) ==
224 clib_host_to_net_u16 (ETHERNET_TYPE_IP4))
225 {
226 hash_key = ipv4_get_key ((ip4_header_t *) (outer + 1));
227 }
228 else if (outer->type == clib_host_to_net_u16 (ETHERNET_TYPE_IP6))
229 {
230 hash_key = ipv6_get_key ((ip6_header_t *) (outer + 1));
231 }
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800232 else if (outer->type == clib_host_to_net_u16 (ETHERNET_TYPE_MPLS))
Dave Barachba868bb2016-08-08 09:51:21 -0400233 {
234 hash_key = mpls_get_key ((mpls_unicast_header_t *) (outer + 1));
235 }
236 else
237 {
238 hash_key = outer->type;
239 }
240 }
241 else
242 {
243 hash_key = 0;
244 }
Damjan Marion0247b462016-06-08 01:37:11 +0200245
Dave Barachba868bb2016-08-08 09:51:21 -0400246 return hash_key;
Damjan Marion0247b462016-06-08 01:37:11 +0200247}
248
249#endif /* included_vnet_handoff_h */
Dave Barachba868bb2016-08-08 09:51:21 -0400250
251/*
252 * fd.io coding-style-patch-verification: ON
253 *
254 * Local Variables:
255 * eval: (c-set-style "gnu")
256 * End:
257 */