From 775f73c6baaf9bc2283e7ab9752c81984823be99 Mon Sep 17 00:00:00 2001 From: Neale Ranns Date: Thu, 20 Dec 2018 03:01:49 -0800 Subject: [PATCH] FIB: encode the label stack in the FIB path during table dump Change-Id: I28e8a99b980ad343a4209e673201791b91ceab4e Signed-off-by: Neale Ranns --- src/plugins/abf/abf_api.c | 2 +- src/vnet/bier/bier_api.c | 10 ++++++-- src/vnet/fib/fib_api.c | 58 +++++++++++++++++++++++++++++++++++++----- src/vnet/fib/fib_entry.c | 15 ++++++++++- src/vnet/fib/fib_path.c | 27 +++++++++++++++++--- src/vnet/fib/fib_path.h | 1 + src/vnet/fib/fib_path_ext.c | 9 ++++--- src/vnet/fib/fib_path_list.c | 28 +++++++++++++++++++-- src/vnet/fib/fib_path_list.h | 11 ++++++++ src/vnet/fib/fib_types.api | 1 + src/vnet/ip/ip_api.c | 2 ++ src/vnet/mfib/mfib_entry.c | 7 +++--- src/vnet/mfib/mfib_table.c | 11 ++++++++ src/vnet/mfib/mfib_table.h | 15 +++++++++++ src/vnet/mpls/mpls_api.c | 3 ++- test/test_mpls.py | 8 +++++- test/vpp_ip_route.py | 60 ++++++++++++++++++++++++++++++++++++++------ 17 files changed, 236 insertions(+), 32 deletions(-) diff --git a/src/plugins/abf/abf_api.c b/src/plugins/abf/abf_api.c index 0bf714bff89..bf2566901c4 100644 --- a/src/plugins/abf/abf_api.c +++ b/src/plugins/abf/abf_api.c @@ -185,7 +185,7 @@ abf_policy_send_details (u32 api, void *args) mp->policy.acl_index = htonl (ap->ap_acl); mp->policy.policy_id = htonl (ap->ap_id); - fib_path_list_walk (ap->ap_pl, fib_path_encode, &api_rpaths); + fib_path_list_walk_w_ext (ap->ap_pl, NULL, fib_path_encode, &api_rpaths); fp = mp->policy.paths; vec_foreach (api_rpath, api_rpaths) diff --git a/src/vnet/bier/bier_api.c b/src/vnet/bier/bier_api.c index ed1e35f5b24..d8248b1b2bd 100644 --- a/src/vnet/bier/bier_api.c +++ b/src/vnet/bier/bier_api.c @@ -264,7 +264,10 @@ send_bier_route_details (const bier_table_t *bt, mp->br_bp = htons(be->be_bp); mp->br_n_paths = htonl(n_paths); - fib_path_list_walk(be->be_path_list, fib_path_encode, &api_rpaths); + fib_path_list_walk_w_ext(be->be_path_list, + NULL, + fib_path_encode, + &api_rpaths); fp = mp->br_paths; vec_foreach (api_rpath, api_rpaths) @@ -625,7 +628,10 @@ send_bier_disp_entry_details (const bier_disp_table_t *bdt, mp->bde_payload_proto = pproto; mp->bde_bp = htons(bp); - fib_path_list_walk(pl, fib_path_encode, &api_rpaths); + fib_path_list_walk_w_ext(pl, + NULL, + fib_path_encode, + &api_rpaths); fp = mp->bde_paths; vec_foreach (api_rpath, api_rpaths) diff --git a/src/vnet/fib/fib_api.c b/src/vnet/fib/fib_api.c index d46b9e23b04..98f92c3e73f 100644 --- a/src/vnet/fib/fib_api.c +++ b/src/vnet/fib/fib_api.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -207,6 +208,8 @@ void fib_api_path_encode (const fib_route_path_encode_t * api_rpath, vl_api_fib_path_t *out) { + int ii; + clib_memset (out, 0, sizeof (*out)); switch (api_rpath->dpo.dpoi_type) { @@ -246,12 +249,20 @@ fib_api_path_encode (const fib_route_path_encode_t * api_rpath, if ((DPO_PROTO_IP6 == api_rpath->rpath.frp_proto) || (DPO_PROTO_IP4 == api_rpath->rpath.frp_proto)) { - fib_table_t *fib; - - fib = fib_table_get (api_rpath->rpath.frp_fib_index, - dpo_proto_to_fib(api_rpath->rpath.frp_proto)); - - out->table_id = htonl (fib->ft_table_id); + if (api_rpath->rpath.frp_flags & FIB_ROUTE_PATH_RPF_ID) + { + out->table_id = + htonl(mfib_table_get_table_id( + api_rpath->rpath.frp_fib_index, + dpo_proto_to_fib(api_rpath->rpath.frp_proto))); + } + else + { + out->table_id = + htonl(fib_table_get_table_id( + api_rpath->rpath.frp_fib_index, + dpo_proto_to_fib(api_rpath->rpath.frp_proto))); + } } } @@ -264,6 +275,41 @@ fib_api_path_encode (const fib_route_path_encode_t * api_rpath, out->is_udp_encap = 1; out->next_hop_id = api_rpath->rpath.frp_udp_encap_id; } + if (api_rpath->rpath.frp_flags & FIB_ROUTE_PATH_INTF_RX) + { + out->is_interface_rx = 1; + } + if (api_rpath->rpath.frp_flags & FIB_ROUTE_PATH_LOCAL) + { + out->is_local = 1; + } + if (api_rpath->rpath.frp_flags & FIB_ROUTE_PATH_RESOLVE_VIA_HOST) + { + out->is_resolve_host = 1; + } + if (api_rpath->rpath.frp_flags & FIB_ROUTE_PATH_RESOLVE_VIA_ATTACHED) + { + out->is_resolve_attached = 1; + } + /* if (api_rpath->rpath.frp_flags & FIB_ROUTE_PATH_ATTACHED) { */ + /* out->is_attached = 1; */ + /* } */ + /* if (api_rpath->rpath.frp_flags & FIB_ROUTE_PATH_CONNECTED) { */ + /* out->is_connected = 1; */ + /* } */ + if (api_rpath->rpath.frp_label_stack) + { + for (ii = 0; ii < vec_len(api_rpath->rpath.frp_label_stack); ii++) + { + out->label_stack[ii].label = + htonl(api_rpath->rpath.frp_label_stack[ii].fml_value); + out->label_stack[ii].ttl = + api_rpath->rpath.frp_label_stack[ii].fml_ttl; + out->label_stack[ii].exp = + api_rpath->rpath.frp_label_stack[ii].fml_exp; + } + out->n_labels = ii; + } } fib_protocol_t diff --git a/src/vnet/fib/fib_entry.c b/src/vnet/fib/fib_entry.c index eaedc504d48..32e45f24453 100644 --- a/src/vnet/fib/fib_entry.c +++ b/src/vnet/fib/fib_entry.c @@ -1652,12 +1652,25 @@ void fib_entry_encode (fib_node_index_t fib_entry_index, fib_route_path_encode_t **api_rpaths) { + fib_path_ext_list_t *ext_list; fib_entry_t *fib_entry; + fib_entry_src_t *bsrc; + ext_list = NULL; fib_entry = fib_entry_get(fib_entry_index); + bsrc = fib_entry_get_best_src_i(fib_entry); + + if (bsrc) + { + ext_list = &bsrc->fes_path_exts; + } + if (FIB_NODE_INDEX_INVALID != fib_entry->fe_parent) { - fib_path_list_walk(fib_entry->fe_parent, fib_path_encode, api_rpaths); + fib_path_list_walk_w_ext(fib_entry->fe_parent, + ext_list, + fib_path_encode, + api_rpaths); } } diff --git a/src/vnet/fib/fib_path.c b/src/vnet/fib/fib_path.c index f528c67677f..d4a701d417c 100644 --- a/src/vnet/fib/fib_path.c +++ b/src/vnet/fib/fib_path.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -605,10 +606,14 @@ format_fib_path (u8 * s, va_list * args) vnm, path->dvr.fp_interface)); break; + case FIB_PATH_TYPE_DEAG: + s = format (s, " %sfib-index:%d", + (path->fp_cfg_flags & FIB_PATH_CFG_FLAG_RPF_ID ? "m" : ""), + path->deag.fp_tbl_id); + break; case FIB_PATH_TYPE_RECEIVE: case FIB_PATH_TYPE_INTF_RX: case FIB_PATH_TYPE_SPECIAL: - case FIB_PATH_TYPE_DEAG: case FIB_PATH_TYPE_EXCLUSIVE: if (dpo_id_is_valid(&path->fp_dpo)) { @@ -2609,7 +2614,8 @@ fib_path_is_looped (fib_node_index_t path_index) fib_path_list_walk_rc_t fib_path_encode (fib_node_index_t path_list_index, - fib_node_index_t path_index, + fib_node_index_t path_index, + const fib_path_ext_t *path_ext, void *ctx) { fib_route_path_encode_t **api_rpaths = ctx; @@ -2628,7 +2634,7 @@ fib_path_encode (fib_node_index_t path_list_index, api_rpath->dpo = path->fp_dpo; switch (path->fp_type) - { + { case FIB_PATH_TYPE_RECEIVE: api_rpath->rpath.frp_addr = path->receive.fp_addr; api_rpath->rpath.frp_sw_if_index = path->receive.fp_interface; @@ -2647,6 +2653,10 @@ fib_path_encode (fib_node_index_t path_list_index, break; case FIB_PATH_TYPE_DEAG: api_rpath->rpath.frp_fib_index = path->deag.fp_tbl_id; + if (path->fp_cfg_flags & FIB_PATH_CFG_FLAG_RPF_ID) + { + api_rpath->rpath.frp_flags |= FIB_ROUTE_PATH_RPF_ID; + } break; case FIB_PATH_TYPE_RECURSIVE: api_rpath->rpath.frp_addr = path->recursive.fp_nh.fp_ip; @@ -2660,9 +2670,18 @@ fib_path_encode (fib_node_index_t path_list_index, api_rpath->rpath.frp_udp_encap_id = path->udp_encap.fp_udp_encap_id; api_rpath->rpath.frp_flags |= FIB_ROUTE_PATH_UDP_ENCAP; break; + case FIB_PATH_TYPE_INTF_RX: + api_rpath->rpath.frp_sw_if_index = path->receive.fp_interface; + api_rpath->rpath.frp_flags |= FIB_ROUTE_PATH_INTF_RX; + break; default: break; - } + } + + if (path_ext && path_ext->fpe_type == FIB_PATH_EXT_MPLS) + { + api_rpath->rpath.frp_label_stack = path_ext->fpe_path.frp_label_stack; + } return (FIB_PATH_LIST_WALK_CONTINUE); } diff --git a/src/vnet/fib/fib_path.h b/src/vnet/fib/fib_path.h index e162f4dad3a..57dec6d90b4 100644 --- a/src/vnet/fib/fib_path.h +++ b/src/vnet/fib/fib_path.h @@ -183,6 +183,7 @@ extern u32 fib_path_get_rpf_id(fib_node_index_t path_index); extern void fib_path_module_init(void); extern fib_path_list_walk_rc_t fib_path_encode(fib_node_index_t path_list_index, fib_node_index_t path_index, + const struct fib_path_ext_t_ *ext_list, void *ctx); #endif diff --git a/src/vnet/fib/fib_path_ext.c b/src/vnet/fib/fib_path_ext.c index 5ecf3a91672..209b6273a85 100644 --- a/src/vnet/fib/fib_path_ext.c +++ b/src/vnet/fib/fib_path_ext.c @@ -328,11 +328,14 @@ fib_path_ext_list_find_by_path_index (const fib_path_ext_list_t *list, { fib_path_ext_t *path_ext; - vec_foreach(path_ext, list->fpel_exts) + if (NULL != list) { - if (path_ext->fpe_path_index == path_index) + vec_foreach(path_ext, list->fpel_exts) { - return (path_ext); + if (path_ext->fpe_path_index == path_index) + { + return (path_ext); + } } } return (NULL); diff --git a/src/vnet/fib/fib_path_list.c b/src/vnet/fib/fib_path_list.c index 568886af143..4e110fba9f0 100644 --- a/src/vnet/fib/fib_path_list.c +++ b/src/vnet/fib/fib_path_list.c @@ -24,6 +24,7 @@ #include #include #include +#include /** * The magic number of child entries that make a path-list popular. @@ -722,7 +723,7 @@ fib_path_list_create (fib_path_list_flags_t flags, if (FIB_NODE_INDEX_INVALID != old_path_list_index) { fib_path_list_destroy(path_list); - + path_list_index = old_path_list_index; } else @@ -747,7 +748,7 @@ fib_path_list_create (fib_path_list_flags_t flags, return (path_list_index); } -static fib_path_cfg_flags_t +static fib_path_cfg_flags_t fib_path_list_flags_2_path_flags (fib_path_list_flags_t plf) { fib_path_cfg_flags_t pf = FIB_PATH_CFG_FLAG_NONE; @@ -1343,6 +1344,29 @@ fib_path_list_walk (fib_node_index_t path_list_index, } } +void +fib_path_list_walk_w_ext (fib_node_index_t path_list_index, + const fib_path_ext_list_t *ext_list, + fib_path_list_walk_w_ext_fn_t func, + void *ctx) +{ + fib_node_index_t *path_index; + fib_path_list_t *path_list; + fib_path_ext_t *path_ext; + + path_list = fib_path_list_get(path_list_index); + + vec_foreach(path_index, path_list->fpl_paths) + { + path_ext = fib_path_ext_list_find_by_path_index(ext_list, *path_index); + + if (FIB_PATH_LIST_WALK_STOP == func(path_list_index, + *path_index, + path_ext, + ctx)) + break; + } +} void fib_path_list_module_init (void) diff --git a/src/vnet/fib/fib_path_list.h b/src/vnet/fib/fib_path_list.h index 18835a60282..380eb1a6864 100644 --- a/src/vnet/fib/fib_path_list.h +++ b/src/vnet/fib/fib_path_list.h @@ -183,6 +183,17 @@ extern void fib_path_list_walk(fib_node_index_t pl_index, fib_path_list_walk_fn_t func, void *ctx); +typedef fib_path_list_walk_rc_t (*fib_path_list_walk_w_ext_fn_t)( + fib_node_index_t pl_index, + fib_node_index_t path_index, + const struct fib_path_ext_t_ *ext_list, + void *ctx); + +extern void fib_path_list_walk_w_ext(fib_node_index_t pl_index, + const fib_path_ext_list_t *ext_list, + fib_path_list_walk_w_ext_fn_t func, + void *ctx); + extern void fib_path_list_module_init(void); extern void fib_path_list_module_init(void); diff --git a/src/vnet/fib/fib_types.api b/src/vnet/fib/fib_types.api index d946ed7889d..8268870c0a7 100644 --- a/src/vnet/fib/fib_types.api +++ b/src/vnet/fib/fib_types.api @@ -59,6 +59,7 @@ typeonly define fib_path u8 is_resolve_attached; u8 is_dvr; u8 is_source_lookup; + u8 is_interface_rx; u8 afi; u8 next_hop[16]; u32 next_hop_id; diff --git a/src/vnet/ip/ip_api.c b/src/vnet/ip/ip_api.c index 5a2aa60b057..d59aa23d7e5 100644 --- a/src/vnet/ip/ip_api.c +++ b/src/vnet/ip/ip_api.c @@ -810,6 +810,8 @@ add_del_route_t_handler (u8 is_multipath, path.frp_local_label = next_hop_via_label; path.frp_eos = MPLS_NON_EOS; } + if (is_local) + path_flags |= FIB_ROUTE_PATH_LOCAL; if (is_dvr) path_flags |= FIB_ROUTE_PATH_DVR; if (is_resolve_host) diff --git a/src/vnet/mfib/mfib_entry.c b/src/vnet/mfib/mfib_entry.c index 51d775dd295..ac37665fb72 100644 --- a/src/vnet/mfib/mfib_entry.c +++ b/src/vnet/mfib/mfib_entry.c @@ -1324,9 +1324,10 @@ mfib_entry_encode (fib_node_index_t mfib_entry_index, if (FIB_NODE_INDEX_INVALID != bsrc->mfes_pl) { - fib_path_list_walk(bsrc->mfes_pl, - fib_path_encode, - api_rpaths); + fib_path_list_walk_w_ext(bsrc->mfes_pl, + NULL, + fib_path_encode, + api_rpaths); } } diff --git a/src/vnet/mfib/mfib_table.c b/src/vnet/mfib/mfib_table.c index 8ae4a784684..68154b37ff8 100644 --- a/src/vnet/mfib/mfib_table.c +++ b/src/vnet/mfib/mfib_table.c @@ -489,6 +489,17 @@ mfib_table_get_index_for_sw_if_index (fib_protocol_t proto, return (~0); } +u32 +mfib_table_get_table_id (u32 fib_index, + fib_protocol_t proto) +{ + mfib_table_t *mfib_table; + + mfib_table = mfib_table_get(fib_index, proto); + + return ((NULL != mfib_table ? mfib_table->mft_table_id : ~0)); +} + u32 mfib_table_find (fib_protocol_t proto, u32 table_id) diff --git a/src/vnet/mfib/mfib_table.h b/src/vnet/mfib/mfib_table.h index 89f194f254e..6be4f798cd7 100644 --- a/src/vnet/mfib/mfib_table.h +++ b/src/vnet/mfib/mfib_table.h @@ -289,6 +289,21 @@ extern void mfib_table_flush(u32 fib_index, extern u32 mfib_table_get_index_for_sw_if_index(fib_protocol_t proto, u32 sw_if_index); +/** + * @brief + * Get the Table-ID of the FIB from protocol and index + * + * @param fib_index + * The FIB index + * + * @paran proto + * The protocol of the FIB (and thus the entries therein) + * + * @return fib_index + * The tableID of the FIB + */ +extern u32 mfib_table_get_table_id(u32 fib_index, fib_protocol_t proto); + /** * @brief * Get the index of the FIB for a Table-ID. This DOES NOT create the diff --git a/src/vnet/mpls/mpls_api.c b/src/vnet/mpls/mpls_api.c index 0f2ebb11bca..4ac5ea72821 100644 --- a/src/vnet/mpls/mpls_api.c +++ b/src/vnet/mpls/mpls_api.c @@ -459,7 +459,8 @@ send_mpls_tunnel_entry (u32 mti, void *arg) mp->mt_sw_if_index = ntohl (mt->mt_sw_if_index); mp->mt_count = ntohl (n); - fib_path_list_walk (mt->mt_path_list, fib_path_encode, &api_rpaths); + fib_path_list_walk_w_ext (mt->mt_path_list, + &mt->mt_path_exts, fib_path_encode, &api_rpaths); fp = mp->mt_paths; vec_foreach (api_rpath, api_rpaths) diff --git a/test/test_mpls.py b/test/test_mpls.py index ad2620b1b50..e7fb288f856 100644 --- a/test/test_mpls.py +++ b/test/test_mpls.py @@ -8,7 +8,7 @@ from vpp_ip import DpoProto from vpp_ip_route import VppIpRoute, VppRoutePath, VppMplsRoute, \ VppMplsIpBind, VppIpMRoute, VppMRoutePath, \ MRouteItfFlags, MRouteEntryFlags, VppIpTable, VppMplsTable, \ - VppMplsLabel, MplsLspMode + VppMplsLabel, MplsLspMode, find_mpls_route from vpp_mpls_tunnel_interface import VppMPLSTunnelInterface from scapy.packet import Raw @@ -379,6 +379,12 @@ class TestMPLS(VppTestCase): labels=[VppMplsLabel(33)])]) route_32_eos.add_vpp_config() + self.assertTrue( + find_mpls_route(self, 0, 32, 1, + [VppRoutePath(self.pg0.remote_ip4, + self.pg0.sw_if_index, + labels=[VppMplsLabel(33)])])) + # # a stream that matches the route for 10.0.0.1 # PG0 is in the default table diff --git a/test/vpp_ip_route.py b/test/vpp_ip_route.py index 45609e80786..5a6598eb012 100644 --- a/test/vpp_ip_route.py +++ b/test/vpp_ip_route.py @@ -78,6 +78,24 @@ def find_mroute(test, grp_addr, src_addr, grp_addr_len, return False +def find_mpls_route(test, table_id, label, eos_bit, paths=None): + dump = test.vapi.mpls_fib_dump() + for e in dump: + if label == e.label \ + and eos_bit == e.eos_bit \ + and table_id == e.table_id: + if not paths: + return True + else: + if (len(paths) != len(e.path)): + return False + for i in range(len(paths)): + if (paths[i] != e.path[i]): + return False + return True + return False + + def fib_interface_ip_prefix(test, address, length, sw_if_index): vp = VppIpPrefix(address, length) addrs = test.vapi.ip_address_dump(sw_if_index, is_ipv6=vp.is_ip6) @@ -225,6 +243,23 @@ class VppMplsLabel(object): 'exp': self.exp, 'is_uniform': is_uniform} + def __eq__(self, other): + if isinstance(other, self.__class__): + return (self.value == other.value and + self.ttl == other.ttl and + self.exp == other.exp and + self.mode == other.mode) + elif hasattr(other, 'label'): + return (self.value == other.label and + self.ttl == other.ttl and + self.exp == other.exp and + (self.mode == MplsLspMode.UNIFORM) == other.is_uniform) + else: + return False + + def __ne__(self, other): + return not (self == other) + class VppRoutePath(object): @@ -293,7 +328,21 @@ class VppRoutePath(object): 'label_stack': self.encode_labels()} def __eq__(self, other): - return self.nh_addr == other.nh_addr + if isinstance(other, self.__class__): + return self.nh_addr == other.nh_addr + elif hasattr(other, 'sw_if_index'): + # vl_api_fib_path_t + if (len(self.nh_labels) != other.n_labels): + return False + for i in range(len(self.nh_labels)): + if (self.nh_labels[i] != other.label_stack[i]): + return False + return self.nh_itf == other.sw_if_index + else: + return False + + def __ne__(self, other): + return not (self == other) class VppMRoutePath(VppRoutePath): @@ -725,13 +774,8 @@ class VppMplsRoute(VppObject): is_add=0) def query_vpp_config(self): - dump = self._test.vapi.mpls_fib_dump() - for e in dump: - if self.local_label == e.label \ - and self.eos_bit == e.eos_bit \ - and self.table_id == e.table_id: - return True - return False + return find_mpls_route(self._test, self.table_id, + self.local_label, self.eos_bit) def __str__(self): return self.object_id() -- 2.16.6