Docs: update MPLS FIB section with text from the wiki
[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 static inline u64
26 ipv4_get_key (ip4_header_t * ip)
27 {
28   u64 hash_key;
29
30   hash_key = *((u64 *) (&ip->address_pair)) ^ ip->protocol;
31
32   return hash_key;
33 }
34
35 static inline u64
36 ipv6_get_key (ip6_header_t * ip)
37 {
38   u64 hash_key;
39
40   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;
44
45   return hash_key;
46 }
47
48 #define MPLS_BOTTOM_OF_STACK_BIT_MASK   0x00000100U
49 #define MPLS_LABEL_MASK                 0xFFFFF000U
50
51 static inline u64
52 mpls_get_key (mpls_unicast_header_t * m)
53 {
54   u64 hash_key;
55   u8 ip_ver;
56
57
58   /* 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++;
65
66   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++;
72
73   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++;
79
80   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++;
86
87   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     }
92
93   /* 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);
95
96   return hash_key;
97
98 bottom_lbl_found:
99   m++;
100   ip_ver = (*((u8 *) m) >> 4);
101
102   /* 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     }
117
118   return hash_key;
119
120 }
121
122 static inline u64
123 eth_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     }
142   else if (h0->type == clib_host_to_net_u16 (ETHERNET_TYPE_MPLS))
143     {
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         }
171       else if (outer->type == clib_host_to_net_u16 (ETHERNET_TYPE_MPLS))
172         {
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 }
187
188 static inline u64
189 eth_get_key (ethernet_header_t * h0)
190 {
191   u64 hash_key;
192
193   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     }
201   else if (h0->type == clib_host_to_net_u16 (ETHERNET_TYPE_MPLS))
202     {
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);
209
210       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         }
221       else if (outer->type == clib_host_to_net_u16 (ETHERNET_TYPE_MPLS))
222         {
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     }
234
235   return hash_key;
236 }
237
238 #endif /* included_vnet_handoff_h */
239
240 /*
241  * fd.io coding-style-patch-verification: ON
242  *
243  * Local Variables:
244  * eval: (c-set-style "gnu")
245  * End:
246  */