diff options
Diffstat (limited to 'src/vnet/fib/fib_urpf_list.h')
-rw-r--r-- | src/vnet/fib/fib_urpf_list.h | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/src/vnet/fib/fib_urpf_list.h b/src/vnet/fib/fib_urpf_list.h new file mode 100644 index 00000000000..09f475747cf --- /dev/null +++ b/src/vnet/fib/fib_urpf_list.h @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @brief A unicast RPF list. + * The uRPF list is the set of interfaces that a prefix can be reached through. + * There are 3 levels of RPF check: + * - do we have any route to the source (i.e. it's not drop) + * - did the packet arrive on an interface that the source is reachable through + * - did the packet arrive from a peer that the source is reachable through + * we don't support the last. But it could be done by storing adjs in the uPRF + * list rather than interface indices. + * + * these conditions are checked against the list by: + * - the list is not empty + * - there is an interface in the list that is on the input interface. + * - there is an adj in the list whose MAC address matches the packet's + * source MAC and input interface. + * + * To speed the last two checks the interface list only needs to have the unique + * interfaces present. If the uRPF check was instead implemented by forward + * walking the DPO chain, then that walk would encounter a great deal of + * non-adjacency objects (i.e. load-balances, mpls-labels, etc) and potentially + * the same adjacency many times (esp. when UCMP is used). + * To that end the uRPF list is a collapsed, unique interface only list. + */ + +#ifndef __FIB_URPF_LIST_H__ +#define __FIB_URPF_LIST_H__ + +#include <vnet/fib/fib_types.h> +#include <vnet/adj/adj.h> + +/** + * @brief flags + */ +typedef enum fib_urpf_list_flag_t_ +{ + /** + * @brief Set to indicated that the uRPF list has already been baked. + * This is protection against it being baked more than once. These + * are not chunky fries - once is enough. + */ + FIB_URPF_LIST_BAKED = (1 << 0), +} fib_urpf_list_flag_t; + +typedef struct fib_urpf_list_t_ +{ + /** + * The list of interfaces that comprise the allowed accepting interfaces + */ + adj_index_t *furpf_itfs; + + /** + * flags + */ + fib_urpf_list_flag_t furpf_flags; + + /** + * uRPF lists are shared amongst many entries so we require a locking + * mechanism. + */ + u32 furpf_locks; +} fib_urpf_list_t; + +extern index_t fib_urpf_list_alloc_and_lock(void); +extern void fib_urpf_list_unlock(index_t urpf); +extern void fib_urpf_list_lock(index_t urpf); + +extern void fib_urpf_list_append(index_t urpf, adj_index_t adj); +extern void fib_urpf_list_combine(index_t urpf1, index_t urpf2); + +extern void fib_urpf_list_bake(index_t urpf); + +extern u8 *format_fib_urpf_list(u8 *s, va_list ap); + +extern void fib_urpf_list_show_mem(void); + +/** + * @brief pool of all fib_urpf_list + */ +extern fib_urpf_list_t *fib_urpf_list_pool; + +static inline fib_urpf_list_t * +fib_urpf_list_get (index_t index) +{ + return (pool_elt_at_index(fib_urpf_list_pool, index)); +} + +/** + * @brief Data-Plane function to check an input interface against an uRPF list + * + * @param ui The uRPF list index to check against. Get this from the load-balance + * object that is the result of the FIB lookup + * @param sw_if_index The SW interface index to validate + * + * @return 1 if the interface is found, 0 otherwise + */ +always_inline int +fib_urpf_check (index_t ui, u32 sw_if_index) +{ + fib_urpf_list_t *urpf; + u32 *swi; + + urpf = fib_urpf_list_get(ui); + + vec_foreach(swi, urpf->furpf_itfs) + { + if (*swi == sw_if_index) + return (1); + } + + return (0); +} + +/** + * @brief Data-Plane function to check the size of an uRPF list, (i.e. the number + * of interfaces in the list). + * + * @param ui The uRPF list index to check against. Get this from the load-balance + * object that is the result of the FIB lookup + * + * @return the number of interfaces in the list + */ +always_inline int +fib_urpf_check_size (index_t ui) +{ + fib_urpf_list_t *urpf; + + urpf = fib_urpf_list_get(ui); + + return (vec_len(urpf->furpf_itfs)); +} + +#endif |