diff options
author | Neale Ranns <nranns@cisco.com> | 2017-04-05 08:11:14 -0700 |
---|---|---|
committer | Damjan Marion <dmarion.lists@gmail.com> | 2017-04-06 15:18:44 +0000 |
commit | 88fc83eb716bf07f4634de6de5b569f795a56418 (patch) | |
tree | 4c8037b62cb6a57209aef4e28ae273d0ba4e40e7 /src/vnet/adj/adj_delegate.c | |
parent | 5ee51f8ed616f14f3b32ae8857d383fefa02d861 (diff) |
BFD-FIB interactions
- single-hop BFD: attach a delegate to the appropriate adjacency
- multi-hop BFD [not supported yet]: attach a delegate to the FIB entry.
adjacency/fib_entry state tracks the BFD session state. when the state is down the object does not contribute forwarding hence and hence dependent objects will not use it.
For example, if a route is ECMP via two adjacencies and one of them is BFD down, then only the other is used to forward (i.e. we don't drop half the traffic).
Change-Id: I0ef53e20e73b067001a132cd0a3045408811a822
Signed-off-by: Neale Ranns <nranns@cisco.com>
Diffstat (limited to 'src/vnet/adj/adj_delegate.c')
-rw-r--r-- | src/vnet/adj/adj_delegate.c | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/src/vnet/adj/adj_delegate.c b/src/vnet/adj/adj_delegate.c new file mode 100644 index 00000000000..701b36e2fd9 --- /dev/null +++ b/src/vnet/adj/adj_delegate.c @@ -0,0 +1,144 @@ +/* + * 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.h> +#include <vnet/adj/adj_internal.h> + +static adj_delegate_t * +adj_delegate_find_i (const ip_adjacency_t *adj, + adj_delegate_type_t type, + u32 *index) +{ + adj_delegate_t *delegate; + int ii; + + ii = 0; + vec_foreach(delegate, adj->ia_delegates) + { + if (delegate->ad_type == type) + { + if (NULL != index) + *index = ii; + + return (delegate); + } + else + { + ii++; + } + } + + return (NULL); +} + +adj_delegate_t * +adj_delegate_get (const ip_adjacency_t *adj, + adj_delegate_type_t type) +{ + return (adj_delegate_find_i(adj, type, NULL)); +} + +void +adj_delegate_remove (ip_adjacency_t *adj, + adj_delegate_type_t type) +{ + adj_delegate_t *aed; + u32 index = ~0; + + aed = adj_delegate_find_i(adj, type, &index); + + ASSERT(NULL != aed); + + vec_del1(adj->ia_delegates, index); +} + +static int +adj_delegate_cmp_for_sort (void * v1, + void * v2) +{ + adj_delegate_t *delegate1 = v1, *delegate2 = v2; + + return (delegate1->ad_type - delegate2->ad_type); +} + +static void +adj_delegate_init (ip_adjacency_t *adj, + adj_delegate_type_t type) + +{ + adj_delegate_t delegate = { + .ad_adj_index = adj_get_index(adj), + .ad_type = type, + }; + + vec_add1(adj->ia_delegates, delegate); + vec_sort_with_function(adj->ia_delegates, + adj_delegate_cmp_for_sort); +} + +adj_delegate_t * +adj_delegate_find_or_add (ip_adjacency_t *adj, + adj_delegate_type_t adt) +{ + adj_delegate_t *delegate; + + delegate = adj_delegate_get(adj, adt); + + if (NULL == delegate) + { + adj_delegate_init(adj, adt); + } + + return (adj_delegate_get(adj, adt)); +} + +/** + * typedef for printing a delegate + */ +typedef u8 * (*adj_delegate_format_t)(const adj_delegate_t *aed, + u8 *s); + +/** + * Print a delegate that represents BFD tracking + */ +static u8 * +adj_delegate_fmt_bfd (const adj_delegate_t *aed, + u8 *s) +{ + s = format(s, "BFD:[state:%d index:%d]", + aed->ad_bfd_state, + aed->ad_bfd_index); + + return (s); +} + +/** + * A delegate type to formatter map + */ +static adj_delegate_format_t aed_formatters[] = +{ + [ADJ_DELEGATE_BFD] = adj_delegate_fmt_bfd, +}; + +u8 * +format_adj_deletegate (u8 * s, va_list * args) +{ + adj_delegate_t *aed; + + aed = va_arg (*args, adj_delegate_t *); + + return (aed_formatters[aed->ad_type](aed, s)); +} |