Line data Source code
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 : * @brief A unicast RPF list. 17 : * The uRPF list is the set of interfaces that a prefix can be reached through. 18 : * There are 3 levels of RPF check: 19 : * - do we have any route to the source (i.e. it's not drop) 20 : * - did the packet arrive on an interface that the source is reachable through 21 : * - did the packet arrive from a peer that the source is reachable through 22 : * we don't support the last. But it could be done by storing adjs in the uPRF 23 : * list rather than interface indices. 24 : * 25 : * these conditions are checked against the list by: 26 : * - the list is not empty 27 : * - there is an interface in the list that is on the input interface. 28 : * - there is an adj in the list whose MAC address matches the packet's 29 : * source MAC and input interface. 30 : * 31 : * To speed the last two checks the interface list only needs to have the unique 32 : * interfaces present. If the uRPF check was instead implemented by forward 33 : * walking the DPO chain, then that walk would encounter a great deal of 34 : * non-adjacency objects (i.e. load-balances, mpls-labels, etc) and potentially 35 : * the same adjacency many times (esp. when UCMP is used). 36 : * To that end the uRPF list is a collapsed, unique interface only list. 37 : */ 38 : 39 : #ifndef __FIB_URPF_LIST_H__ 40 : #define __FIB_URPF_LIST_H__ 41 : 42 : #include <vnet/fib/fib_types.h> 43 : #include <vnet/adj/adj.h> 44 : 45 : /** 46 : * @brief flags 47 : */ 48 : typedef enum fib_urpf_list_flag_t_ 49 : { 50 : /** 51 : * @brief Set to indicated that the uRPF list has already been baked. 52 : * This is protection against it being baked more than once. These 53 : * are not chunky fries - once is enough. 54 : */ 55 : FIB_URPF_LIST_BAKED = (1 << 0), 56 : } fib_urpf_list_flag_t; 57 : 58 : typedef struct fib_urpf_list_t_ 59 : { 60 : /** 61 : * The list of interfaces that comprise the allowed accepting interfaces 62 : */ 63 : adj_index_t *furpf_itfs; 64 : 65 : /** 66 : * flags 67 : */ 68 : fib_urpf_list_flag_t furpf_flags; 69 : 70 : /** 71 : * uRPF lists are shared amongst many entries so we require a locking 72 : * mechanism. 73 : */ 74 : u32 furpf_locks; 75 : } fib_urpf_list_t; 76 : 77 : extern index_t fib_urpf_list_alloc_and_lock(void); 78 : extern void fib_urpf_list_unlock(index_t urpf); 79 : extern void fib_urpf_list_lock(index_t urpf); 80 : 81 : extern void fib_urpf_list_append(index_t urpf, adj_index_t adj); 82 : extern void fib_urpf_list_combine(index_t urpf1, index_t urpf2); 83 : 84 : extern void fib_urpf_list_bake(index_t urpf); 85 : 86 : extern u8 *format_fib_urpf_list(u8 *s, va_list *ap); 87 : 88 : extern void fib_urpf_list_show_mem(void); 89 : 90 : /** 91 : * @brief pool of all fib_urpf_list 92 : */ 93 : extern fib_urpf_list_t *fib_urpf_list_pool; 94 : 95 : static inline fib_urpf_list_t * 96 524801 : fib_urpf_list_get (index_t index) 97 : { 98 524801 : return (pool_elt_at_index(fib_urpf_list_pool, index)); 99 : } 100 : 101 : /** 102 : * @brief Data-Plane function to check an input interface against an uRPF list 103 : * 104 : * @param ui The uRPF list index to check against. Get this from the load-balance 105 : * object that is the result of the FIB lookup 106 : * @param sw_if_index The SW interface index to validate 107 : * 108 : * @return 1 if the interface is found, 0 otherwise 109 : */ 110 : always_inline int 111 901 : fib_urpf_check (index_t ui, u32 sw_if_index) 112 : { 113 : fib_urpf_list_t *urpf; 114 : u32 *swi; 115 : 116 901 : urpf = fib_urpf_list_get(ui); 117 : 118 1288 : vec_foreach(swi, urpf->furpf_itfs) 119 : { 120 656 : if (*swi == sw_if_index) 121 269 : return (1); 122 : } 123 : 124 632 : return (0); 125 : } 126 : 127 : /** 128 : * @brief Data-Plane function to check the size of an uRPF list, (i.e. the number 129 : * of interfaces in the list). 130 : * 131 : * @param ui The uRPF list index to check against. Get this from the load-balance 132 : * object that is the result of the FIB lookup 133 : * 134 : * @return the number of interfaces in the list 135 : */ 136 : always_inline int 137 117415 : fib_urpf_check_size (index_t ui) 138 : { 139 : fib_urpf_list_t *urpf; 140 : 141 117415 : urpf = fib_urpf_list_get(ui); 142 : 143 117415 : return (vec_len(urpf->furpf_itfs)); 144 : } 145 : 146 : #endif