diff options
Diffstat (limited to 'src/vnet/adj')
-rw-r--r-- | src/vnet/adj/adj.c | 30 | ||||
-rw-r--r-- | src/vnet/adj/adj_delegate.c | 2 | ||||
-rw-r--r-- | src/vnet/adj/adj_delegate.h | 6 | ||||
-rw-r--r-- | src/vnet/adj/adj_midchain.h | 21 | ||||
-rw-r--r-- | src/vnet/adj/adj_midchain_delegate.c | 183 |
5 files changed, 237 insertions, 5 deletions
diff --git a/src/vnet/adj/adj.c b/src/vnet/adj/adj.c index 3ca3d6015f9..9d18dbf2727 100644 --- a/src/vnet/adj/adj.c +++ b/src/vnet/adj/adj.c @@ -537,10 +537,32 @@ static fib_node_back_walk_rc_t adj_back_walk_notify (fib_node_t *node, fib_node_back_walk_ctx_t *ctx) { - /* - * Que pasa. yo soj en el final! - */ - ASSERT(0); + ip_adjacency_t *adj; + + adj = ADJ_FROM_NODE(node); + + switch (adj->lookup_next_index) + { + case IP_LOOKUP_NEXT_MIDCHAIN: + adj_midchain_delegate_restack(adj_get_index(adj)); + break; + case IP_LOOKUP_NEXT_ARP: + case IP_LOOKUP_NEXT_REWRITE: + case IP_LOOKUP_NEXT_BCAST: + case IP_LOOKUP_NEXT_GLEAN: + case IP_LOOKUP_NEXT_MCAST: + case IP_LOOKUP_NEXT_MCAST_MIDCHAIN: + case IP_LOOKUP_NEXT_DROP: + case IP_LOOKUP_NEXT_PUNT: + case IP_LOOKUP_NEXT_LOCAL: + case IP_LOOKUP_NEXT_ICMP_ERROR: + case IP_LOOKUP_N_NEXT: + /* + * Que pasa. yo soj en el final! + */ + ASSERT(0); + break; + } return (FIB_NODE_BACK_WALK_CONTINUE); } diff --git a/src/vnet/adj/adj_delegate.c b/src/vnet/adj/adj_delegate.c index 15dcb02afaa..cd5301c1e77 100644 --- a/src/vnet/adj/adj_delegate.c +++ b/src/vnet/adj/adj_delegate.c @@ -25,7 +25,7 @@ static adj_delegate_vft_t *ad_vfts; /** * The value of the last dynamically allocated delegeate value */ -static adj_delegate_type_t ad_max_id = ADJ_DELEGATE_BFD; +static adj_delegate_type_t ad_max_id = ADJ_DELEGATE_LAST; static adj_delegate_t * adj_delegate_find_i (const ip_adjacency_t *adj, diff --git a/src/vnet/adj/adj_delegate.h b/src/vnet/adj/adj_delegate.h index 13bf911c5a6..f6da245bb52 100644 --- a/src/vnet/adj/adj_delegate.h +++ b/src/vnet/adj/adj_delegate.h @@ -36,8 +36,14 @@ typedef enum adj_delegate_type_t_ { * BFD session state */ ADJ_DELEGATE_BFD, + /** + * Stacking of a midchain's nexthop + */ + ADJ_DELEGATE_MIDCHAIN, } adj_delegate_type_t; +#define ADJ_DELEGATE_LAST (ADJ_DELEGATE_MIDCHAIN) + /** * Adj delegate. This object is attached to the adjacency. */ diff --git a/src/vnet/adj/adj_midchain.h b/src/vnet/adj/adj_midchain.h index 24fea427a6b..1f5deaecd95 100644 --- a/src/vnet/adj/adj_midchain.h +++ b/src/vnet/adj/adj_midchain.h @@ -118,4 +118,25 @@ extern void adj_midchain_module_init(void); */ extern u8* format_adj_midchain(u8* s, va_list *ap); +/** + * @brief + * create/attach a midchain delegate and stack it on the prefix passed + * @param ai - the index of the adjacency to stack + * @param fib_index - The FIB index of the prefix on which to stack + * @param pfx - The prefix on which to stack + */ +extern void adj_midchain_delegate_stack(adj_index_t ai, + u32 fib_index, + const fib_prefix_t *pfx); + +/** + * @brief restack a midchain delegate + */ +extern void adj_midchain_delegate_restack(adj_index_t ai); + +/** + * @brief unstack a midchain delegate (this stacks it on a drop) + */ +extern void adj_midchain_delegate_unstack(adj_index_t ai); + #endif diff --git a/src/vnet/adj/adj_midchain_delegate.c b/src/vnet/adj/adj_midchain_delegate.c new file mode 100644 index 00000000000..922283e92cf --- /dev/null +++ b/src/vnet/adj/adj_midchain_delegate.c @@ -0,0 +1,183 @@ +/* + * 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. + */ + +#include <vnet/adj/adj_delegate.h> +#include <vnet/adj/adj_midchain.h> +#include <vnet/fib/fib_table.h> + +/** + * Midchain stacker delegate + */ +typedef struct adj_midchain_delegate_t_ +{ + /** + * the Fib Entry we are stacked on + */ + fib_node_index_t amd_fei; + + /** + * The sibling entry on the FIB entry + */ + u32 amd_sibling; +} adj_midchain_delegate_t; + +/** + * Pool of delegates + */ +static adj_midchain_delegate_t *amd_pool; + +static inline const adj_midchain_delegate_t* +adj_midchain_from_const_base (const adj_delegate_t *ad) +{ + if (NULL != ad) + { + return (pool_elt_at_index(amd_pool, ad->ad_index)); + } + return (NULL); +} + +static void +adj_midchain_delegate_restack_i (adj_index_t ai, + adj_midchain_delegate_t *amd) +{ + if (vnet_sw_interface_is_admin_up (vnet_get_main (), + adj_get_sw_if_index(ai)) && + (FIB_NODE_INDEX_INVALID != amd->amd_fei)) + { + const fib_prefix_t *pfx; + + pfx = fib_entry_get_prefix(amd->amd_fei); + + adj_nbr_midchain_stack_on_fib_entry ( + ai, + amd->amd_fei, + fib_forw_chain_type_from_fib_proto(pfx->fp_proto)); + } + else + { + adj_nbr_midchain_unstack (ai); + } +} + +void +adj_midchain_delegate_restack (adj_index_t ai) +{ + adj_midchain_delegate_t *amd; + ip_adjacency_t *adj; + adj_delegate_t *ad; + + /* + * if there's a delegate already use that + */ + adj = adj_get(ai); + ad = adj_delegate_get(adj, ADJ_DELEGATE_MIDCHAIN); + + if (NULL != ad) + { + amd = pool_elt_at_index(amd_pool, ad->ad_index); + + adj_midchain_delegate_restack_i(ai, amd); + } + /* + * else + * nothing to stack + */ +} + +void +adj_midchain_delegate_stack (adj_index_t ai, + u32 fib_index, + const fib_prefix_t *pfx) +{ + adj_midchain_delegate_t *amd; + ip_adjacency_t *adj; + adj_delegate_t *ad; + + /* + * if there's a delegate already use that + */ + adj = adj_get(ai); + ad = adj_delegate_get(adj, ADJ_DELEGATE_MIDCHAIN); + + if (NULL != ad) + { + amd = pool_elt_at_index(amd_pool, ad->ad_index); + } + else + { + pool_get(amd_pool, amd); + amd->amd_fei = FIB_NODE_INDEX_INVALID; + adj_delegate_add(adj, ADJ_DELEGATE_MIDCHAIN, amd - amd_pool); + + amd->amd_fei = fib_table_entry_special_add(fib_index, + pfx, + FIB_SOURCE_RR, + FIB_ENTRY_FLAG_NONE); + amd->amd_sibling = fib_entry_child_add(amd->amd_fei, + FIB_NODE_TYPE_ADJ, + ai); + } + adj_midchain_delegate_restack_i(ai, amd); +} + +void +adj_midchain_delegate_unstack (adj_index_t ai) +{ + adj_nbr_midchain_unstack(ai); +} + +static void +adj_midchain_delegate_adj_deleted (adj_delegate_t *ad) +{ + adj_midchain_delegate_t *amd; + + amd = pool_elt_at_index(amd_pool, ad->ad_index); + + fib_entry_child_remove (amd->amd_fei, amd->amd_sibling); + fib_table_entry_delete_index (amd->amd_fei, FIB_SOURCE_RR); + + pool_put(amd_pool, amd); +} + +/** + * Print a delegate that represents MIDCHAIN tracking + */ +static u8 * +adj_midchain_delegate_fmt (const adj_delegate_t *aed, u8 *s) +{ + const adj_midchain_delegate_t *amd = adj_midchain_from_const_base(aed); + + s = format(s, "MIDCHAIN:[fib-entry:%d]", amd->amd_fei); + + return (s); +} + +const static adj_delegate_vft_t adj_delegate_vft = { + .adv_format = adj_midchain_delegate_fmt, + .adv_adj_deleted = adj_midchain_delegate_adj_deleted, +}; + +static clib_error_t * +adj_midchain_delegate_module_init (vlib_main_t * vm) +{ + clib_error_t * error = NULL; + + adj_delegate_register_type (ADJ_DELEGATE_MIDCHAIN, &adj_delegate_vft); + + return (error); +} + +VLIB_INIT_FUNCTION (adj_midchain_delegate_module_init); + |