blob: 815206a9f8c4d58364bd26688f22e62ac3dc1b38 [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 }
153 else if (h0->type == clib_host_to_net_u16 (ETHERNET_TYPE_MPLS_UNICAST))
154 {
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 }
182 else if (outer->type ==
183 clib_host_to_net_u16 (ETHERNET_TYPE_MPLS_UNICAST))
184 {
185 hash_key = mpls_get_key ((mpls_unicast_header_t *) (outer + 1));
186 }
187 else
188 {
189 hash_key = outer->type;
190 }
191 }
192 else
193 {
194 hash_key = 0;
195 }
196
197 return hash_key;
198}
Damjan Marion0247b462016-06-08 01:37:11 +0200199
200static inline u64
Dave Barachba868bb2016-08-08 09:51:21 -0400201eth_get_key (ethernet_header_t * h0)
Damjan Marion0247b462016-06-08 01:37:11 +0200202{
Dave Barachba868bb2016-08-08 09:51:21 -0400203 u64 hash_key;
Damjan Marion0247b462016-06-08 01:37:11 +0200204
Dave Barachba868bb2016-08-08 09:51:21 -0400205 if (PREDICT_TRUE (h0->type) == clib_host_to_net_u16 (ETHERNET_TYPE_IP4))
206 {
207 hash_key = ipv4_get_key ((ip4_header_t *) (h0 + 1));
208 }
209 else if (h0->type == clib_host_to_net_u16 (ETHERNET_TYPE_IP6))
210 {
211 hash_key = ipv6_get_key ((ip6_header_t *) (h0 + 1));
212 }
213 else if (h0->type == clib_host_to_net_u16 (ETHERNET_TYPE_MPLS_UNICAST))
214 {
215 hash_key = mpls_get_key ((mpls_unicast_header_t *) (h0 + 1));
216 }
217 else if ((h0->type == clib_host_to_net_u16 (ETHERNET_TYPE_VLAN)) ||
218 (h0->type == clib_host_to_net_u16 (ETHERNET_TYPE_DOT1AD)))
219 {
220 ethernet_vlan_header_t *outer = (ethernet_vlan_header_t *) (h0 + 1);
Damjan Marion0247b462016-06-08 01:37:11 +0200221
Dave Barachba868bb2016-08-08 09:51:21 -0400222 outer = (outer->type == clib_host_to_net_u16 (ETHERNET_TYPE_VLAN)) ?
223 outer + 1 : outer;
224 if (PREDICT_TRUE (outer->type) ==
225 clib_host_to_net_u16 (ETHERNET_TYPE_IP4))
226 {
227 hash_key = ipv4_get_key ((ip4_header_t *) (outer + 1));
228 }
229 else if (outer->type == clib_host_to_net_u16 (ETHERNET_TYPE_IP6))
230 {
231 hash_key = ipv6_get_key ((ip6_header_t *) (outer + 1));
232 }
233 else if (outer->type ==
234 clib_host_to_net_u16 (ETHERNET_TYPE_MPLS_UNICAST))
235 {
236 hash_key = mpls_get_key ((mpls_unicast_header_t *) (outer + 1));
237 }
238 else
239 {
240 hash_key = outer->type;
241 }
242 }
243 else
244 {
245 hash_key = 0;
246 }
Damjan Marion0247b462016-06-08 01:37:11 +0200247
Dave Barachba868bb2016-08-08 09:51:21 -0400248 return hash_key;
Damjan Marion0247b462016-06-08 01:37:11 +0200249}
250
251#endif /* included_vnet_handoff_h */
Dave Barachba868bb2016-08-08 09:51:21 -0400252
253/*
254 * fd.io coding-style-patch-verification: ON
255 *
256 * Local Variables:
257 * eval: (c-set-style "gnu")
258 * End:
259 */