Reorganize source tree to use single autotools instance
[vpp.git] / src / vnet / handoff.h
1 /*
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>
23 #include <vnet/mpls/packet.h>
24
25 typedef enum
26 {
27   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
35
36 static inline u64
37 ipv4_get_key (ip4_header_t * ip)
38 {
39   u64 hash_key;
40
41   hash_key = *((u64 *) (&ip->address_pair)) ^ ip->protocol;
42
43   return hash_key;
44 }
45
46 static inline u64
47 ipv6_get_key (ip6_header_t * ip)
48 {
49   u64 hash_key;
50
51   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;
55
56   return hash_key;
57 }
58
59 #define MPLS_BOTTOM_OF_STACK_BIT_MASK   0x00000100U
60 #define MPLS_LABEL_MASK                 0xFFFFF000U
61
62 static inline u64
63 mpls_get_key (mpls_unicast_header_t * m)
64 {
65   u64 hash_key;
66   u8 ip_ver;
67
68
69   /* 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++;
76
77   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++;
83
84   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++;
90
91   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++;
97
98   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     }
103
104   /* 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);
106
107   return hash_key;
108
109 bottom_lbl_found:
110   m++;
111   ip_ver = (*((u8 *) m) >> 4);
112
113   /* 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     }
128
129   return hash_key;
130
131 }
132
133 static inline u64
134 eth_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 }
199
200 static inline u64
201 eth_get_key (ethernet_header_t * h0)
202 {
203   u64 hash_key;
204
205   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);
221
222       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     }
247
248   return hash_key;
249 }
250
251 #endif /* included_vnet_handoff_h */
252
253 /*
254  * fd.io coding-style-patch-verification: ON
255  *
256  * Local Variables:
257  * eval: (c-set-style "gnu")
258  * End:
259  */