MPLS lookup DPO does not pop the label (nor does it handle replicate)
[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  * Compute flow hash. 
29  * We'll use it to select which adjacency to use for this flow.  And other things.
30  */
31 always_inline u32
32 mpls_compute_flow_hash (const mpls_unicast_header_t * hdr,
33                         flow_hash_config_t flow_hash_config)
34 {
35     /*
36      * We need to byte swap so we use the numerical value. i.e. an odd label
37      * leads to an odd bucket. as opposed to a label above and below value X.
38      */
39     u8 next_label_is_entropy;
40     mpls_label_t ho_label;
41     u32 hash, value;
42
43     ho_label = clib_net_to_host_u32(hdr->label_exp_s_ttl);
44     hash = vnet_mpls_uc_get_label(ho_label);
45     next_label_is_entropy = 0;
46
47     while (MPLS_EOS != vnet_mpls_uc_get_s(ho_label))
48     {
49         hdr++;
50         ho_label = clib_net_to_host_u32(hdr->label_exp_s_ttl);
51         value = vnet_mpls_uc_get_label(ho_label);
52
53         if (1 == next_label_is_entropy)
54         {
55             /*
56              * The label is an entropy value, use it alone as the hash
57              */
58             return (ho_label);
59         }
60         if (MPLS_IETF_ENTROPY_LABEL == value)
61         {
62             /*
63              * we've met a label in the stack indicating that tha next
64              * label is an entropy value
65              */
66             next_label_is_entropy = 1;
67         }
68         else
69         {
70             /*
71              * XOR the label values in the stack together to
72              * build up the hash value
73              */
74             hash ^= value;
75         }
76     }
77
78     /*
79      * check the top nibble for v4 and v6
80      */
81     hdr++;
82
83     switch (((u8*)hdr)[0] >> 4)
84     {
85     case 4:
86         /* incorporate the v4 flow-hash */
87         hash ^= ip4_compute_flow_hash ((const ip4_header_t *)hdr,
88                                        IP_FLOW_HASH_DEFAULT);
89         break;
90     case 6:
91         /* incorporate the v6 flow-hash */
92         hash ^= ip6_compute_flow_hash ((const ip6_header_t *)hdr,
93                                        IP_FLOW_HASH_DEFAULT);
94         break;
95     default:
96         break;
97     }
98
99     return (hash);
100 }
101
102 #endif /* __MPLS_LOOKUP_H__ */