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