summaryrefslogtreecommitdiffstats
path: root/src/vnet/bier/bier_entry.h
blob: 629e47a859a6a063ec2178ef4a8047ace4846185 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
/*
 * 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.
 */
/**
 * bier_entry : The BIER entry
 *
 * The interface to the BIER entry is through a bier_entry_t* rather
 * than an index. This is becuase the BIER table allocates the entries
 * in a contiguous array once and only once when the table is created.
 * this is done for forwarding performance. The entry is thus not subject
 * to realloc, and does not need to be malloc'd when a route to that
 * bit-position is first learned.
 *
 */

#ifndef __BIER_ENTRY_H__
#define __BIER_ENTRY_H__

#include <vlib/vlib.h>
#include <vnet/fib/fib_node.h>
#include <vnet/bier/bier_types.h>

/**
 * Forward declarations
 */
struct bier_route_update_t_;
struct bier_fmask_db_t_;

/**
 * The BIER entry
 *
 * the BIER entry is the representation of a BIER forwarding egress router (BFER)
 * (or the egress PE) that is assigned a bit position.
 */
typedef struct bier_entry_t_ {
    /**
     * linkage into the FIB graph
     */
    fib_node_t be_node;

    /**
     * The index of the BIER table in which this entry resides
     */
    index_t be_bti;

    /**
     * the bit position this entry represents.
     *  this is the key table insertion
     */
    bier_bp_t be_bp;

    /**
     * the FIB path-list this entry resolves through.
     * the path-list is itself resoved on the entry's fmasks
     */
    fib_node_index_t be_path_list;
    /**
     * sibling index on the path list
     */
    fib_node_index_t be_sibling_index;
} bier_entry_t;

extern index_t bier_entry_create(index_t bti,
                                 bier_bp_t bp);
extern void bier_entry_delete(index_t bei);

extern void bier_entry_path_update (index_t bei,
                                    const fib_route_path_t *rpaths);

extern void bier_entry_path_add(index_t bei,
                                const fib_route_path_t *brp);

extern int bier_entry_path_remove(index_t bei,
                                  const fib_route_path_t *brp);

extern u8* format_bier_entry(u8* s, va_list *ap);

extern void bier_entry_contribute_forwarding(index_t bei,
                                             dpo_id_t *dpo);

extern bier_entry_t *bier_entry_pool;
always_inline bier_entry_t* bier_entry_get(index_t bei)
{
    return (&bier_entry_pool[bei]);
}
#endif
ss="n">fib_path_list_create_special( proto, fib_entry_src_flags_2_path_list_flags(flags), dpo); } static void fib_entry_src_interface_remove (fib_entry_src_t *src) { src->fes_pl = FIB_NODE_INDEX_INVALID; } static void fib_entry_src_interface_path_swap (fib_entry_src_t *src, const fib_entry_t *entry, fib_path_list_flags_t pl_flags, const fib_route_path_t *paths) { fib_node_index_t fib_entry_index; ip_adjacency_t *adj; fib_entry_index = fib_entry_get_index(entry); src->fes_pl = fib_path_list_create(pl_flags, paths); /* * this is a hack to get the entry's prefix into the glean adjacency * so that it is available for fast retrieval in the switch path. */ if (!(FIB_ENTRY_FLAG_LOCAL & src->fes_entry_flags)) { adj_index_t ai; ai = fib_path_list_get_adj(src->fes_pl, fib_entry_get_default_chain_type( fib_entry_get(fib_entry_index))); if (INDEX_INVALID != ai) { adj = adj_get(ai); if (IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index) { /* * the connected prefix will link to a glean on a non-p2p * u.interface. */ adj->sub_type.glean.receive_addr = entry->fe_prefix.fp_addr; } } } } /* * Source activate. * Called when the source is teh new longer best source on the entry */ static int fib_entry_src_interface_activate (fib_entry_src_t *src, const fib_entry_t *fib_entry) { fib_entry_t *cover; if (FIB_ENTRY_FLAG_LOCAL & src->fes_entry_flags) { /* * Track the covering attached/connected cover. This is so that * during an attached export of the cover, this local prefix is * also exported */ src->u.interface.fesi_cover = fib_table_get_less_specific(fib_entry->fe_fib_index, &fib_entry->fe_prefix); ASSERT(FIB_NODE_INDEX_INVALID != src->u.interface.fesi_cover); cover = fib_entry_get(src->u.interface.fesi_cover); src->u.interface.fesi_sibling = fib_entry_cover_track(cover, fib_entry_get_index(fib_entry)); } return (!0); } /* * Source Deactivate. * Called when the source is no longer best source on the entry */ static void fib_entry_src_interface_deactivate (fib_entry_src_t *src, const fib_entry_t *fib_entry) { fib_entry_t *cover; /* * remove the dependency on the covering entry */ if (FIB_NODE_INDEX_INVALID != src->u.interface.fesi_cover) { cover = fib_entry_get(src->u.interface.fesi_cover); fib_entry_cover_untrack(cover, src->u.interface.fesi_sibling); src->u.interface.fesi_cover = FIB_NODE_INDEX_INVALID; } } static fib_entry_src_cover_res_t fib_entry_src_interface_cover_change (fib_entry_src_t *src, const fib_entry_t *fib_entry) { fib_entry_src_cover_res_t res = { .install = !0, .bw_reason = FIB_NODE_BW_REASON_FLAG_NONE, }; if (FIB_NODE_INDEX_INVALID == src->u.interface.fesi_cover) { /* * not tracking the cover. surprised we got poked? */ return (res); } /* * this function is called when this entry's cover has a more specific * entry inserted benaeth it. That does not necessarily mean that this * entry is covered by the new prefix. check that */ if (src->u.interface.fesi_cover != fib_table_get_less_specific(fib_entry->fe_fib_index, &fib_entry->fe_prefix)) { fib_entry_src_interface_deactivate(src, fib_entry); fib_entry_src_interface_activate(src, fib_entry); } return (res); } static void fib_entry_src_interface_installed (fib_entry_src_t *src, const fib_entry_t *fib_entry) { /* * The interface source now rules! poke our cover to get exported */ fib_entry_t *cover; if (FIB_NODE_INDEX_INVALID != src->u.interface.fesi_cover) { cover = fib_entry_get(src->u.interface.fesi_cover); fib_attached_export_covered_added(cover, fib_entry_get_index(fib_entry)); } } static u8* fib_entry_src_interface_format (fib_entry_src_t *src, u8* s) { return (format(s, " cover:%d", src->u.interface.fesi_cover)); } const static fib_entry_src_vft_t interface_src_vft = { .fesv_init = fib_entry_src_interface_init, .fesv_add = fib_entry_src_interface_add, .fesv_remove = fib_entry_src_interface_remove, .fesv_path_swap = fib_entry_src_interface_path_swap, .fesv_activate = fib_entry_src_interface_activate, .fesv_deactivate = fib_entry_src_interface_deactivate, .fesv_format = fib_entry_src_interface_format, .fesv_installed = fib_entry_src_interface_installed, .fesv_cover_change = fib_entry_src_interface_cover_change, /* * not concerned about updates to the cover. the cover will * decide to export or not */ }; void fib_entry_src_interface_register (void) { fib_entry_src_behaviour_register(FIB_SOURCE_BH_INTERFACE, &interface_src_vft); }