loop counter to prevent infiinte number of look ups per-packet
[vpp.git] / src / vnet / mpls / mpls_lookup.h
1 /*
2  * Copyright (c) 2015 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 __MPLS_LOOKUP_H__
17 #define __MPLS_LOOKUP_H__
18
19 #include <vnet/mpls/mpls.h>
20 #include <vnet/ip/ip.h>
21
22 /**
23  * The arc/edge from the MPLS lookup node to the MPLS replicate node
24  */
25 u32 mpls_lookup_to_replicate_edge;
26
27 /**
28  * Enum of statically configred MPLS lookup next nodes
29  */
30 typedef enum mpls_lookup_next_t_
31 {
32     MPLS_LOOKUP_NEXT_DROP = 0,
33 } mpls_lookup_next_t;
34
35 /*
36  * Compute flow hash. 
37  * We'll use it to select which adjacency to use for this flow.  And other things.
38  */
39 always_inline u32
40 mpls_compute_flow_hash (const mpls_unicast_header_t * hdr,
41                         flow_hash_config_t flow_hash_config)
42 {
43     /*
44      * We need to byte swap so we use the numerical value. i.e. an odd label
45      * leads to an odd bucket. as opposed to a label above and below value X.
46      */
47     u8 next_label_is_entropy;
48     mpls_label_t ho_label;
49     u32 hash, value;
50
51     ho_label = clib_net_to_host_u32(hdr->label_exp_s_ttl);
52     hash = vnet_mpls_uc_get_label(ho_label);
53     next_label_is_entropy = 0;
54
55     while (MPLS_EOS != vnet_mpls_uc_get_s(ho_label))
56     {
57         hdr++;
58         ho_label = clib_net_to_host_u32(hdr->label_exp_s_ttl);
59         value = vnet_mpls_uc_get_label(ho_label);
60
61         if (1 == next_label_is_entropy)
62         {
63             /*
64              * The label is an entropy value, use it alone as the hash
65              */
66             return (ho_label);
67         }
68         if (MPLS_IETF_ENTROPY_LABEL == value)
69         {
70             /*
71              * we've met a label in the stack indicating that tha next
72              * label is an entropy value
73              */
74             next_label_is_entropy = 1;
75         }
76         else
77         {
78             /*
79              * XOR the label values in the stack together to
80              * build up the hash value
81              */
82             hash ^= value;
83         }
84     }
85
86     /*
87      * check the top nibble for v4 and v6
88      */
89     hdr++;
90
91     switch (((u8*)hdr)[0] >> 4)
92     {
93     case 4:
94         /* incorporate the v4 flow-hash */
95         hash ^= ip4_compute_flow_hash ((const ip4_header_t *)hdr,
96                                        IP_FLOW_HASH_DEFAULT);
97         break;
98     case 6:
99         /* incorporate the v6 flow-hash */
100         hash ^= ip6_compute_flow_hash ((const ip6_header_t *)hdr,
101                                        IP_FLOW_HASH_DEFAULT);
102         break;
103     default:
104         break;
105     }
106
107     return (hash);
108 }
109
110 #endif /* __MPLS_LOOKUP_H__ */