diff options
Diffstat (limited to 'src/vnet')
44 files changed, 2080 insertions, 2067 deletions
diff --git a/src/vnet/CMakeLists.txt b/src/vnet/CMakeLists.txt index 1d7d4988002..5465d717f8c 100644 --- a/src/vnet/CMakeLists.txt +++ b/src/vnet/CMakeLists.txt @@ -1455,6 +1455,7 @@ list(APPEND VNET_SOURCES mfib/mfib_forward.c mfib/ip4_mfib.c mfib/ip6_mfib.c + mfib/mfib_api.c mfib/mfib_types.c mfib/mfib_signal.c mfib/mfib_itf.c diff --git a/src/vnet/api_errno.h b/src/vnet/api_errno.h index be42086e668..8771d2c1a88 100644 --- a/src/vnet/api_errno.h +++ b/src/vnet/api_errno.h @@ -44,7 +44,7 @@ _(FEATURE_DISABLED, -30, "Feature disabled by configuration") \ _(INVALID_REGISTRATION, -31, "Invalid registration") \ _(NEXT_HOP_NOT_IN_FIB, -50, "Next hop not in FIB") \ _(UNKNOWN_DESTINATION, -51, "Unknown destination") \ -_(PREFIX_MATCHES_NEXT_HOP, -52, "Prefix matches next hop") \ +_(NO_PATHS_IN_ROUTE, -52, "No paths specified in route") \ _(NEXT_HOP_NOT_FOUND_MP, -53, "Next hop not found (multipath)") \ _(NO_MATCHING_INTERFACE, -54, "No matching interface for probe") \ _(INVALID_VLAN, -55, "Invalid VLAN") \ @@ -148,7 +148,8 @@ _(BD_ALREADY_HAS_BVI, -152, "Bridge domain already has a BVI interface") \ _(INVALID_PROTOCOL, -153, "Invalid Protocol") \ _(INVALID_ALGORITHM, -154, "Invalid Algorithm") \ _(RSRC_IN_USE, -155, "Resource In Use") \ -_(KEY_LENGTH, -156, "invalid Key Length") +_(KEY_LENGTH, -156, "invalid Key Length") \ +_(FIB_PATH_UNSUPPORTED_NH_PROTO, -157, "Unsupported FIB Path protocol") typedef enum { diff --git a/src/vnet/bier/bier.api b/src/vnet/bier/bier.api index b5ac8cabd39..0cc56cab50a 100644 --- a/src/vnet/bier/bier.api +++ b/src/vnet/bier/bier.api @@ -1,3 +1,4 @@ +/* Hey Emacs use -*- mode: C -*- */ /* * Copyright (c) 2016 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,7 +19,7 @@ This file defines vpp BIER control-plane API messages which are generally called through a shared memory interface. */ -option version = "1.1.0"; +option version = "1.2.0"; import "vnet/fib/fib_types.api"; /** \brief BIER Table Identifier @@ -77,16 +78,21 @@ define bier_table_details @param br_n_paths - The number of paths @param br_paths - The array of paths */ +typedef bier_route +{ + u32 br_bp; + vl_api_bier_table_id_t br_tbl_id; + u8 br_n_paths; + vl_api_fib_path_t br_paths[br_n_paths]; +}; + autoreply define bier_route_add_del { u32 client_index; u32 context; - u32 br_bp; u8 br_is_add; u8 br_is_replace; - vl_api_bier_table_id_t br_tbl_id; - u8 br_n_paths; - vl_api_fib_path_t br_paths[br_n_paths]; + vl_api_bier_route_t br_route; }; define bier_route_dump @@ -99,10 +105,7 @@ define bier_route_dump define bier_route_details { u32 context; - u16 br_bp; - vl_api_bier_table_id_t br_tbl_id; - u32 br_n_paths; - vl_api_fib_path_t br_paths[br_n_paths]; + vl_api_bier_route_t br_route; }; /** \brief BIER Imposition Add diff --git a/src/vnet/bier/bier_api.c b/src/vnet/bier/bier_api.c index d8248b1b2bd..66f6b422810 100644 --- a/src/vnet/bier/bier_api.c +++ b/src/vnet/bier/bier_api.c @@ -169,10 +169,10 @@ vl_api_bier_route_add_del_t_handler (vl_api_bier_route_add_del_t * mp) vnm = vnet_get_main (); vnm->api_errno = 0; - bp = ntohl(mp->br_bp); + bp = ntohl(mp->br_route.br_bp); brpaths = NULL; - if (mp->br_tbl_id.bt_hdr_len_id >= BIER_HDR_LEN_2048) + if (mp->br_route.br_tbl_id.bt_hdr_len_id >= BIER_HDR_LEN_2048) { rv = VNET_API_ERROR_BIER_BSL_UNSUP; goto done; @@ -184,19 +184,19 @@ vl_api_bier_route_add_del_t_handler (vl_api_bier_route_add_del_t * mp) } bier_table_id_t bti = { - .bti_set = mp->br_tbl_id.bt_set, - .bti_sub_domain = mp->br_tbl_id.bt_sub_domain, - .bti_hdr_len = mp->br_tbl_id.bt_hdr_len_id, + .bti_set = mp->br_route.br_tbl_id.bt_set, + .bti_sub_domain = mp->br_route.br_tbl_id.bt_sub_domain, + .bti_hdr_len = mp->br_route.br_tbl_id.bt_hdr_len_id, .bti_type = BIER_TABLE_MPLS_SPF, .bti_ecmp = BIER_ECMP_TABLE_ID_MAIN, }; - vec_validate(brpaths, mp->br_n_paths - 1); + vec_validate(brpaths, mp->br_route.br_n_paths - 1); vec_foreach_index(ii, brpaths) { brpath = &brpaths[ii]; - rv = fib_path_api_parse(&mp->br_paths[ii], brpath); + rv = fib_api_path_decode(&mp->br_route.br_paths[ii], brpath); if (0 != rv) { @@ -242,9 +242,12 @@ send_bier_route_details (const bier_table_t *bt, const bier_entry_t *be, void *args) { - fib_route_path_encode_t *api_rpaths = NULL, *api_rpath; bier_route_details_walk_t *ctx = args; vl_api_bier_route_details_t *mp; + fib_path_encode_ctx_t path_ctx = { + .rpaths = NULL, + }; + fib_route_path_t *rpath; vl_api_fib_path_t *fp; u32 n_paths, m_size; @@ -258,24 +261,25 @@ send_bier_route_details (const bier_table_t *bt, mp->_vl_msg_id = ntohs(VL_API_BIER_ROUTE_DETAILS); mp->context = ctx->context; - mp->br_tbl_id.bt_set = bt->bt_id.bti_set; - mp->br_tbl_id.bt_sub_domain = bt->bt_id.bti_sub_domain; - mp->br_tbl_id.bt_hdr_len_id = bt->bt_id.bti_hdr_len; - mp->br_bp = htons(be->be_bp); - mp->br_n_paths = htonl(n_paths); + mp->br_route.br_tbl_id.bt_set = bt->bt_id.bti_set; + mp->br_route.br_tbl_id.bt_sub_domain = bt->bt_id.bti_sub_domain; + mp->br_route.br_tbl_id.bt_hdr_len_id = bt->bt_id.bti_hdr_len; + mp->br_route.br_bp = htonl(be->be_bp); + mp->br_route.br_n_paths = htonl(n_paths); fib_path_list_walk_w_ext(be->be_path_list, NULL, fib_path_encode, - &api_rpaths); + &path_ctx); - fp = mp->br_paths; - vec_foreach (api_rpath, api_rpaths) + fp = mp->br_route.br_paths; + vec_foreach (rpath, path_ctx.rpaths) { - fib_api_path_encode(api_rpath, fp); + fib_api_path_encode(rpath, fp); fp++; } + vec_free(path_ctx.rpaths); vl_api_send_msg (ctx->reg, (u8 *) mp); } @@ -506,16 +510,16 @@ vl_api_bier_disp_entry_add_del_t_handler (vl_api_bier_disp_entry_add_del_t * mp) brp->frp_rpf_id = ntohl(mp->bde_paths[ii].rpf_id); } - if (0 == mp->bde_paths[ii].afi) + if (FIB_API_PATH_NH_PROTO_IP4 == mp->bde_paths[ii].proto) { - clib_memcpy_fast (&brp->frp_addr.ip4, - mp->bde_paths[ii].next_hop, + clib_memcpy (&brp->frp_addr.ip4, + &mp->bde_paths[ii].nh.address.ip4, sizeof (brp->frp_addr.ip4)); } - else + else if (FIB_API_PATH_NH_PROTO_IP6 == mp->bde_paths[ii].proto) { - clib_memcpy_fast (&brp->frp_addr.ip6, - mp->bde_paths[ii].next_hop, + clib_memcpy (&brp->frp_addr.ip6, + &mp->bde_paths[ii].nh.address.ip6, sizeof (brp->frp_addr.ip6)); } if (ip46_address_is_zero(&brp->frp_addr)) @@ -601,7 +605,6 @@ send_bier_disp_entry_details (const bier_disp_table_t *bdt, u16 bp, void *args) { - fib_route_path_encode_t *api_rpaths = NULL, *api_rpath; bier_disp_entry_details_walk_t *ctx = args; vl_api_bier_disp_entry_details_t *mp; bier_hdr_proto_id_t pproto; @@ -611,8 +614,14 @@ send_bier_disp_entry_details (const bier_disp_table_t *bdt, FOR_EACH_BIER_HDR_PROTO(pproto) { fib_node_index_t pl = bde->bde_pl[pproto]; + if (INDEX_INVALID != pl) { + fib_path_encode_ctx_t path_ctx = { + .rpaths = NULL, + }; + fib_route_path_t *rpath; + n_paths = fib_path_list_get_n_paths(pl); m_size = sizeof(*mp) + (n_paths * sizeof(vl_api_fib_path_t)); mp = vl_msg_api_alloc(m_size); @@ -631,16 +640,17 @@ send_bier_disp_entry_details (const bier_disp_table_t *bdt, fib_path_list_walk_w_ext(pl, NULL, fib_path_encode, - &api_rpaths); + &path_ctx); fp = mp->bde_paths; - vec_foreach (api_rpath, api_rpaths) + vec_foreach (rpath, path_ctx.rpaths) { - fib_api_path_encode(api_rpath, fp); + fib_api_path_encode(rpath, fp); fp++; } vl_api_send_msg (ctx->reg, (u8 *) mp); + vec_free(path_ctx.rpaths); } } } diff --git a/src/vnet/bier/bier_entry.c b/src/vnet/bier/bier_entry.c index 77d96b80782..e8bf722d88f 100644 --- a/src/vnet/bier/bier_entry.c +++ b/src/vnet/bier/bier_entry.c @@ -147,7 +147,7 @@ bier_entry_delete (index_t bei) be = bier_entry_get(bei); /* - * if we still ahve a path-list, unlink from it + * if we still have a path-list, unlink from it */ if (FIB_NODE_INDEX_INVALID != be->be_path_list) { diff --git a/src/vnet/bier/bier_fmask.c b/src/vnet/bier/bier_fmask.c index b6169d3c4bb..a58a77ff281 100644 --- a/src/vnet/bier/bier_fmask.c +++ b/src/vnet/bier/bier_fmask.c @@ -404,7 +404,7 @@ bier_fmask_get_stats (index_t bfmi, u64 * packets, u64 * bytes) void bier_fmask_encode (index_t bfmi, bier_table_id_t *btid, - fib_route_path_encode_t *rpath) + fib_route_path_t *rpath) { bier_fmask_t *bfm; @@ -413,17 +413,17 @@ bier_fmask_encode (index_t bfmi, clib_memset(rpath, 0, sizeof(*rpath)); - rpath->rpath.frp_sw_if_index = ~0; + rpath->frp_sw_if_index = ~0; switch (bfm->bfm_id->bfmi_nh_type) { case BIER_NH_UDP: - rpath->rpath.frp_flags = FIB_ROUTE_PATH_UDP_ENCAP; - rpath->rpath.frp_udp_encap_id = bfm->bfm_id->bfmi_id; + rpath->frp_flags = FIB_ROUTE_PATH_UDP_ENCAP; + rpath->frp_udp_encap_id = bfm->bfm_id->bfmi_id; break; case BIER_NH_IP: - memcpy(&rpath->rpath.frp_addr, &bfm->bfm_id->bfmi_nh, - sizeof(rpath->rpath.frp_addr)); + memcpy(&rpath->frp_addr, &bfm->bfm_id->bfmi_nh, + sizeof(rpath->frp_addr)); break; } } diff --git a/src/vnet/bier/bier_fmask.h b/src/vnet/bier/bier_fmask.h index e522b0350e7..87845bb031b 100644 --- a/src/vnet/bier/bier_fmask.h +++ b/src/vnet/bier/bier_fmask.h @@ -166,7 +166,7 @@ extern void bier_fmask_child_remove (fib_node_index_t fib_entry_index, extern void bier_fmask_get_stats (index_t bfmi, u64 * packets, u64 * bytes); extern void bier_fmask_encode (index_t bfmi, bier_table_id_t *btid, - fib_route_path_encode_t *rpath); + fib_route_path_t *rpath); /* * provided for fast data-path access diff --git a/src/vnet/bier/bier_table.c b/src/vnet/bier/bier_table.c index a9f8a6d338f..0e8cc1e88b4 100644 --- a/src/vnet/bier/bier_table.c +++ b/src/vnet/bier/bier_table.c @@ -779,9 +779,12 @@ bier_table_ecmp_walk (index_t bti, bt = bier_table_get(bti); - fib_path_list_walk(bt->bt_pl, - bier_table_ecmp_walk_path_list, - &ewc); + if (FIB_NODE_INDEX_INVALID != bt->bt_pl) + { + fib_path_list_walk(bt->bt_pl, + bier_table_ecmp_walk_path_list, + &ewc); + } } void diff --git a/src/vnet/dhcp/dhcp6_proxy_node.c b/src/vnet/dhcp/dhcp6_proxy_node.c index a199b7a34e4..a253fa1959f 100644 --- a/src/vnet/dhcp/dhcp6_proxy_node.c +++ b/src/vnet/dhcp/dhcp6_proxy_node.c @@ -893,16 +893,16 @@ dhcp6_proxy_set_server (ip46_address_t * addr, .frp_addr = zero_addr, .frp_sw_if_index = 0xffffffff, .frp_fib_index = ~0, - .frp_weight = 0, + .frp_weight = 1, .frp_flags = FIB_ROUTE_PATH_LOCAL, + .frp_mitf_flags = MFIB_ITF_FLAG_FORWARD, }; if (dhcp_proxy_server_add (FIB_PROTOCOL_IP6, addr, src_addr, rx_fib_index, server_table_id)) { mfib_table_entry_path_update (rx_fib_index, &all_dhcp_servers, - MFIB_SOURCE_DHCP, - &path_for_us, MFIB_ITF_FLAG_FORWARD); + MFIB_SOURCE_DHCP, &path_for_us); /* * Each interface that is enabled in this table, needs to be added * as an accepting interface, but this is not easily doable in VPP. diff --git a/src/vnet/dpo/mpls_disposition.c b/src/vnet/dpo/mpls_disposition.c index cf0b5fcf1ef..7bc2cb65f87 100644 --- a/src/vnet/dpo/mpls_disposition.c +++ b/src/vnet/dpo/mpls_disposition.c @@ -88,8 +88,12 @@ format_mpls_disp_dpo (u8 *s, va_list *args) mdd = mpls_disp_dpo_get(index); - s = format(s, "mpls-disposition:[%d]:[%U, %U]", - index, + s = format(s, "mpls-disposition:[%d]:[", index); + + if (0 != mdd->mdd_rpf_id) + s = format(s, "rpf-id:%d ", mdd->mdd_rpf_id); + + s = format(s, "%U, %U]", format_dpo_proto, mdd->mdd_payload_proto, format_fib_mpls_lsp_mode, mdd->mdd_mode); @@ -132,7 +136,9 @@ mpls_disp_dpo_unlock (dpo_id_t *dpo) */ typedef struct mpls_label_disposition_trace_t_ { - index_t mdd; + dpo_proto_t mddt_payload_proto; + fib_rpf_id_t mddt_rpf_id; + fib_mpls_lsp_mode_t mddt_mode; } mpls_label_disposition_trace_t; extern vlib_node_registration_t ip4_mpls_label_disposition_pipe_node; @@ -293,13 +299,17 @@ mpls_label_disposition_inline (vlib_main_t * vm, mpls_label_disposition_trace_t *tr = vlib_add_trace(vm, node, b0, sizeof(*tr)); - tr->mdd = mddi0; + tr->mddt_payload_proto = mdd0->mdd_payload_proto; + tr->mddt_rpf_id = mdd0->mdd_rpf_id; + tr->mddt_mode = mdd0->mdd_mode; } if (PREDICT_FALSE(b1->flags & VLIB_BUFFER_IS_TRACED)) { mpls_label_disposition_trace_t *tr = vlib_add_trace(vm, node, b1, sizeof(*tr)); - tr->mdd = mddi1; + tr->mddt_payload_proto = mdd1->mdd_payload_proto; + tr->mddt_rpf_id = mdd1->mdd_rpf_id; + tr->mddt_mode = mdd1->mdd_mode; } vlib_validate_buffer_enqueue_x2(vm, node, next_index, to_next, @@ -383,7 +393,9 @@ mpls_label_disposition_inline (vlib_main_t * vm, { mpls_label_disposition_trace_t *tr = vlib_add_trace(vm, node, b0, sizeof(*tr)); - tr->mdd = mddi0; + tr->mddt_payload_proto = mdd0->mdd_payload_proto; + tr->mddt_rpf_id = mdd0->mdd_rpf_id; + tr->mddt_mode = mdd0->mdd_mode; } vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, @@ -403,7 +415,11 @@ format_mpls_label_disposition_trace (u8 * s, va_list * args) t = va_arg(*args, mpls_label_disposition_trace_t *); - s = format(s, "disp:%d", t->mdd); + s = format(s, "rpf-id:%d %U, %U", + t->mddt_rpf_id, + format_dpo_proto, t->mddt_payload_proto, + format_fib_mpls_lsp_mode, t->mddt_mode); + return (s); } diff --git a/src/vnet/fib/fib_api.c b/src/vnet/fib/fib_api.c index 12c4f0de13f..5aa5c4ec875 100644 --- a/src/vnet/fib/fib_api.c +++ b/src/vnet/fib/fib_api.c @@ -16,10 +16,11 @@ #include <vnet/vnet.h> #include <vlibmemory/api.h> #include <vnet/fib/fib_api.h> +#include <vnet/ip/ip_types_api.h> #include <vnet/fib/fib_table.h> #include <vnet/mfib/mfib_table.h> #include <vnet/bier/bier_disp_table.h> -#include <vnet/dpo/ip_null_dpo.h> +#include <vpp/api/types.h> #include <vnet/vnet_msg_enum.h> @@ -40,288 +41,485 @@ #include <vlibapi/api_helper_macros.h> int -fib_path_api_parse (const vl_api_fib_path_t *in, - fib_route_path_t *out) +fib_api_table_id_decode (fib_protocol_t fproto, + u32 table_id, + u32 *fib_index) { - fib_route_path_flags_t path_flags; - mpls_label_t next_hop_via_label; - int rv = 0, n_labels; - u8 ii; + *fib_index = fib_table_find(fproto, table_id); - path_flags = FIB_ROUTE_PATH_FLAG_NONE; - next_hop_via_label = ntohl (in->via_label); - clib_memset(out, 0, sizeof(*out)); - out->frp_sw_if_index = ~0; + if (INDEX_INVALID == *fib_index) + { + return VNET_API_ERROR_NO_SUCH_FIB; + } - out->frp_proto = in->afi; - // .frp_addr = (NULL == next_hop ? zero_addr : *next_hop), - out->frp_sw_if_index = ntohl(in->sw_if_index); - out->frp_weight = in->weight; - out->frp_preference = in->preference; + return (0); +} - if (DPO_PROTO_IP4 == out->frp_proto || - DPO_PROTO_IP6 == out->frp_proto || - DPO_PROTO_MPLS == out->frp_proto) - { - out->frp_fib_index = fib_table_find (dpo_proto_to_fib(out->frp_proto), - ntohl (in->table_id)); +int +fib_api_mtable_id_decode (fib_protocol_t fproto, + u32 table_id, + u32 *fib_index) +{ + *fib_index = mfib_table_find(fproto, table_id); - if (~0 == out->frp_fib_index) - return (VNET_API_ERROR_NO_SUCH_FIB); + if (~0 == *fib_index) + { + return VNET_API_ERROR_NO_SUCH_FIB; } - /* - * the special INVALID label means we are not recursing via a - * label. Exp-null value is never a valid via-label so that - * also means it's not a via-label and means clients that set - * it to 0 by default get the expected behaviour - */ - if ((MPLS_LABEL_INVALID != next_hop_via_label) && - (0 != next_hop_via_label)) + return (0); +} + +static void +fib_api_next_hop_decode (const vl_api_fib_path_t *in, + ip46_address_t *out) +{ + if (in->proto == FIB_API_PATH_NH_PROTO_IP4) + memcpy (&out->ip4, &in->nh.address.ip4, sizeof (out->ip4)); + else if (in->proto == FIB_API_PATH_NH_PROTO_IP6) + memcpy (&out->ip6, &in->nh.address.ip6, sizeof (out->ip6)); +} + +static vl_api_fib_path_nh_proto_t +fib_api_path_dpo_proto_to_nh (dpo_proto_t dproto) +{ + switch (dproto) { - out->frp_proto = DPO_PROTO_MPLS; - out->frp_local_label = next_hop_via_label; - out->frp_eos = MPLS_NON_EOS; + case DPO_PROTO_IP4: + return (FIB_API_PATH_NH_PROTO_IP4); + case DPO_PROTO_IP6: + return (FIB_API_PATH_NH_PROTO_IP6); + case DPO_PROTO_MPLS: + return (FIB_API_PATH_NH_PROTO_MPLS); + case DPO_PROTO_BIER: + return (FIB_API_PATH_NH_PROTO_BIER); + case DPO_PROTO_ETHERNET: + return (FIB_API_PATH_NH_PROTO_ETHERNET); + case DPO_PROTO_NSH: + ASSERT(0); + break; } + return (FIB_API_PATH_NH_PROTO_IP4); +} - n_labels = in->n_labels; - if (n_labels == 0) - ; - else + +static void +fib_api_next_hop_encode (const fib_route_path_t *rpath, + vl_api_fib_path_t *fp) +{ + fp->proto = fib_api_path_dpo_proto_to_nh(rpath->frp_proto); + + if (rpath->frp_proto == DPO_PROTO_IP4) + memcpy (&fp->nh.address.ip4, + &rpath->frp_addr.ip4, + sizeof (rpath->frp_addr.ip4)); + else if (rpath->frp_proto == DPO_PROTO_IP6) + memcpy (&fp->nh.address.ip6, + &rpath->frp_addr.ip6, + sizeof (rpath->frp_addr.ip6)); +} + +static int +fib_api_path_nh_proto_to_dpo (vl_api_fib_path_nh_proto_t pp, + dpo_proto_t *dproto) +{ + switch (pp) { - vec_validate (out->frp_label_stack, n_labels - 1); - for (ii = 0; ii < n_labels; ii++) - { - out->frp_label_stack[ii].fml_value = - ntohl(in->label_stack[ii].label); - out->frp_label_stack[ii].fml_ttl = - in->label_stack[ii].ttl; - out->frp_label_stack[ii].fml_exp = - in->label_stack[ii].exp; - out->frp_label_stack[ii].fml_mode = - (in->label_stack[ii].is_uniform ? - FIB_MPLS_LSP_MODE_UNIFORM : - FIB_MPLS_LSP_MODE_PIPE); - } + case FIB_API_PATH_NH_PROTO_IP4: + *dproto = DPO_PROTO_IP4; + break; + case FIB_API_PATH_NH_PROTO_IP6: + *dproto = DPO_PROTO_IP6; + break; + case FIB_API_PATH_NH_PROTO_MPLS: + *dproto = DPO_PROTO_MPLS; + break; + case FIB_API_PATH_NH_PROTO_BIER: + *dproto = DPO_PROTO_BIER; + break; + case FIB_API_PATH_NH_PROTO_ETHERNET: + *dproto = DPO_PROTO_ETHERNET; + break; + default: + return (-1); } + return (0); +} + +int +fib_api_path_decode (vl_api_fib_path_t *in, + fib_route_path_t *out) +{ + vnet_classify_main_t *cm = &vnet_classify_main; + int rv = 0, n_labels; + vnet_main_t *vnm; + u8 ii; + + vnm = vnet_get_main (); + clib_memset(&out->frp_dpo, 0, sizeof(out->frp_dpo)); + + /* enums are u32 */ + in->flags = ntohl (in->flags); + in->type = ntohl (in->type); + in->proto = ntohl (in->proto); - if (in->is_dvr) - path_flags |= FIB_ROUTE_PATH_DVR; - if (in->is_resolve_host) - path_flags |= FIB_ROUTE_PATH_RESOLVE_VIA_HOST; - if (in->is_resolve_attached) - path_flags |= FIB_ROUTE_PATH_RESOLVE_VIA_ATTACHED; - /* if (in->is_interface_rx) */ - /* path_flags |= FIB_ROUTE_PATH_INTF_RX; */ - /* if (in->is_rpf_id) */ - /* path_flags |= FIB_ROUTE_PATH_RPF_ID; */ - if (in->is_source_lookup) - path_flags |= FIB_ROUTE_PATH_SOURCE_LOOKUP; - - if (in->is_udp_encap) + /* + * attributes that apply to all path types + */ + out->frp_flags = 0; + out->frp_weight = in->weight; + if (0 == out->frp_weight) { - path_flags |= FIB_ROUTE_PATH_UDP_ENCAP; - out->frp_udp_encap_id = ntohl(in->next_hop_id); + out->frp_weight = 1; } - else + out->frp_preference = in->preference; + + rv = fib_api_path_nh_proto_to_dpo(in->proto, &out->frp_proto); + + if (0 != rv) + return (rv); + + /* + * convert the flags and the AFI to determine the path type + */ + if (in->flags & FIB_API_PATH_FLAG_RESOLVE_VIA_HOST) + out->frp_flags |= FIB_ROUTE_PATH_RESOLVE_VIA_HOST; + if (in->flags & FIB_API_PATH_FLAG_RESOLVE_VIA_ATTACHED) + out->frp_flags |= FIB_ROUTE_PATH_RESOLVE_VIA_ATTACHED; + + switch (in->type) { - if (DPO_PROTO_IP4 == in->afi) - { - clib_memcpy (&out->frp_addr.ip4, - in->next_hop, - sizeof (out->frp_addr.ip4)); - } - else if (DPO_PROTO_IP6 == in->afi) + case FIB_API_PATH_TYPE_DVR: + out->frp_sw_if_index = ntohl(in->sw_if_index); + out->frp_flags |= FIB_ROUTE_PATH_DVR; + break; + case FIB_API_PATH_TYPE_INTERFACE_RX: + out->frp_sw_if_index = ntohl(in->sw_if_index); + out->frp_flags |= FIB_ROUTE_PATH_INTF_RX; + break; + case FIB_API_PATH_TYPE_DROP: + out->frp_flags |= FIB_ROUTE_PATH_DROP; + break; + case FIB_API_PATH_TYPE_LOCAL: + out->frp_flags |= FIB_ROUTE_PATH_LOCAL; + out->frp_sw_if_index = ntohl(in->sw_if_index); + break; + case FIB_API_PATH_TYPE_ICMP_UNREACH: + out->frp_flags |= FIB_ROUTE_PATH_ICMP_UNREACH; + break; + case FIB_API_PATH_TYPE_ICMP_PROHIBIT: + out->frp_flags |= FIB_ROUTE_PATH_ICMP_PROHIBIT; + break; + case FIB_API_PATH_TYPE_CLASSIFY: + out->frp_flags |= FIB_ROUTE_PATH_CLASSIFY; + + if (pool_is_free_index (cm->tables, ntohl (in->nh.classify_table_index))) { - clib_memcpy (&out->frp_addr.ip6, - in->next_hop, - sizeof (out->frp_addr.ip6)); + return VNET_API_ERROR_NO_SUCH_TABLE; } + out->frp_classify_table_id = ntohl (in->nh.classify_table_index); + break; + case FIB_API_PATH_TYPE_UDP_ENCAP: + out->frp_flags |= FIB_ROUTE_PATH_UDP_ENCAP; + out->frp_udp_encap_id = ntohl(in->nh.obj_id); + break; + case FIB_API_PATH_TYPE_BIER_IMP: + out->frp_flags |= FIB_ROUTE_PATH_BIER_IMP; + out->frp_bier_imp = ntohl (in->nh.obj_id); + break; - if (ip46_address_is_zero(&out->frp_addr)) + case FIB_API_PATH_TYPE_SOURCE_LOOKUP: + out->frp_flags |= FIB_ROUTE_PATH_SOURCE_LOOKUP; + /* fall through */ + case FIB_API_PATH_TYPE_NORMAL: + switch (out->frp_proto) { - if (DPO_PROTO_BIER == in->afi) + case DPO_PROTO_IP4: + case DPO_PROTO_IP6: + fib_api_next_hop_decode(in, &out->frp_addr); + out->frp_sw_if_index = ntohl(in->sw_if_index); + out->frp_rpf_id = ntohl(in->rpf_id); + + if (0 == out->frp_rpf_id) { - index_t bdti; + /* allow 0 to be an unset value on the API */ + out->frp_rpf_id = ~0; + } - bdti = bier_disp_table_find(ntohl(in->table_id)); + if (~0 != out->frp_rpf_id) + { + out->frp_flags |= FIB_ROUTE_PATH_RPF_ID; + } - if (INDEX_INVALID != bdti) + if (~0 == out->frp_sw_if_index) + { + /* recursive or deag, validate the next-hop FIB */ + if (~0 != out->frp_rpf_id) { - out->frp_fib_index = bdti; - out->frp_proto = DPO_PROTO_BIER; + rv = fib_api_mtable_id_decode( + dpo_proto_to_fib(out->frp_proto), + ntohl(in->table_id), + &out->frp_fib_index); } else { - rv = VNET_API_ERROR_NO_SUCH_FIB; + rv = fib_api_table_id_decode( + dpo_proto_to_fib(out->frp_proto), + ntohl(in->table_id), + &out->frp_fib_index); + } + if (0 != rv) + { + return (rv); } } - else if (out->frp_sw_if_index == ~0 && - out->frp_fib_index != ~0) + else { - path_flags |= FIB_ROUTE_PATH_DEAG; + if (pool_is_free_index (vnm->interface_main.sw_interfaces, + out->frp_sw_if_index)) + { + return VNET_API_ERROR_NO_MATCHING_INTERFACE; + } } - } - } - out->frp_flags = path_flags; + if (ip46_address_is_zero(&out->frp_addr)) + { + if (~0 == out->frp_sw_if_index && + ~0 != out->frp_fib_index) + { + out->frp_flags |= FIB_ROUTE_PATH_DEAG; + } + } - return (rv); -} + break; + case DPO_PROTO_MPLS: + out->frp_local_label = ntohl (in->nh.via_label); + out->frp_eos = MPLS_NON_EOS; + out->frp_sw_if_index = ~0; + break; + case DPO_PROTO_BIER: + out->frp_sw_if_index = ntohl(in->sw_if_index); + out->frp_rpf_id = ntohl(in->rpf_id); -void -fib_prefix_to_api (const fib_prefix_t *pfx, - u8 address[16], - u8 *length, - u8 *is_ip6) -{ - *length = pfx->fp_len; - *is_ip6 = (FIB_PROTOCOL_IP6 == pfx->fp_proto ? 1 : 0); + if (!(out->frp_flags & FIB_ROUTE_PATH_BIER_IMP)) + { + fib_api_next_hop_decode(in, &out->frp_addr); - if (FIB_PROTOCOL_IP6 == pfx->fp_proto) - { - memcpy (address, &pfx->fp_addr.ip6, sizeof (pfx->fp_addr.ip6)); - } - else - { - memcpy (address, &pfx->fp_addr.ip4, sizeof (pfx->fp_addr.ip4)); + if (ip46_address_is_zero(&out->frp_addr)) + { + index_t bdti; + + bdti = bier_disp_table_find(ntohl(in->table_id)); + + if (INDEX_INVALID != bdti) + { + out->frp_fib_index = bdti; + } + else + { + return (VNET_API_ERROR_NO_SUCH_FIB); + } + } + } + break; + case DPO_PROTO_ETHERNET: + out->frp_sw_if_index = ntohl(in->sw_if_index); + break; + case DPO_PROTO_NSH: + break; + } } -} -static void -fib_api_path_copy_next_hop (const fib_route_path_encode_t * api_rpath, void *fp_arg) -{ - int is_ip4; - vl_api_fib_path_t *fp = (vl_api_fib_path_t *) fp_arg; - - if (api_rpath->rpath.frp_proto == DPO_PROTO_IP4) - fp->afi = IP46_TYPE_IP4; - else if (api_rpath->rpath.frp_proto == DPO_PROTO_IP6) - fp->afi = IP46_TYPE_IP6; - else + n_labels = in->n_labels; + if (n_labels != 0) { - is_ip4 = ip46_address_is_ip4 (&api_rpath->rpath.frp_addr); - if (is_ip4) - fp->afi = IP46_TYPE_IP4; - else - fp->afi = IP46_TYPE_IP6; + vec_validate (out->frp_label_stack, n_labels - 1); + for (ii = 0; ii < n_labels; ii++) + { + out->frp_label_stack[ii].fml_value = + ntohl(in->label_stack[ii].label); + out->frp_label_stack[ii].fml_ttl = + in->label_stack[ii].ttl; + out->frp_label_stack[ii].fml_exp = + in->label_stack[ii].exp; + out->frp_label_stack[ii].fml_mode = + (in->label_stack[ii].is_uniform ? + FIB_MPLS_LSP_MODE_UNIFORM : + FIB_MPLS_LSP_MODE_PIPE); + } } - if (fp->afi == IP46_TYPE_IP4) - memcpy (fp->next_hop, &api_rpath->rpath.frp_addr.ip4, - sizeof (api_rpath->rpath.frp_addr.ip4)); - else - memcpy (fp->next_hop, &api_rpath->rpath.frp_addr.ip6, - sizeof (api_rpath->rpath.frp_addr.ip6)); + + return (0); } void -fib_api_path_encode (const fib_route_path_encode_t * api_rpath, +fib_api_path_encode (const fib_route_path_t * rpath, vl_api_fib_path_t *out) { - int ii; + memset (out, 0, sizeof (*out)); - clib_memset (out, 0, sizeof (*out)); - switch (api_rpath->dpo.dpoi_type) - { - case DPO_RECEIVE: - out->is_local = true; - break; - case DPO_DROP: - out->is_drop = true; - break; - case DPO_IP_NULL: - switch (ip_null_dpo_get_action(api_rpath->dpo.dpoi_index)) - { - case IP_NULL_ACTION_NONE: - out->is_drop = true; - break; - case IP_NULL_ACTION_SEND_ICMP_UNREACH: - out->is_unreach = true; - break; - case IP_NULL_ACTION_SEND_ICMP_PROHIBIT: - out->is_prohibit = true; - break; - default: - break; - } - break; - default: - break; - } - out->weight = api_rpath->rpath.frp_weight; - out->preference = api_rpath->rpath.frp_preference; - out->sw_if_index = htonl (api_rpath->rpath.frp_sw_if_index); - out->afi = api_rpath->rpath.frp_proto; - fib_api_path_copy_next_hop (api_rpath, out); + out->weight = rpath->frp_weight; + out->preference = rpath->frp_preference; + out->sw_if_index = htonl (rpath->frp_sw_if_index); + out->proto = fib_api_path_dpo_proto_to_nh(rpath->frp_proto); + out->rpf_id = rpath->frp_rpf_id; + fib_api_next_hop_encode (rpath, out); - if (0 != api_rpath->rpath.frp_fib_index) + if (0 != rpath->frp_fib_index) { - if ((DPO_PROTO_IP6 == api_rpath->rpath.frp_proto) || - (DPO_PROTO_IP4 == api_rpath->rpath.frp_proto)) + if ((DPO_PROTO_IP6 == rpath->frp_proto) || + (DPO_PROTO_IP4 == rpath->frp_proto)) { - if (api_rpath->rpath.frp_flags & FIB_ROUTE_PATH_RPF_ID) + if (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))); + out->table_id = htonl (mfib_table_get_table_id( + rpath->frp_fib_index, + dpo_proto_to_fib(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))); + out->table_id = htonl (fib_table_get_table_id( + rpath->frp_fib_index, + dpo_proto_to_fib(rpath->frp_proto))); } } } - if (api_rpath->rpath.frp_flags & FIB_ROUTE_PATH_DVR) + if (rpath->frp_flags & FIB_ROUTE_PATH_DVR) { - out->is_dvr = 1; + out->type = FIB_API_PATH_TYPE_DVR; } - if (api_rpath->rpath.frp_flags & FIB_ROUTE_PATH_UDP_ENCAP) + else if (rpath->frp_flags & FIB_ROUTE_PATH_ICMP_UNREACH) { - out->is_udp_encap = 1; - out->next_hop_id = api_rpath->rpath.frp_udp_encap_id; + out->type = FIB_API_PATH_TYPE_ICMP_UNREACH; } - if (api_rpath->rpath.frp_flags & FIB_ROUTE_PATH_INTF_RX) + else if (rpath->frp_flags & FIB_ROUTE_PATH_ICMP_PROHIBIT) { - out->is_interface_rx = 1; + out->type = FIB_API_PATH_TYPE_ICMP_PROHIBIT; } - if (api_rpath->rpath.frp_flags & FIB_ROUTE_PATH_LOCAL) + else if (rpath->frp_flags & FIB_ROUTE_PATH_LOCAL) { - out->is_local = 1; + out->type = FIB_API_PATH_TYPE_LOCAL; } - if (api_rpath->rpath.frp_flags & FIB_ROUTE_PATH_RESOLVE_VIA_HOST) + else if (rpath->frp_flags & FIB_ROUTE_PATH_DROP) { - out->is_resolve_host = 1; + out->type = FIB_API_PATH_TYPE_DROP; } - if (api_rpath->rpath.frp_flags & FIB_ROUTE_PATH_RESOLVE_VIA_ATTACHED) + else if (rpath->frp_flags & FIB_ROUTE_PATH_UDP_ENCAP) { - out->is_resolve_attached = 1; + out->type = FIB_API_PATH_TYPE_UDP_ENCAP; + out->nh.obj_id = rpath->frp_udp_encap_id; } - /* 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) + else if (rpath->frp_flags & FIB_ROUTE_PATH_BIER_IMP) + { + out->type = FIB_API_PATH_TYPE_BIER_IMP; + out->nh.obj_id = rpath->frp_bier_imp; + } + else + { + out->type = FIB_API_PATH_TYPE_NORMAL; + } + if (rpath->frp_flags & FIB_ROUTE_PATH_RESOLVE_VIA_HOST) + { + out->flags |= FIB_API_PATH_FLAG_RESOLVE_VIA_HOST; + } + if (rpath->frp_flags & FIB_ROUTE_PATH_RESOLVE_VIA_ATTACHED) + { + out->flags |= FIB_API_PATH_FLAG_RESOLVE_VIA_ATTACHED; + } + + out->flags = htonl (out->flags); + out->type = htonl (out->type); + out->proto = htonl (out->proto); + + if (rpath->frp_label_stack) { - for (ii = 0; ii < vec_len(api_rpath->rpath.frp_label_stack); ii++) + int ii; + + for (ii = 0; ii < vec_len(rpath->frp_label_stack); ii++) { out->label_stack[ii].label = - htonl(api_rpath->rpath.frp_label_stack[ii].fml_value); + htonl(rpath->frp_label_stack[ii].fml_value); out->label_stack[ii].ttl = - api_rpath->rpath.frp_label_stack[ii].fml_ttl; + rpath->frp_label_stack[ii].fml_ttl; out->label_stack[ii].exp = - api_rpath->rpath.frp_label_stack[ii].fml_exp; + rpath->frp_label_stack[ii].fml_exp; } out->n_labels = ii; } } +void +fib_api_route_add_del (u8 is_add, + u8 is_multipath, + u32 fib_index, + const fib_prefix_t * prefix, + fib_entry_flag_t entry_flags, + fib_route_path_t *rpaths) +{ + if (is_multipath) + { + /* Iterative path add/remove */ + if (is_add) + fib_table_entry_path_add2 (fib_index, + prefix, + FIB_SOURCE_API, + entry_flags, + rpaths); + else + fib_table_entry_path_remove2 (fib_index, + prefix, + FIB_SOURCE_API, + rpaths); + } + else + { + if (is_add) + /* path replacement */ + fib_table_entry_update (fib_index, + prefix, + FIB_SOURCE_API, + entry_flags, + rpaths); + else + /* entry delete */ + fib_table_entry_delete (fib_index, + prefix, + FIB_SOURCE_API); + } +} + +u8* +format_vl_api_fib_path (u8 * s, va_list * args) +{ + const vl_api_fib_path_t *path = va_arg (*args, vl_api_fib_path_t*); + + s = format (s, "sw_if_index %d", ntohl (path->sw_if_index)); + switch (clib_net_to_host_u32(path->proto)) + { + case FIB_API_PATH_NH_PROTO_IP4: + s = format (s, " %U", format_vl_api_address_union, + &path->nh.address, ADDRESS_IP4); + break; + case FIB_API_PATH_NH_PROTO_IP6: + s = format (s, " %U", format_vl_api_address_union, + &path->nh.address, ADDRESS_IP6); + break; + default: + break; + } + s = format (s, " weight %d", path->weight); + s = format (s, " preference %d", path->preference); + s = format (s, " type %d", ntohl(path->type)); + s = format (s, " proto %d", ntohl(path->proto)); + s = format (s, " flags %d", ntohl(path->flags)); + s = format (s, " n_labels %d", ntohl(path->n_labels)); + s = format (s, " table-id %d", ntohl(path->table_id)); + s = format (s, " rpf-id %d", ntohl(path->rpf_id)); + + return (s); +} + fib_protocol_t fib_proto_from_api_address_family (int af) { diff --git a/src/vnet/fib/fib_api.h b/src/vnet/fib/fib_api.h index 041f962e3d7..ffff2289b37 100644 --- a/src/vnet/fib/fib_api.h +++ b/src/vnet/fib/fib_api.h @@ -17,61 +17,38 @@ #define __FIB_API_H__ #include <vnet/fib/fib_types.h> +#include <vnet/fib/fib_entry.h> -int -add_del_route_check (fib_protocol_t table_proto, - u32 table_id, - u32 next_hop_sw_if_index, - dpo_proto_t next_hop_table_proto, - u32 next_hop_table_id, - u8 is_rpf_id, - u32 * fib_index, u32 * next_hop_fib_index); - -int -add_del_route_t_handler (u8 is_multipath, - u8 is_add, - u8 is_drop, - u8 is_unreach, - u8 is_prohibit, - u8 is_local, - u8 is_multicast, - u8 is_classify, - u32 classify_table_index, - u8 is_resolve_host, - u8 is_resolve_attached, - u8 is_interface_rx, - u8 is_rpf_id, - u8 is_dvr, - u8 is_source_lookup, - u8 is_udp_encap, - u32 fib_index, - const fib_prefix_t * prefix, - dpo_proto_t next_hop_proto, - const ip46_address_t * next_hop, - u32 next_hop_id, - u32 next_hop_sw_if_index, - u8 next_hop_fib_index, - u16 next_hop_weight, - u16 next_hop_preference, - mpls_label_t next_hop_via_label, - fib_mpls_label_t * next_hop_out_label_stack); - +/** + * Forward declare the API type, no need to include the generated api headers + */ struct _vl_api_fib_path; +struct _vl_api_fib_prefix; -extern void fib_api_path_encode (const fib_route_path_encode_t * api_rpath, - struct _vl_api_fib_path *out); +/** + * Encode and decode functions from the API types to internal types + */ +extern void fib_api_path_encode(const fib_route_path_t * api_rpath, + struct _vl_api_fib_path *out); +extern int fib_api_path_decode(struct _vl_api_fib_path *in, + fib_route_path_t *out); -void -fib_prefix_to_api (const fib_prefix_t *pfx, - u8 address[16], - u8 *length, - u8 *is_ip6); +extern int fib_api_table_id_decode(fib_protocol_t fproto, + u32 table_id, + u32 *fib_index); +/** + * Adding routes from the API + */ +extern void fib_api_route_add_del (u8 is_add, + u8 is_multipath, + u32 fib_index, + const fib_prefix_t * prefix, + fib_entry_flag_t entry_flags, + fib_route_path_t *rpaths); -struct _vl_api_fib_path; +extern u8* format_vl_api_fib_path(u8 * s, va_list * args); -extern int fib_path_api_parse(const struct _vl_api_fib_path *in, - fib_route_path_t *out); extern fib_protocol_t fib_proto_from_api_address_family (int af); extern int fib_proto_to_api_address_family (fib_protocol_t fproto); diff --git a/src/vnet/fib/fib_entry.c b/src/vnet/fib/fib_entry.c index edbfdf6e3a4..6ff692dea98 100644 --- a/src/vnet/fib/fib_entry.c +++ b/src/vnet/fib/fib_entry.c @@ -906,21 +906,19 @@ void fib_entry_path_add (fib_node_index_t fib_entry_index, fib_source_t source, fib_entry_flag_t flags, - const fib_route_path_t *rpath) + const fib_route_path_t *rpaths) { fib_source_t best_source; fib_entry_t *fib_entry; fib_entry_src_t *bsrc; - ASSERT(1 == vec_len(rpath)); - fib_entry = fib_entry_get(fib_entry_index); ASSERT(NULL != fib_entry); bsrc = fib_entry_get_best_src_i(fib_entry); best_source = fib_entry_src_get_source(bsrc); - fib_entry = fib_entry_src_action_path_add(fib_entry, source, flags, rpath); + fib_entry = fib_entry_src_action_path_add(fib_entry, source, flags, rpaths); fib_entry_source_change(fib_entry, best_source, source); @@ -1003,7 +1001,7 @@ fib_entry_source_removed (fib_entry_t *fib_entry, fib_entry_src_flag_t fib_entry_path_remove (fib_node_index_t fib_entry_index, fib_source_t source, - const fib_route_path_t *rpath) + const fib_route_path_t *rpaths) { fib_entry_src_flag_t sflag; fib_source_t best_source; @@ -1011,8 +1009,6 @@ fib_entry_path_remove (fib_node_index_t fib_entry_index, fib_entry_t *fib_entry; fib_entry_src_t *bsrc; - ASSERT(1 == vec_len(rpath)); - fib_entry = fib_entry_get(fib_entry_index); ASSERT(NULL != fib_entry); @@ -1020,7 +1016,7 @@ fib_entry_path_remove (fib_node_index_t fib_entry_index, best_source = fib_entry_src_get_source(bsrc); bflags = fib_entry_src_get_flags(bsrc); - sflag = fib_entry_src_action_path_remove(fib_entry, source, rpath); + sflag = fib_entry_src_action_path_remove(fib_entry, source, rpaths); FIB_ENTRY_DBG(fib_entry, "path remove:%U", format_fib_source, source); @@ -1648,11 +1644,13 @@ fib_entry_module_init (void) fib_entry_logger = vlib_log_register_class("fib", "entry"); } -void -fib_entry_encode (fib_node_index_t fib_entry_index, - fib_route_path_encode_t **api_rpaths) +fib_route_path_t * +fib_entry_encode (fib_node_index_t fib_entry_index) { fib_path_ext_list_t *ext_list; + fib_path_encode_ctx_t ctx = { + .rpaths = NULL, + }; fib_entry_t *fib_entry; fib_entry_src_t *bsrc; @@ -1670,8 +1668,10 @@ fib_entry_encode (fib_node_index_t fib_entry_index, fib_path_list_walk_w_ext(fib_entry->fe_parent, ext_list, fib_path_encode, - api_rpaths); + &ctx); } + + return (ctx.rpaths); } const fib_prefix_t * diff --git a/src/vnet/fib/fib_entry.h b/src/vnet/fib/fib_entry.h index 8ede39c1e9d..5d0fb24bcb2 100644 --- a/src/vnet/fib/fib_entry.h +++ b/src/vnet/fib/fib_entry.h @@ -539,7 +539,7 @@ extern void fib_entry_update (fib_node_index_t fib_entry_index, extern void fib_entry_path_add(fib_node_index_t fib_entry_index, fib_source_t source, fib_entry_flag_t flags, - const fib_route_path_t *rpath); + const fib_route_path_t *rpaths); extern void fib_entry_special_add(fib_node_index_t fib_entry_index, fib_source_t source, fib_entry_flag_t flags, @@ -553,7 +553,7 @@ extern fib_entry_src_flag_t fib_entry_special_remove(fib_node_index_t fib_entry_ extern fib_entry_src_flag_t fib_entry_path_remove(fib_node_index_t fib_entry_index, fib_source_t source, - const fib_route_path_t *rpath); + const fib_route_path_t *rpaths); extern void fib_entry_inherit(fib_node_index_t cover, fib_node_index_t covered); @@ -601,9 +601,8 @@ extern u32 fib_entry_get_resolving_interface_for_source( fib_node_index_t fib_entry_index, fib_source_t source); -extern void fib_entry_encode(fib_node_index_t fib_entry_index, - fib_route_path_encode_t **api_rpaths); -extern const fib_prefix_t *fib_entry_get_prefix(fib_node_index_t fib_entry_index); +extern fib_route_path_t* fib_entry_encode(fib_node_index_t fib_entry_index); +extern const fib_prefix_t* fib_entry_get_prefix(fib_node_index_t fib_entry_index); extern u32 fib_entry_get_fib_index(fib_node_index_t fib_entry_index); extern void fib_entry_set_source_data(fib_node_index_t fib_entry_index, fib_source_t source, diff --git a/src/vnet/fib/fib_entry_src.c b/src/vnet/fib/fib_entry_src.c index c6c2a04bed7..1766ec765ea 100644 --- a/src/vnet/fib/fib_entry_src.c +++ b/src/vnet/fib/fib_entry_src.c @@ -1490,34 +1490,39 @@ fib_entry_src_flags_2_path_list_flags (fib_entry_flag_t eflags) static void fib_entry_flags_update (const fib_entry_t *fib_entry, - const fib_route_path_t *rpath, + const fib_route_path_t *rpaths, fib_path_list_flags_t *pl_flags, fib_entry_src_t *esrc) { - if ((esrc->fes_src == FIB_SOURCE_API) || - (esrc->fes_src == FIB_SOURCE_CLI)) - { - if (fib_path_is_attached(rpath)) - { - esrc->fes_entry_flags |= FIB_ENTRY_FLAG_ATTACHED; - } - else - { - esrc->fes_entry_flags &= ~FIB_ENTRY_FLAG_ATTACHED; - } - if (rpath->frp_flags & FIB_ROUTE_PATH_DEAG) - { - esrc->fes_entry_flags |= FIB_ENTRY_FLAG_LOOSE_URPF_EXEMPT; - } - } - if (fib_route_attached_cross_table(fib_entry, rpath) && - !(esrc->fes_entry_flags & FIB_ENTRY_FLAG_NO_ATTACHED_EXPORT)) - { - esrc->fes_entry_flags |= FIB_ENTRY_FLAG_IMPORT; - } - else + const fib_route_path_t *rpath; + + vec_foreach(rpath, rpaths) { - esrc->fes_entry_flags &= ~FIB_ENTRY_FLAG_IMPORT; + if ((esrc->fes_src == FIB_SOURCE_API) || + (esrc->fes_src == FIB_SOURCE_CLI)) + { + if (fib_path_is_attached(rpath)) + { + esrc->fes_entry_flags |= FIB_ENTRY_FLAG_ATTACHED; + } + else + { + esrc->fes_entry_flags &= ~FIB_ENTRY_FLAG_ATTACHED; + } + if (rpath->frp_flags & FIB_ROUTE_PATH_DEAG) + { + esrc->fes_entry_flags |= FIB_ENTRY_FLAG_LOOSE_URPF_EXEMPT; + } + } + if (fib_route_attached_cross_table(fib_entry, rpath) && + !(esrc->fes_entry_flags & FIB_ENTRY_FLAG_NO_ATTACHED_EXPORT)) + { + esrc->fes_entry_flags |= FIB_ENTRY_FLAG_IMPORT; + } + else + { + esrc->fes_entry_flags &= ~FIB_ENTRY_FLAG_IMPORT; + } } } @@ -1533,7 +1538,7 @@ fib_entry_t* fib_entry_src_action_path_add (fib_entry_t *fib_entry, fib_source_t source, fib_entry_flag_t flags, - const fib_route_path_t *rpath) + const fib_route_path_t *rpaths) { fib_node_index_t old_path_list, fib_entry_index; fib_path_list_flags_t pl_flags; @@ -1550,7 +1555,7 @@ fib_entry_src_action_path_add (fib_entry_t *fib_entry, const dpo_id_t *dpo; if (flags == FIB_ENTRY_FLAG_EXCLUSIVE) { - dpo = &rpath->dpo; + dpo = &rpaths->dpo; } else { dpo = drop_dpo_get(fib_entry_get_dpo_proto(fib_entry)); } @@ -1574,10 +1579,10 @@ fib_entry_src_action_path_add (fib_entry_t *fib_entry, ASSERT(FIB_ENTRY_SRC_VFT_EXISTS(esrc, fesv_path_add)); pl_flags = fib_entry_src_flags_2_path_list_flags(fib_entry_get_flags_i(fib_entry)); - fib_entry_flags_update(fib_entry, rpath, &pl_flags, esrc); + fib_entry_flags_update(fib_entry, rpaths, &pl_flags, esrc); FIB_ENTRY_SRC_VFT_INVOKE(esrc, fesv_path_add, - (esrc, fib_entry, pl_flags, rpath)); + (esrc, fib_entry, pl_flags, rpaths)); fib_entry = fib_entry_get(fib_entry_index); fib_path_list_lock(esrc->fes_pl); @@ -1670,7 +1675,7 @@ fib_entry_src_action_path_swap (fib_entry_t *fib_entry, fib_entry_src_flag_t fib_entry_src_action_path_remove (fib_entry_t *fib_entry, fib_source_t source, - const fib_route_path_t *rpath) + const fib_route_path_t *rpaths) { fib_path_list_flags_t pl_flags; fib_node_index_t old_path_list; @@ -1692,10 +1697,10 @@ fib_entry_src_action_path_remove (fib_entry_t *fib_entry, ASSERT(FIB_ENTRY_SRC_VFT_EXISTS(esrc, fesv_path_remove)); pl_flags = fib_entry_src_flags_2_path_list_flags(fib_entry_get_flags_i(fib_entry)); - fib_entry_flags_update(fib_entry, rpath, &pl_flags, esrc); + fib_entry_flags_update(fib_entry, rpaths, &pl_flags, esrc); FIB_ENTRY_SRC_VFT_INVOKE(esrc, fesv_path_remove, - (esrc, pl_flags, rpath)); + (esrc, pl_flags, rpaths)); /* * lock the new path-list, unlock the old if it had one diff --git a/src/vnet/fib/fib_path.c b/src/vnet/fib/fib_path.c index 67a4bc1d4de..eebba1b1548 100644 --- a/src/vnet/fib/fib_path.c +++ b/src/vnet/fib/fib_path.c @@ -24,7 +24,8 @@ #include <vnet/dpo/interface_rx_dpo.h> #include <vnet/dpo/mpls_disposition.h> #include <vnet/dpo/dvr_dpo.h> -#include <vnet/dpo/drop_dpo.h> +#include <vnet/dpo/ip_null_dpo.h> +#include <vnet/dpo/classify_dpo.h> #include <vnet/adj/adj.h> #include <vnet/adj/adj_mcast.h> @@ -353,6 +354,12 @@ typedef struct fib_path_t_ { } udp_encap; struct { /** + * The UDP Encap object this path resolves through + */ + u32 fp_classify_table_id; + } classify; + struct { + /** * The interface */ u32 fp_interface; @@ -882,8 +889,8 @@ fib_path_unresolve (fib_path_t *path) { fib_entry_child_remove(path->fp_via_fib, path->fp_sibling); - fib_table_entry_special_remove(path->recursive.fp_tbl_id, - fib_entry_get_prefix(path->fp_via_fib), + fib_table_entry_special_remove(path->recursive.fp_tbl_id, + fib_entry_get_prefix(path->fp_via_fib), FIB_SOURCE_RR); fib_table_unlock(path->recursive.fp_tbl_id, dpo_proto_to_fib(path->fp_nh_proto), @@ -1244,6 +1251,10 @@ fib_path_route_flags_to_cfg_flags (const fib_route_path_t *rpath) cfg_flags |= FIB_PATH_CFG_FLAG_DROP; if (rpath->frp_flags & FIB_ROUTE_PATH_SOURCE_LOOKUP) cfg_flags |= FIB_PATH_CFG_FLAG_DEAG_SRC; + if (rpath->frp_flags & FIB_ROUTE_PATH_ICMP_UNREACH) + cfg_flags |= FIB_PATH_CFG_FLAG_ICMP_UNREACH; + if (rpath->frp_flags & FIB_ROUTE_PATH_ICMP_PROHIBIT) + cfg_flags |= FIB_PATH_CFG_FLAG_ICMP_PROHIBIT; return (cfg_flags); } @@ -1337,6 +1348,16 @@ fib_path_create (fib_node_index_t pl_index, path->fp_type = FIB_PATH_TYPE_EXCLUSIVE; dpo_copy(&path->exclusive.fp_ex_dpo, &rpath->dpo); } + else if ((path->fp_cfg_flags & FIB_PATH_CFG_FLAG_ICMP_PROHIBIT) || + (path->fp_cfg_flags & FIB_PATH_CFG_FLAG_ICMP_UNREACH)) + { + path->fp_type = FIB_PATH_TYPE_SPECIAL; + } + else if ((path->fp_cfg_flags & FIB_PATH_CFG_FLAG_CLASSIFY)) + { + path->fp_type = FIB_PATH_TYPE_SPECIAL; + path->classify.fp_classify_table_id = rpath->frp_classify_table_id; + } else if (~0 != rpath->frp_sw_if_index) { if (ip46_address_is_zero(&rpath->frp_addr)) @@ -1730,8 +1751,17 @@ fib_path_cmp_w_route_path (fib_node_index_t path_index, case FIB_PATH_TYPE_EXCLUSIVE: res = dpo_cmp(&path->exclusive.fp_ex_dpo, &rpath->dpo); break; - case FIB_PATH_TYPE_SPECIAL: case FIB_PATH_TYPE_RECEIVE: + if (rpath->frp_flags & FIB_ROUTE_PATH_LOCAL) + { + res = 0; + } + else + { + res = 1; + } + break; + case FIB_PATH_TYPE_SPECIAL: res = 0; break; } @@ -2006,11 +2036,33 @@ fib_path_resolve (fib_node_index_t path_index) break; } case FIB_PATH_TYPE_SPECIAL: - /* - * Resolve via the drop - */ - dpo_copy(&path->fp_dpo, drop_dpo_get(path->fp_nh_proto)); - break; + if (path->fp_cfg_flags & FIB_PATH_CFG_FLAG_ICMP_PROHIBIT) + { + ip_null_dpo_add_and_lock (path->fp_nh_proto, + IP_NULL_ACTION_SEND_ICMP_PROHIBIT, + &path->fp_dpo); + } + else if (path->fp_cfg_flags & FIB_PATH_CFG_FLAG_ICMP_UNREACH) + { + ip_null_dpo_add_and_lock (path->fp_nh_proto, + IP_NULL_ACTION_SEND_ICMP_UNREACH, + &path->fp_dpo); + } + else if (path->fp_cfg_flags & FIB_PATH_CFG_FLAG_CLASSIFY) + { + dpo_set (&path->fp_dpo, DPO_CLASSIFY, + path->fp_nh_proto, + classify_dpo_create (path->fp_nh_proto, + path->classify.fp_classify_table_id)); + } + else + { + /* + * Resolve via the drop + */ + dpo_copy(&path->fp_dpo, drop_dpo_get(path->fp_nh_proto)); + } + break; case FIB_PATH_TYPE_DEAG: { if (DPO_PROTO_BIER == path->fp_nh_proto) @@ -2459,10 +2511,10 @@ fib_path_contribute_forwarding (fib_node_index_t path_index, case FIB_FORW_CHAIN_TYPE_MPLS_EOS: case FIB_FORW_CHAIN_TYPE_UNICAST_IP4: case FIB_FORW_CHAIN_TYPE_UNICAST_IP6: - dpo_copy(dpo, &path->fp_dpo); - break; case FIB_FORW_CHAIN_TYPE_MCAST_IP4: case FIB_FORW_CHAIN_TYPE_MCAST_IP6: + dpo_copy(dpo, &path->fp_dpo); + break; case FIB_FORW_CHAIN_TYPE_BIER: break; case FIB_FORW_CHAIN_TYPE_ETHERNET: @@ -2627,73 +2679,83 @@ fib_path_list_walk_rc_t fib_path_encode (fib_node_index_t path_list_index, fib_node_index_t path_index, const fib_path_ext_t *path_ext, - void *ctx) + void *args) { - fib_route_path_encode_t **api_rpaths = ctx; - fib_route_path_encode_t *api_rpath; + fib_path_encode_ctx_t *ctx = args; + fib_route_path_t *rpath; fib_path_t *path; path = fib_path_get(path_index); if (!path) return (FIB_PATH_LIST_WALK_CONTINUE); - vec_add2(*api_rpaths, api_rpath, 1); - api_rpath->rpath.frp_weight = path->fp_weight; - api_rpath->rpath.frp_preference = path->fp_preference; - api_rpath->rpath.frp_proto = path->fp_nh_proto; - api_rpath->rpath.frp_sw_if_index = ~0; - api_rpath->rpath.frp_fib_index = 0; - api_rpath->dpo = path->fp_dpo; + + vec_add2(ctx->rpaths, rpath, 1); + rpath->frp_weight = path->fp_weight; + rpath->frp_preference = path->fp_preference; + rpath->frp_proto = path->fp_nh_proto; + rpath->frp_sw_if_index = ~0; + rpath->frp_fib_index = 0; 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; + rpath->frp_addr = path->receive.fp_addr; + rpath->frp_sw_if_index = path->receive.fp_interface; + rpath->frp_flags |= FIB_ROUTE_PATH_LOCAL; break; case FIB_PATH_TYPE_ATTACHED: - api_rpath->rpath.frp_sw_if_index = path->attached.fp_interface; + rpath->frp_sw_if_index = path->attached.fp_interface; break; case FIB_PATH_TYPE_ATTACHED_NEXT_HOP: - api_rpath->rpath.frp_sw_if_index = path->attached_next_hop.fp_interface; - api_rpath->rpath.frp_addr = path->attached_next_hop.fp_nh; + rpath->frp_sw_if_index = path->attached_next_hop.fp_interface; + rpath->frp_addr = path->attached_next_hop.fp_nh; break; case FIB_PATH_TYPE_BIER_FMASK: - api_rpath->rpath.frp_bier_fmask = path->bier_fmask.fp_bier_fmask; + rpath->frp_bier_fmask = path->bier_fmask.fp_bier_fmask; break; case FIB_PATH_TYPE_SPECIAL: break; case FIB_PATH_TYPE_DEAG: - api_rpath->rpath.frp_fib_index = path->deag.fp_tbl_id; + 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; + 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; - api_rpath->rpath.frp_fib_index = path->recursive.fp_tbl_id; + rpath->frp_addr = path->recursive.fp_nh.fp_ip; + rpath->frp_fib_index = path->recursive.fp_tbl_id; break; case FIB_PATH_TYPE_DVR: - api_rpath->rpath.frp_sw_if_index = path->dvr.fp_interface; - api_rpath->rpath.frp_flags |= FIB_ROUTE_PATH_DVR; + rpath->frp_sw_if_index = path->dvr.fp_interface; + rpath->frp_flags |= FIB_ROUTE_PATH_DVR; break; case FIB_PATH_TYPE_UDP_ENCAP: - api_rpath->rpath.frp_udp_encap_id = path->udp_encap.fp_udp_encap_id; - api_rpath->rpath.frp_flags |= FIB_ROUTE_PATH_UDP_ENCAP; + rpath->frp_udp_encap_id = path->udp_encap.fp_udp_encap_id; + 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; + rpath->frp_sw_if_index = path->receive.fp_interface; + rpath->frp_flags |= FIB_ROUTE_PATH_INTF_RX; break; + case FIB_PATH_TYPE_EXCLUSIVE: + rpath->frp_flags |= FIB_ROUTE_PATH_EXCLUSIVE; 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; + rpath->frp_label_stack = path_ext->fpe_path.frp_label_stack; } + if (path->fp_cfg_flags & FIB_PATH_CFG_FLAG_DROP) + rpath->frp_flags |= FIB_ROUTE_PATH_DROP; + if (path->fp_cfg_flags & FIB_PATH_CFG_FLAG_ICMP_UNREACH) + rpath->frp_flags |= FIB_ROUTE_PATH_ICMP_UNREACH; + if (path->fp_cfg_flags & FIB_PATH_CFG_FLAG_ICMP_PROHIBIT) + rpath->frp_flags |= FIB_ROUTE_PATH_ICMP_PROHIBIT; + return (FIB_PATH_LIST_WALK_CONTINUE); } diff --git a/src/vnet/fib/fib_path.h b/src/vnet/fib/fib_path.h index 57dec6d90b4..50aca9e1cf5 100644 --- a/src/vnet/fib/fib_path.h +++ b/src/vnet/fib/fib_path.h @@ -80,6 +80,18 @@ typedef enum fib_path_cfg_attribute_t_ { */ FIB_PATH_CFG_ATTRIBUTE_LOCAL, /** + * The path reolves via an ICMP unreachable + */ + FIB_PATH_CFG_ATTRIBUTE_ICMP_UNREACH, + /** + * The path reolves via an ICMP prohibit + */ + FIB_PATH_CFG_ATTRIBUTE_ICMP_PROHIBIT, + /** + * The path reolves via a classify + */ + FIB_PATH_CFG_ATTRIBUTE_CLASSIFY, + /** * The deag path does a source lookup */ FIB_PATH_CFG_ATTRIBUTE_DEAG_SRC, @@ -100,6 +112,9 @@ typedef enum fib_path_cfg_attribute_t_ { [FIB_PATH_CFG_ATTRIBUTE_RESOLVE_HOST] = "resolve-host", \ [FIB_PATH_CFG_ATTRIBUTE_RESOLVE_ATTACHED] = "resolve-attached", \ [FIB_PATH_CFG_ATTRIBUTE_LOCAL] = "local", \ + [FIB_PATH_CFG_ATTRIBUTE_ICMP_UNREACH] = "icmp-unreach", \ + [FIB_PATH_CFG_ATTRIBUTE_ICMP_PROHIBIT] = "icmp-prohibit", \ + [FIB_PATH_CFG_ATTRIBUTE_CLASSIFY] = "classify", \ [FIB_PATH_CFG_ATTRIBUTE_ATTACHED] = "attached", \ [FIB_PATH_CFG_ATTRIBUTE_INTF_RX] = "interface-rx", \ [FIB_PATH_CFG_ATTRIBUTE_RPF_ID] = "rpf-id", \ @@ -121,6 +136,9 @@ typedef enum fib_path_cfg_flags_t_ { FIB_PATH_CFG_FLAG_RESOLVE_HOST = (1 << FIB_PATH_CFG_ATTRIBUTE_RESOLVE_HOST), FIB_PATH_CFG_FLAG_RESOLVE_ATTACHED = (1 << FIB_PATH_CFG_ATTRIBUTE_RESOLVE_ATTACHED), FIB_PATH_CFG_FLAG_LOCAL = (1 << FIB_PATH_CFG_ATTRIBUTE_LOCAL), + FIB_PATH_CFG_FLAG_ICMP_UNREACH = (1 << FIB_PATH_CFG_ATTRIBUTE_ICMP_UNREACH), + FIB_PATH_CFG_FLAG_ICMP_PROHIBIT = (1 << FIB_PATH_CFG_ATTRIBUTE_ICMP_PROHIBIT), + FIB_PATH_CFG_FLAG_CLASSIFY = (1 << FIB_PATH_CFG_ATTRIBUTE_CLASSIFY), FIB_PATH_CFG_FLAG_ATTACHED = (1 << FIB_PATH_CFG_ATTRIBUTE_ATTACHED), FIB_PATH_CFG_FLAG_INTF_RX = (1 << FIB_PATH_CFG_ATTRIBUTE_INTF_RX), FIB_PATH_CFG_FLAG_RPF_ID = (1 << FIB_PATH_CFG_ATTRIBUTE_RPF_ID), @@ -181,6 +199,16 @@ extern u16 fib_path_get_preference(fib_node_index_t path_index); extern u32 fib_path_get_rpf_id(fib_node_index_t path_index); extern void fib_path_module_init(void); + +/** + * Path encode context to use when walking a path-list + * to encode paths + */ +typedef struct fib_path_encode_ctx_t_ +{ + fib_route_path_t *rpaths; +} fib_path_encode_ctx_t; + 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, diff --git a/src/vnet/fib/fib_path_list.c b/src/vnet/fib/fib_path_list.c index 47170adf864..7c57c807327 100644 --- a/src/vnet/fib/fib_path_list.c +++ b/src/vnet/fib/fib_path_list.c @@ -830,12 +830,14 @@ fib_path_list_find_rpath (fib_node_index_t path_list_index, * The path-list returned could either have been newly created, or * can be a shared path-list from the data-base. */ -fib_node_index_t -fib_path_list_path_add (fib_node_index_t path_list_index, - const fib_route_path_t *rpaths) +fib_node_index_t* +fib_path_list_paths_add (fib_node_index_t path_list_index, + const fib_route_path_t *rpaths) { - fib_node_index_t new_path_index, *orig_path_index; + fib_node_index_t *new_path_indices, *path_index; + const fib_route_path_t *rpath; fib_path_list_t *path_list; + u32 ii; /* * alloc the new list before we retrieve the old one, lest @@ -843,40 +845,65 @@ fib_path_list_path_add (fib_node_index_t path_list_index, */ path_list = fib_path_list_get(path_list_index); - ASSERT(1 == vec_len(rpaths)); ASSERT(!(path_list->fpl_flags & FIB_PATH_LIST_FLAG_SHARED)); - FIB_PATH_LIST_DBG(path_list, "path-add"); + FIB_PATH_LIST_DBG(path_list, "paths-add"); - new_path_index = fib_path_create(path_list_index, - rpaths); + new_path_indices = NULL; + vec_validate_init_empty(new_path_indices, + vec_len(rpaths) - 1, + FIB_NODE_INDEX_INVALID); - vec_foreach (orig_path_index, path_list->fpl_paths) + vec_foreach (path_index, path_list->fpl_paths) { /* * don't add duplicate paths */ - if (0 == fib_path_cmp(new_path_index, *orig_path_index)) + int found = 0; + + vec_foreach_index(ii, rpaths) { - fib_path_destroy(new_path_index); - return (*orig_path_index); + rpath = &rpaths[ii]; + if (0 == fib_path_cmp_w_route_path(*path_index, rpath)) + { + found = 1; + break; + } + } + if (found) + { + new_path_indices[ii] = *path_index; } } /* - * Add the new path - no sort, no sharing, no key.. + * new_path_indices array contains INVALID for each path not found + * and something valid for matches */ - vec_add1(path_list->fpl_paths, new_path_index); + vec_foreach_index (ii, new_path_indices) + { + path_index = &new_path_indices[ii]; + rpath = &rpaths[ii]; - FIB_PATH_LIST_DBG(path_list, "path-added"); + if (FIB_NODE_INDEX_INVALID == *path_index) + { + *path_index = fib_path_create(path_list_index, rpath); + /* + * Add the new path - no sort, no sharing, no key.. + */ + vec_add1(path_list->fpl_paths, *path_index); - /* - * no shared path list requested. resolve and use the one - * just created. - */ - fib_path_resolve(new_path_index); + /* + * no shared path list requested. resolve and use the one + * just created. + */ + fib_path_resolve(*path_index); + } + } + + FIB_PATH_LIST_DBG(path_list, "paths-added"); - return (new_path_index); + return (new_path_indices); } fib_node_index_t @@ -884,14 +911,13 @@ fib_path_list_copy_and_path_add (fib_node_index_t orig_path_list_index, fib_path_list_flags_t flags, const fib_route_path_t *rpaths) { - fib_node_index_t path_index, new_path_index, *orig_path_index; + fib_node_index_t new_path_index, *orig_path_index; fib_path_list_t *path_list, *orig_path_list; fib_node_index_t exist_path_list_index; fib_node_index_t path_list_index; + const fib_route_path_t *rpath; fib_node_index_t pi; - ASSERT(1 == vec_len(rpaths)); - /* * alloc the new list before we retrieve the old one, lest * the alloc result in a realloc @@ -905,32 +931,50 @@ fib_path_list_copy_and_path_add (fib_node_index_t orig_path_list_index, flags = fib_path_list_flags_fixup(flags); path_list->fpl_flags = flags; - vec_validate(path_list->fpl_paths, vec_len(orig_path_list->fpl_paths)); + vec_validate(path_list->fpl_paths, + (vec_len(orig_path_list->fpl_paths) + + vec_len(rpaths) - 1)); pi = 0; - new_path_index = fib_path_create(path_list_index, - rpaths); - - vec_foreach (orig_path_index, orig_path_list->fpl_paths) + vec_foreach(orig_path_index, orig_path_list->fpl_paths) { /* - * don't add duplicate paths - * In the unlikely event the path is a duplicate, then we'll - * find a matching path-list later and this one will be toast. + * copy the original paths over to the new list */ - if (0 != fib_path_cmp(new_path_index, *orig_path_index)) + path_list->fpl_paths[pi++] = fib_path_copy(*orig_path_index, + path_list_index); + } + vec_foreach(rpath, rpaths) + { + int duplicate = 0; + + new_path_index = fib_path_create(path_list_index, rpath); + + vec_foreach(orig_path_index, orig_path_list->fpl_paths) { - path_index = fib_path_copy(*orig_path_index, path_list_index); - path_list->fpl_paths[pi++] = path_index; + /* + * don't add duplicate paths + * In the unlikely event the path is a duplicate, then we'll + * find a matching path-list later and this one will be toast. + */ + if (0 == fib_path_cmp(new_path_index, *orig_path_index)) + { + duplicate = 1; + break; + } + } + if (duplicate) + { + _vec_len(path_list->fpl_paths) = + vec_len(path_list->fpl_paths) - 1; + fib_path_destroy(new_path_index); } else { - _vec_len(path_list->fpl_paths) = vec_len(orig_path_list->fpl_paths); + path_list->fpl_paths[pi++] = new_path_index; } } - path_list->fpl_paths[pi] = new_path_index; - /* * we sort the paths since the key for the path-list is * the description of the paths it contains. The paths need to @@ -978,51 +1022,60 @@ fib_path_list_copy_and_path_add (fib_node_index_t orig_path_list_index, } /* - * fib_path_list_path_remove + * fib_path_list_paths_remove */ -fib_node_index_t -fib_path_list_path_remove (fib_node_index_t path_list_index, +fib_node_index_t* +fib_path_list_paths_remove (fib_node_index_t path_list_index, const fib_route_path_t *rpaths) { - fib_node_index_t match_path_index, tmp_path_index; + fib_node_index_t *match_path_indices; fib_path_list_t *path_list; - fib_node_index_t pi; + i32 ii, jj; path_list = fib_path_list_get(path_list_index); + match_path_indices = NULL; + vec_validate_init_empty(match_path_indices, + vec_len(rpaths) - 1, + FIB_NODE_INDEX_INVALID); - ASSERT(1 == vec_len(rpaths)); ASSERT(!(path_list->fpl_flags & FIB_PATH_LIST_FLAG_SHARED)); FIB_PATH_LIST_DBG(path_list, "path-remove"); /* - * create a representation of the path to be removed, so it - * can be used as a comparison object during the copy. + * the number of existing paths is likely to be larger than the + * number of paths being added. + * walk in reverse so the vec_del is ok */ - tmp_path_index = fib_path_create(path_list_index, - rpaths); - match_path_index = FIB_NODE_INDEX_INVALID; - - vec_foreach_index (pi, path_list->fpl_paths) + vec_foreach_index_backwards(ii, path_list->fpl_paths) { - if (0 == fib_path_cmp(tmp_path_index, - path_list->fpl_paths[pi])) + int found = ~0; + + vec_foreach_index(jj, rpaths) { + if (0 == fib_path_cmp_w_route_path(path_list->fpl_paths[ii], + &rpaths[jj])) + { + found = jj; + break; + } + } + if (~0 != found) + { + fib_node_index_t match_path_index; /* * match - remove it */ - match_path_index = path_list->fpl_paths[pi]; + match_path_index = path_list->fpl_paths[ii]; + vec_del1(path_list->fpl_paths, ii); fib_path_destroy(match_path_index); - vec_del1(path_list->fpl_paths, pi); - } + match_path_indices[jj] = match_path_index; + } } - /* - * done with the temporary now - */ - fib_path_destroy(tmp_path_index); + FIB_PATH_LIST_DBG(path_list, "paths-removed"); - return (match_path_index); + return (match_path_indices); } /* @@ -1035,10 +1088,11 @@ fib_path_list_path_remove (fib_node_index_t path_list_index, fib_node_index_t fib_path_list_copy_and_path_remove (fib_node_index_t orig_path_list_index, fib_path_list_flags_t flags, - const fib_route_path_t *rpath) + const fib_route_path_t *rpaths) { - fib_node_index_t path_index, *orig_path_index, path_list_index, tmp_path_index; + fib_node_index_t *orig_path_index, path_list_index, tmp_path_index; fib_path_list_t *path_list, *orig_path_list; + const fib_route_path_t *rpath; fib_node_index_t pi; path_list = fib_path_list_alloc(&path_list_index); @@ -1053,44 +1107,42 @@ fib_path_list_copy_and_path_remove (fib_node_index_t orig_path_list_index, * allocate as many paths as we might need in one go, rather than * using vec_add to do a few at a time. */ - if (vec_len(orig_path_list->fpl_paths) > 1) - { - vec_validate(path_list->fpl_paths, vec_len(orig_path_list->fpl_paths) - 2); - } + vec_validate(path_list->fpl_paths, + vec_len(orig_path_list->fpl_paths) - 1); pi = 0; /* * create a representation of the path to be removed, so it * can be used as a comparison object during the copy. */ - tmp_path_index = fib_path_create(path_list_index, rpath); - - vec_foreach (orig_path_index, orig_path_list->fpl_paths) + vec_foreach(orig_path_index, orig_path_list->fpl_paths) { - if (0 != fib_path_cmp(tmp_path_index, *orig_path_index)) { - path_index = fib_path_copy(*orig_path_index, path_list_index); - if (pi < vec_len(path_list->fpl_paths)) - { - path_list->fpl_paths[pi++] = path_index; - } - else - { - /* - * this is the unlikely case that the path being - * removed does not match one in the path-list, so - * we end up with as many paths as we started with. - * the paths vector was sized above with the expectation - * that we would have 1 less. - */ - vec_add1(path_list->fpl_paths, path_index); - } - } + /* + * copy the original paths over to the new list + */ + path_list->fpl_paths[pi++] = fib_path_copy(*orig_path_index, + path_list_index); } + vec_foreach(rpath, rpaths) + { + int found = 0; + tmp_path_index = fib_path_create(path_list_index, rpath); - /* - * done with the temporary now - */ - fib_path_destroy(tmp_path_index); + vec_foreach_index(pi, path_list->fpl_paths) + { + if (0 == fib_path_cmp(tmp_path_index, path_list->fpl_paths[pi])) + { + found = 1; + break; + } + } + if (found) + { + fib_path_destroy(path_list->fpl_paths[pi]); + vec_del1(path_list->fpl_paths, pi); + } + fib_path_destroy(tmp_path_index); + } /* * if there are no paths, then the new path-list is aborted diff --git a/src/vnet/fib/fib_path_list.h b/src/vnet/fib/fib_path_list.h index 380eb1a6864..06c1b14204b 100644 --- a/src/vnet/fib/fib_path_list.h +++ b/src/vnet/fib/fib_path_list.h @@ -118,10 +118,10 @@ extern fib_node_index_t fib_path_list_copy_and_path_remove( fib_node_index_t pl_index, fib_path_list_flags_t flags, const fib_route_path_t *path); -extern fib_node_index_t fib_path_list_path_add ( +extern fib_node_index_t* fib_path_list_paths_add ( fib_node_index_t path_list_index, const fib_route_path_t *rpaths); -extern fib_node_index_t fib_path_list_path_remove ( +extern fib_node_index_t* fib_path_list_paths_remove ( fib_node_index_t path_list_index, const fib_route_path_t *rpaths); diff --git a/src/vnet/fib/fib_table.c b/src/vnet/fib/fib_table.c index 56c8f030fda..3778fa9a944 100644 --- a/src/vnet/fib/fib_table.c +++ b/src/vnet/fib/fib_table.c @@ -481,7 +481,7 @@ fib_table_entry_special_remove (u32 fib_index, */ static void fib_table_route_path_fixup (const fib_prefix_t *prefix, - fib_entry_flag_t eflags, + fib_entry_flag_t *eflags, fib_route_path_t *path) { /* @@ -496,7 +496,8 @@ fib_table_route_path_fixup (const fib_prefix_t *prefix, /* Prefix recurses via itse;f */ path->frp_flags |= FIB_ROUTE_PATH_DROP; } - if (fib_prefix_is_host(prefix) && + if (!(path->frp_flags & FIB_ROUTE_PATH_LOCAL) && + fib_prefix_is_host(prefix) && ip46_address_is_zero(&path->frp_addr) && path->frp_sw_if_index != ~0 && path->frp_proto != DPO_PROTO_ETHERNET) @@ -504,18 +505,27 @@ fib_table_route_path_fixup (const fib_prefix_t *prefix, path->frp_addr = prefix->fp_addr; path->frp_flags |= FIB_ROUTE_PATH_ATTACHED; } - if (eflags & FIB_ENTRY_FLAG_DROP) + if (*eflags & FIB_ENTRY_FLAG_DROP) { path->frp_flags |= FIB_ROUTE_PATH_DROP; } - if (eflags & FIB_ENTRY_FLAG_LOCAL) + if (*eflags & FIB_ENTRY_FLAG_LOCAL) { path->frp_flags |= FIB_ROUTE_PATH_LOCAL; } - if (eflags & FIB_ENTRY_FLAG_EXCLUSIVE) + if (*eflags & FIB_ENTRY_FLAG_EXCLUSIVE) { path->frp_flags |= FIB_ROUTE_PATH_EXCLUSIVE; } + if (path->frp_flags & FIB_ROUTE_PATH_LOCAL) + { + *eflags |= FIB_ENTRY_FLAG_LOCAL; + + if (path->frp_sw_if_index != ~0) + { + *eflags |= FIB_ENTRY_FLAG_CONNECTED; + } + } } fib_node_index_t @@ -538,6 +548,7 @@ fib_table_entry_path_add (u32 fib_index, .frp_fib_index = next_hop_fib_index, .frp_weight = next_hop_weight, .frp_flags = path_flags, + .frp_rpf_id = INDEX_INVALID, .frp_label_stack = next_hop_labels, }; fib_node_index_t fib_entry_index; @@ -557,7 +568,7 @@ fib_table_entry_path_add2 (u32 fib_index, const fib_prefix_t *prefix, fib_source_t source, fib_entry_flag_t flags, - fib_route_path_t *rpath) + fib_route_path_t *rpaths) { fib_node_index_t fib_entry_index; fib_table_t *fib_table; @@ -566,16 +577,16 @@ fib_table_entry_path_add2 (u32 fib_index, fib_table = fib_table_get(fib_index, prefix->fp_proto); fib_entry_index = fib_table_lookup_exact_match_i(fib_table, prefix); - for (ii = 0; ii < vec_len(rpath); ii++) + for (ii = 0; ii < vec_len(rpaths); ii++) { - fib_table_route_path_fixup(prefix, flags, &rpath[ii]); + fib_table_route_path_fixup(prefix, &flags, &rpaths[ii]); } if (FIB_NODE_INDEX_INVALID == fib_entry_index) { fib_entry_index = fib_entry_create(fib_index, prefix, source, flags, - rpath); + rpaths); fib_table_entry_insert(fib_table, prefix, fib_entry_index); fib_table->ft_src_route_counts[source]++; @@ -585,7 +596,7 @@ fib_table_entry_path_add2 (u32 fib_index, int was_sourced; was_sourced = fib_entry_is_sourced(fib_entry_index, source); - fib_entry_path_add(fib_entry_index, source, flags, rpath);; + fib_entry_path_add(fib_entry_index, source, flags, rpaths);; if (was_sourced != fib_entry_is_sourced(fib_entry_index, source)) { @@ -600,7 +611,7 @@ void fib_table_entry_path_remove2 (u32 fib_index, const fib_prefix_t *prefix, fib_source_t source, - fib_route_path_t *rpath) + fib_route_path_t *rpaths) { /* * 1 is it present @@ -609,8 +620,8 @@ fib_table_entry_path_remove2 (u32 fib_index, * no => cover walk */ fib_node_index_t fib_entry_index; + fib_route_path_t *rpath; fib_table_t *fib_table; - u32 ii; fib_table = fib_table_get(fib_index, prefix->fp_proto); fib_entry_index = fib_table_lookup_exact_match_i(fib_table, prefix); @@ -640,16 +651,16 @@ fib_table_entry_path_remove2 (u32 fib_index, */ fib_entry_lock(fib_entry_index); - for (ii = 0; ii < vec_len(rpath); ii++) + vec_foreach(rpath, rpaths) { - fib_table_route_path_fixup( - prefix, - fib_entry_get_flags_for_source(fib_entry_index, - source), - &rpath[ii]); + fib_entry_flag_t eflags; + + eflags = fib_entry_get_flags_for_source(fib_entry_index, + source); + fib_table_route_path_fixup(prefix, &eflags, rpath); } - src_flag = fib_entry_path_remove(fib_entry_index, source, rpath); + src_flag = fib_entry_path_remove(fib_entry_index, source, rpaths); if (!(FIB_ENTRY_SRC_FLAG_ADDED & src_flag)) { @@ -735,7 +746,7 @@ fib_table_entry_update (u32 fib_index, for (ii = 0; ii < vec_len(paths); ii++) { - fib_table_route_path_fixup(prefix, flags, &paths[ii]); + fib_table_route_path_fixup(prefix, &flags, &paths[ii]); } /* * sort the paths provided by the control plane. this means diff --git a/src/vnet/fib/fib_types.api b/src/vnet/fib/fib_types.api index 8268870c0a7..9073192c3c4 100644 --- a/src/vnet/fib/fib_types.api +++ b/src/vnet/fib/fib_types.api @@ -1,5 +1,6 @@ +/* Hey Emacs use -*- mode: C -*- */ /* - * Copyright (c) 2016 Cisco and/or its affiliates. + * Copyright (c) 2018 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: @@ -12,10 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - + +option version = "2.0.0"; +import "vnet/ip/ip_types.api"; + /** \brief MPLS label */ -typeonly define fib_mpls_label +typedef fib_mpls_label { u8 is_uniform; u32 label; @@ -23,48 +27,101 @@ typeonly define fib_mpls_label u8 exp; }; +/** brief A path's nexthop protocol + */ +enum fib_path_nh_proto +{ + FIB_API_PATH_NH_PROTO_IP4 = 0, + FIB_API_PATH_NH_PROTO_IP6, + FIB_API_PATH_NH_PROTO_MPLS, + FIB_API_PATH_NH_PROTO_ETHERNET, + FIB_API_PATH_NH_PROTO_BIER, +}; + +/** \brief Flags for the path + */ +enum fib_path_flags +{ + FIB_API_PATH_FLAG_NONE = 0, + /* the path must resolve via an attached route */ + FIB_API_PATH_FLAG_RESOLVE_VIA_ATTACHED, + /* the path must resolve via a host route */ + FIB_API_PATH_FLAG_RESOLVE_VIA_HOST, +}; + +/* \brief A description of the 'next-hop' for a path + * this can be something that needs resolving like an IP address + * (into an adjacency or another FIB entry) or the index of another + * VPP object that was previously created (i.e. a UDP encap object) + */ +typedef fib_path_nh +{ + /* proto = IP[46] */ + vl_api_address_union_t address; + /* proto = MPLS */ + u32 via_label; + /* proto = ANY, determined by path type */ + u32 obj_id; + /* path-type = CLASSIFY */ + u32 classify_table_index; +}; + +enum fib_path_type +{ + /* Normal Paths */ + FIB_API_PATH_TYPE_NORMAL = 0, + /* local/for-us/receive = packet sent to VPP's L4 stack */ + FIB_API_PATH_TYPE_LOCAL, + /* packet is dropped */ + FIB_API_PATH_TYPE_DROP, + /* Packet is UDP encapped - set obj_id in fib_path_nh_id */ + FIB_API_PATH_TYPE_UDP_ENCAP, + /* Packet is BIER encapped - set obj_id in fib_path_nh_id */ + FIB_API_PATH_TYPE_BIER_IMP, + /* packet will generated ICMP unreach to sender */ + FIB_API_PATH_TYPE_ICMP_UNREACH, + /* packet will generated ICMP prohibt to sender */ + FIB_API_PATH_TYPE_ICMP_PROHIBIT, + /* perform a lookup based on the packet's source address */ + FIB_API_PATH_TYPE_SOURCE_LOOKUP, + /* Distributed Virtual router, packet is forwarded with the original + L2 header unchanged */ + FIB_API_PATH_TYPE_DVR, + /* packet's RX interface is changed */ + FIB_API_PATH_TYPE_INTERFACE_RX, + /* packet will be sent to a classify table */ + FIB_API_PATH_TYPE_CLASSIFY, +}; + /** \brief FIB path @param sw_if_index - index of the interface + @param table_id - The table ID in which to find the next-hop address + (for recursive routes, i.e. when the interface is + not given) @param weight - The weight, for UCMP @param preference - The preference of the path. lowest preference - is prefered - @param is_local - local if non-zero, else remote - @param is_drop - Drop the packet - @param is_unreach - Drop the packet and rate limit send ICMP unreachable - @param is_prohibit - Drop the packet and rate limit send ICMP prohibited - @param is_udp_encap - The path describes a UDP-o-IP encapsulation. - @param is_dvr - Does the route resolve via a DVR interface. - @param is_source_lookup - The the path is a deaggregate path (i.e. a lookup - in another table) is the lookup on the packet's - source address or destination. - @param afi - dpo_proto_t protocol that describes the next-hop address - @param via_label - The next-hop is a resolved via a local label - @param next_hop[16] - the next hop address - @param next_hop_id - Used when the path resolves via an object - that has a unique identifier. e.g. the UDP - encap object + is prefered + @param rpf-id - For paths that pop to multicast, this the the + RPF ID the packet will be given (0 and ~0 => unset) + @param type - the path type + @param flags - path flags + @param proto - protocol that describes the next-hop address + @param nh - the next-hop/net resolving object + @param n_labels - the number of labels present in the stack + @param label_stack - a stack of MPLS labels */ -typeonly define fib_path +typedef fib_path { u32 sw_if_index; u32 table_id; + u32 rpf_id; u8 weight; u8 preference; - u8 is_local; - u8 is_drop; - u8 is_udp_encap; - u8 is_unreach; - u8 is_prohibit; - u8 is_resolve_host; - 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; - u32 rpf_id; - u32 via_label; + + vl_api_fib_path_type_t type; + vl_api_fib_path_flags_t flags; + vl_api_fib_path_nh_proto_t proto; + vl_api_fib_path_nh_t nh; u8 n_labels; vl_api_fib_mpls_label_t label_stack[16]; }; diff --git a/src/vnet/fib/fib_types.c b/src/vnet/fib/fib_types.c index 7f0f13079ee..4b1280f6fa8 100644 --- a/src/vnet/fib/fib_types.c +++ b/src/vnet/fib/fib_types.c @@ -598,7 +598,14 @@ unformat_fib_route_path (unformat_input_t * input, va_list * args) rpath->frp_proto = DPO_PROTO_IP4; rpath->frp_flags = FIB_ROUTE_PATH_INTF_RX; } - else if (unformat (input, "out-labels")) + else if (unformat (input, "local")) + { + clib_memset (&rpath->frp_addr, 0, sizeof (rpath->frp_addr)); + rpath->frp_sw_if_index = ~0; + rpath->frp_weight = 1; + rpath->frp_flags |= FIB_ROUTE_PATH_LOCAL; + } + else if (unformat (input, "out-labels")) { while (unformat (input, "%U", unformat_mpls_unicast_label, &out_label)) @@ -615,6 +622,15 @@ unformat_fib_route_path (unformat_input_t * input, va_list * args) { rpath->frp_proto = *payload_proto; } + else if (unformat (input, "via")) + { + /* new path, back up and return */ + unformat_put_input (input); + unformat_put_input (input); + unformat_put_input (input); + unformat_put_input (input); + break; + } else { return (0); diff --git a/src/vnet/fib/fib_types.h b/src/vnet/fib/fib_types.h index 472ce888b4e..77b133fa9db 100644 --- a/src/vnet/fib/fib_types.h +++ b/src/vnet/fib/fib_types.h @@ -379,6 +379,10 @@ typedef enum fib_route_path_flags_t_ * A path that resolves via a DVR DPO */ FIB_ROUTE_PATH_DVR = (1 << 14), + + FIB_ROUTE_PATH_ICMP_UNREACH = (1 << 15), + FIB_ROUTE_PATH_ICMP_PROHIBIT = (1 << 16), + FIB_ROUTE_PATH_CLASSIFY = (1 << 17), } fib_route_path_flags_t; /** @@ -496,18 +500,24 @@ typedef struct fib_route_path_t_ { */ mpls_eos_bit_t frp_eos; }; - }; - union { /** - * The interface. - * Will be invalid for recursive paths. + * A path via a BIER imposition object. + * Present in an mfib path list */ - u32 frp_sw_if_index; - /** - * The RPF-ID - */ - fib_rpf_id_t frp_rpf_id; + index_t frp_bier_imp; }; + + /** + * The interface. + * Will be invalid for recursive paths. + */ + u32 frp_sw_if_index; + + /** + * The RPF-ID + */ + fib_rpf_id_t frp_rpf_id; + union { /** * The FIB index to lookup the nexthop @@ -523,7 +533,6 @@ typedef struct fib_route_path_t_ { * The outgoing MPLS label Stack. NULL implies no label. */ fib_mpls_label_t *frp_label_stack; - /** * Exclusive DPO */ @@ -540,20 +549,24 @@ typedef struct fib_route_path_t_ { bier_table_id_t frp_bier_tbl; /** - * A path via a BIER imposition object. - * Present in an mfib path list + * UDP encap ID */ - index_t frp_bier_imp; + u32 frp_udp_encap_id; /** - * UDP encap ID + * Classify table ID */ - u32 frp_udp_encap_id; + u32 frp_classify_table_id; /** * Resolving via a BIER Fmask */ index_t frp_bier_fmask; + + /** + * The DPO for use with exclusive paths + */ + dpo_id_t frp_dpo; }; /** * [un]equal cost path weight @@ -582,15 +595,6 @@ extern uword unformat_fib_route_path(unformat_input_t * input, va_list * args); #define FIB_ROUTE_PATH_HELP "[next-hop-address] [next-hop-interface] [next-hop-table <value>] [weight <value>] [preference <value>] [udp-encap-id <value>] [ip4-lookup-in-table <value>] [ip6-lookup-in-table <value>] [mpls-lookup-in-table <value>] [resolve-via-host] [resolve-via-connected] [rx-ip4 <interface>] [out-labels <value value value>]" /** - * @brief - * A representation of a fib path for fib_path_encode to convey the information to the caller - */ -typedef struct fib_route_path_encode_t_ { - fib_route_path_t rpath; - dpo_id_t dpo; -} fib_route_path_encode_t; - -/** * return code to control pat-hlist walk */ typedef enum fib_path_list_walk_rc_t_ diff --git a/src/vnet/fib/mpls_fib.c b/src/vnet/fib/mpls_fib.c index 6440689eab5..6f59eb3ee44 100644 --- a/src/vnet/fib/mpls_fib.c +++ b/src/vnet/fib/mpls_fib.c @@ -442,11 +442,24 @@ mpls_fib_show (vlib_main_t * vm, pool_foreach (fib_table, mpls_main.fibs, ({ + fib_source_t source; + u8 *s = NULL; + if (table_id >= 0 && table_id != fib_table->ft_table_id) continue; - vlib_cli_output (vm, "%v, fib_index %d", - fib_table->ft_desc, mpls_main.fibs - fib_table); + s = format (s, "%v, fib_index:%d locks:[", + fib_table->ft_desc, mpls_main.fibs - fib_table); + FOR_EACH_FIB_SOURCE(source) + { + if (0 != fib_table->ft_locks[source]) + { + s = format(s, "%U:%d, ", + format_fib_source, source, + fib_table->ft_locks[source]); + } + } + vlib_cli_output (vm, "%v]", s); if (MPLS_LABEL_INVALID == label) { diff --git a/src/vnet/geneve/geneve.c b/src/vnet/geneve/geneve.c index 8b773c1e009..b0c17e2a988 100644 --- a/src/vnet/geneve/geneve.c +++ b/src/vnet/geneve/geneve.c @@ -524,8 +524,9 @@ int vnet_geneve_add_del_tunnel .frp_addr = zero_addr, .frp_sw_if_index = 0xffffffff, .frp_fib_index = ~0, - .frp_weight = 0, + .frp_weight = 1, .frp_flags = FIB_ROUTE_PATH_LOCAL, + .frp_mitf_flags = MFIB_ITF_FLAG_FORWARD, }; const mfib_prefix_t mpfx = { .fp_proto = fp, @@ -539,17 +540,14 @@ int vnet_geneve_add_del_tunnel * - the accepting interface is that from the API */ mfib_table_entry_path_update (t->encap_fib_index, - &mpfx, - MFIB_SOURCE_GENEVE, - &path, MFIB_ITF_FLAG_FORWARD); + &mpfx, MFIB_SOURCE_GENEVE, &path); path.frp_sw_if_index = a->mcast_sw_if_index; path.frp_flags = FIB_ROUTE_PATH_FLAG_NONE; + path.frp_mitf_flags = MFIB_ITF_FLAG_ACCEPT; mfei = mfib_table_entry_path_update (t->encap_fib_index, &mpfx, - MFIB_SOURCE_GENEVE, - &path, - MFIB_ITF_FLAG_ACCEPT); + MFIB_SOURCE_GENEVE, &path); /* * Create the mcast adjacency to send traffic to the group diff --git a/src/vnet/ip/ip.api b/src/vnet/ip/ip.api index afb0960c78a..2dae4385602 100644 --- a/src/vnet/ip/ip.api +++ b/src/vnet/ip/ip.api @@ -20,15 +20,13 @@ called through a shared memory interface. */ -option version = "2.0.1"; -import "vnet/ip/ip_types.api"; +option version = "3.0.0"; + import "vnet/fib/fib_types.api"; import "vnet/ethernet/ethernet_types.api"; +import "vnet/mfib/mfib_types.api"; -/** \brief Add / del table request - A table can be added multiple times, but need be deleted only once. - @param client_index - opaque cookie to identify the sender - @param context - sender context, to match reply w/ request +/** \brief An IP table @param is_ipv6 - V4 or V6 table @param table_id - table ID associated with the route This table ID will apply to both the unicats @@ -37,70 +35,104 @@ import "vnet/ethernet/ethernet_types.api"; not set by the client, then VPP will generate something meaningfull. */ +typeonly define ip_table +{ + u32 table_id; + u8 is_ip6; + u8 name[64]; +}; + +/** \brief Add / del table request + A table can be added multiple times, but need be deleted only once. + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request +*/ autoreply define ip_table_add_del { u32 client_index; u32 context; - u32 table_id; - u8 is_ipv6; u8 is_add; - u8 name[64]; + vl_api_ip_table_t table; }; -/** \brief Dump IP fib table +/** \brief Dump IP all fib tables @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request */ -define ip_fib_dump +define ip_table_dump { u32 client_index; u32 context; }; /** \brief IP FIB table response - @param table_id - IP fib table id - @address_length - mask length - @address - ip4 prefix - @param count - the number of fib_path in path - @param path - array of of fib_path structures + @param context - sender context + @param table - description of the table */ -manual_endian manual_print define ip_fib_details +manual_endian manual_print define ip_table_details { u32 context; + vl_api_ip_table_t table; +}; + +/** \brief An IP route + @param table_id The IP table the route is in + @param stats_index The index of the route in the stats segment + @param prefix the prefix for the route + @param n_paths The number of paths the route has + @param paths The paths of the route +*/ +typeonly define ip_route +{ u32 table_id; - u8 table_name[64]; - u8 address_length; - u8 address[4]; - u32 count; u32 stats_index; - vl_api_fib_path_t path[count]; + vl_api_prefix_t prefix; + u8 n_paths; + vl_api_fib_path_t paths[n_paths]; }; -/** \brief Dump IP6 fib table +/** \brief Add / del route request @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request + @param is_multipath - Set to 1 if these paths will be added/removed + to/from the existing set, or 0 to replace + the existing set. + is_add=0 & is_multipath=0 implies delete all paths + @param is_add - Are the paths being added or removed */ -define ip6_fib_dump +define ip_route_add_del { u32 client_index; u32 context; + u8 is_add; + u8 is_multipath; + vl_api_ip_route_t route; +}; +define ip_route_add_del_reply +{ + u32 context; + i32 retval; + u32 stats_index; }; -/** \brief IP6 FIB table entry response - @param table_id - IP6 fib table id - @param address_length - mask length - @param address - ip6 prefix - @param count - the number of fib_path in path - @param path - array of of fib_path structures +/** \brief Dump IP routes from a table + @param client_index - opaque cookie to identify the sender + @param table - The table from which to dump routes (ony ID an AF are needed) */ -manual_endian manual_print define ip6_fib_details +define ip_route_dump { + u32 client_index; u32 context; - u32 table_id; - u8 table_name[64]; - u8 address_length; - u8 address[16]; - u32 count; - u32 stats_index; - vl_api_fib_path_t path[count]; + vl_api_ip_table_t table; +}; + +/** \brief IP FIB table entry response + @param route The route entry in the table +*/ +manual_endian manual_print define ip_route_details +{ + u32 context; + vl_api_ip_route_t route; }; /** \brief IP neighbor flags @@ -359,76 +391,33 @@ autoreply define sw_interface_ip6_enable_disable u8 enable; /* set to true if enable */ }; -/** \brief Add / del route request +/** \brief IPv6 set link local address on interface request @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request - @param sw_if_index - software index of the new vlan's parent interface - @param vrf_id - fib table /vrf associated with the route - @param lookup_in_vrf - - @param classify_table_index - - @param is_add - 1 if adding the route, 0 if deleting - @param is_drop - Drop the packet - @param is_unreach - Drop the packet and rate limit send ICMP unreachable - @param is_prohibit - Drop the packet and rate limit send ICMP prohibited - @param is_ipv6 - 0 if an ip4 route, else ip6 - @param is_local - The route will result in packets sent to VPP IP stack - @param is_udp_encap - The path describes a UDP-o-IP encapsulation. - @param is_classify - - @param is_multipath - Set to 1 if this is a multipath route, else 0 - @param is_dvr - Does the route resolve via a DVR interface. - @param is_source_lookup - The the path is a deaggregate path (i.e. a lookup - in another table) is the lookup on the packet's - source address or destination. - @param next_hop_weight - Weight for Unequal cost multi-path - @param next_hop_preference - Path that are up that have the best preference are - are used for forwarding. lower value is better. - @param next_hop_id - Used when the path resolves via an object that has a unique - identifier. - @param dst_address_length - - @param dst_address[16] - - @param next_hop_address[16] - - @param next_hop_n_out_labels - the number of labels in the label stack - @param next_hop_out_label_stack - the next-hop output label stack, outer most first - @param next_hop_via_label - The next-hop is a resolved via a local label + @param sw_if_index - interface to set link local on + @param address[] - the new link local address */ -define ip_add_del_route +autoreply define sw_interface_ip6_set_link_local_address { u32 client_index; u32 context; - u32 next_hop_sw_if_index; - u32 table_id; - u32 classify_table_index; - u32 next_hop_table_id; - u32 next_hop_id; - u8 is_add; - u8 is_drop; - u8 is_unreach; - u8 is_prohibit; - u8 is_ipv6; - u8 is_local; - u8 is_classify; - u8 is_multipath; - u8 is_resolve_host; - u8 is_resolve_attached; - u8 is_dvr; - u8 is_source_lookup; - u8 is_udp_encap; - u8 next_hop_weight; - u8 next_hop_preference; - u8 next_hop_proto; - u8 dst_address_length; - u8 dst_address[16]; - u8 next_hop_address[16]; - u8 next_hop_n_out_labels; - u32 next_hop_via_label; - vl_api_fib_mpls_label_t next_hop_out_label_stack[next_hop_n_out_labels]; -}; - -define ip_add_del_route_reply + u32 sw_if_index; + u8 address[16]; +}; + +/** \brief Dump IP multicast fib table + @param client_index - opaque cookie to identify the sender +*/ +define ip_mtable_dump { + u32 client_index; u32 context; - i32 retval; - u32 stats_index; +}; +define ip_mtable_details +{ + u32 client_index; + u32 context; + vl_api_ip_table_t table; }; /** \brief Add / del route request @@ -459,105 +448,55 @@ define ip_add_del_route_reply FIXME not complete yet */ -define ip_mroute_add_del +typedef ip_mroute { - u32 client_index; - u32 context; - u32 next_hop_sw_if_index; u32 table_id; u32 entry_flags; - u32 itf_flags; u32 rpf_id; - u32 bier_imp; - u16 grp_address_length; - u8 next_hop_afi; - u8 is_add; - u8 is_ipv6; - u8 is_local; - u8 grp_address[16]; - u8 src_address[16]; - u8 nh_address[16]; -}; - -define ip_mroute_add_del_reply -{ - u32 context; - i32 retval; - u32 stats_index; + vl_api_mprefix_t prefix; + u8 n_paths; + vl_api_mfib_path_t paths[n_paths]; }; -/** \brief Dump IP multicast fib table - @param client_index - opaque cookie to identify the sender -*/ -define ip_mfib_dump +define ip_mroute_add_del { u32 client_index; u32 context; + u8 is_add; + u8 is_multipath; + vl_api_ip_mroute_t route; }; - -/** \brief IP Multicast FIB table response - @param table_id - IP fib table id - @address_length - mask length - @grp_address - Group address/prefix - @src_address - Source address - @param count - the number of fib_path in path - @param path - array of of fib_path structures -*/ -typedef mfib_path -{ - vl_api_fib_path_t path; - u32 itf_flags; -}; - -manual_endian manual_print define ip_mfib_details +define ip_mroute_add_del_reply { u32 context; - u32 table_id; - u32 entry_flags; - u32 rpf_id; - u8 address_length; - u8 grp_address[4]; - u8 src_address[4]; - u32 count; + i32 retval; u32 stats_index; - vl_api_mfib_path_t path[count]; }; -/** \brief Dump IP6 multicast fib table - @param client_index - opaque cookie to identify the sender +/** \brief Dump IP multicast fib table + @param table - The table from which to dump routes (ony ID an AF are needed) */ -define ip6_mfib_dump +define ip_mroute_dump { u32 client_index; u32 context; + vl_api_ip_table_t table; }; -/** \brief IP6 Multicast FIB table response - @param table_id - IP fib table id - @address_length - mask length - @grp_address - Group address/prefix - @src_address - Source address - @param count - the number of fib_path in path - @param path - array of of fib_path structures +/** \brief IP Multicast Route Details + @param route - Details of the route */ -manual_endian manual_print define ip6_mfib_details +manual_endian manual_print define ip_mroute_details { u32 context; - u32 table_id; - u8 address_length; - u8 grp_address[16]; - u8 src_address[16]; - u32 count; - vl_api_mfib_path_t path[count]; + vl_api_ip_mroute_t route; }; define ip_address_details { u32 context; - u8 ip[16]; - u8 prefix_length; u32 sw_if_index; - u8 is_ipv6; + vl_api_prefix_t prefix; }; define ip_address_dump @@ -614,9 +553,7 @@ define mfib_signal_details u32 context; u32 sw_if_index; u32 table_id; - u16 grp_address_len; - u8 grp_address[16]; - u8 src_address[16]; + vl_api_mprefix_t prefix; u16 ip_packet_len; u8 ip_packet_data[256]; }; diff --git a/src/vnet/ip/ip_api.c b/src/vnet/ip/ip_api.c index bcbcf5ac8d4..4d2f0704ca3 100644 --- a/src/vnet/ip/ip_api.c +++ b/src/vnet/ip/ip_api.c @@ -29,18 +29,15 @@ #include <vnet/ip/ip_types_api.h> #include <vnet/ip/ip6_neighbor.h> #include <vnet/ip/ip_punt_drop.h> +#include <vnet/ip/ip_types_api.h> #include <vnet/fib/fib_table.h> #include <vnet/fib/fib_api.h> -#include <vnet/dpo/drop_dpo.h> -#include <vnet/dpo/receive_dpo.h> -#include <vnet/dpo/lookup_dpo.h> -#include <vnet/dpo/classify_dpo.h> -#include <vnet/dpo/ip_null_dpo.h> #include <vnet/ethernet/arp_packet.h> #include <vnet/mfib/ip6_mfib.h> #include <vnet/mfib/ip4_mfib.h> #include <vnet/mfib/mfib_signal.h> #include <vnet/mfib/mfib_entry.h> +#include <vnet/mfib/mfib_api.h> #include <vnet/ip/ip_source_and_port_range_check.h> #include <vnet/fib/ip4_fib.h> #include <vnet/fib/ip6_fib.h> @@ -71,10 +68,10 @@ #define foreach_ip_api_msg \ -_(IP_FIB_DUMP, ip_fib_dump) \ -_(IP6_FIB_DUMP, ip6_fib_dump) \ -_(IP_MFIB_DUMP, ip_mfib_dump) \ -_(IP6_MFIB_DUMP, ip6_mfib_dump) \ +_(IP_TABLE_DUMP, ip_table_dump) \ +_(IP_ROUTE_DUMP, ip_route_dump) \ +_(IP_MTABLE_DUMP, ip_mtable_dump) \ +_(IP_MROUTE_DUMP, ip_mroute_dump) \ _(IP_NEIGHBOR_DUMP, ip_neighbor_dump) \ _(IP_MROUTE_ADD_DEL, ip_mroute_add_del) \ _(MFIB_SIGNAL_DUMP, mfib_signal_dump) \ @@ -93,7 +90,7 @@ _(PROXY_ARP_DUMP, proxy_arp_dump) \ _(PROXY_ARP_INTFC_ENABLE_DISABLE, proxy_arp_intfc_enable_disable) \ _(PROXY_ARP_INTFC_DUMP, proxy_arp_intfc_dump) \ _(RESET_FIB, reset_fib) \ -_(IP_ADD_DEL_ROUTE, ip_add_del_route) \ +_(IP_ROUTE_ADD_DEL, ip_route_add_del) \ _(IP_TABLE_ADD_DEL, ip_table_add_del) \ _(IP_PUNT_POLICE, ip_punt_police) \ _(IP_PUNT_REDIRECT, ip_punt_redirect) \ @@ -211,137 +208,104 @@ vl_api_ip_neighbor_dump_t_handler (vl_api_ip_neighbor_dump_t * mp) } static void -send_ip_fib_details (vpe_api_main_t * am, - vl_api_registration_t * reg, - const fib_table_t * table, - const fib_prefix_t * pfx, - fib_route_path_encode_t * api_rpaths, u32 context) -{ - vl_api_ip_fib_details_t *mp; - fib_route_path_encode_t *api_rpath; - vl_api_fib_path_t *fp; - int path_count; +send_ip_table_details (vpe_api_main_t * am, + vl_api_registration_t * reg, + u32 context, const fib_table_t * table) +{ + vl_api_ip_table_details_t *mp; - path_count = vec_len (api_rpaths); - mp = vl_msg_api_alloc (sizeof (*mp) + path_count * sizeof (*fp)); + mp = vl_msg_api_alloc (sizeof (*mp)); if (!mp) return; clib_memset (mp, 0, sizeof (*mp)); - mp->_vl_msg_id = ntohs (VL_API_IP_FIB_DETAILS); + mp->_vl_msg_id = ntohs (VL_API_IP_TABLE_DETAILS); mp->context = context; - mp->table_id = htonl (table->ft_table_id); - memcpy (mp->table_name, table->ft_desc, - clib_min (vec_len (table->ft_desc), sizeof (mp->table_name))); - mp->address_length = pfx->fp_len; - memcpy (mp->address, &pfx->fp_addr.ip4, sizeof (pfx->fp_addr.ip4)); - mp->stats_index = - htonl (fib_table_entry_get_stats_index (table->ft_index, pfx)); - - mp->count = htonl (path_count); - fp = mp->path; - vec_foreach (api_rpath, api_rpaths) - { - fib_api_path_encode (api_rpath, fp); - fp++; - } + mp->table.is_ip6 = (table->ft_proto == FIB_PROTOCOL_IP6); + mp->table.table_id = htonl (table->ft_table_id); + memcpy (mp->table.name, table->ft_desc, + clib_min (vec_len (table->ft_desc), sizeof (mp->table.name))); vl_api_send_msg (reg, (u8 *) mp); } -typedef struct vl_api_ip_fib_dump_walk_ctx_t_ -{ - fib_node_index_t *feis; -} vl_api_ip_fib_dump_walk_ctx_t; - -static fib_table_walk_rc_t -vl_api_ip_fib_dump_walk (fib_node_index_t fei, void *arg) -{ - vl_api_ip_fib_dump_walk_ctx_t *ctx = arg; - - vec_add1 (ctx->feis, fei); - - return (FIB_TABLE_WALK_CONTINUE); -} - static void -vl_api_ip_fib_dump_t_handler (vl_api_ip_fib_dump_t * mp) +vl_api_ip_table_dump_t_handler (vl_api_ip_table_dump_t * mp) { vpe_api_main_t *am = &vpe_api_main; vl_api_registration_t *reg; - ip4_main_t *im = &ip4_main; fib_table_t *fib_table; - fib_node_index_t *lfeip; - const fib_prefix_t *pfx; - u32 fib_index; - fib_route_path_encode_t *api_rpaths; - vl_api_ip_fib_dump_walk_ctx_t ctx = { - .feis = NULL, - }; reg = vl_api_client_index_to_registration (mp->client_index); if (!reg) return; /* *INDENT-OFF* */ - pool_foreach (fib_table, im->fibs, + pool_foreach (fib_table, ip4_main.fibs, ({ - fib_table_walk(fib_table->ft_index, - FIB_PROTOCOL_IP4, - vl_api_ip_fib_dump_walk, - &ctx); + send_ip_table_details(am, reg, mp->context, fib_table); + })); + pool_foreach (fib_table, ip6_main.fibs, + ({ + /* don't send link locals */ + if (fib_table->ft_flags & FIB_TABLE_FLAG_IP6_LL) + continue; + send_ip_table_details(am, reg, mp->context, fib_table); })); /* *INDENT-ON* */ +} - vec_sort_with_function (ctx.feis, fib_entry_cmp_for_sort); +typedef struct vl_api_ip_fib_dump_walk_ctx_t_ +{ + fib_node_index_t *feis; +} vl_api_ip_fib_dump_walk_ctx_t; - vec_foreach (lfeip, ctx.feis) - { - pfx = fib_entry_get_prefix (*lfeip); - fib_index = fib_entry_get_fib_index (*lfeip); - fib_table = fib_table_get (fib_index, pfx->fp_proto); - api_rpaths = NULL; - fib_entry_encode (*lfeip, &api_rpaths); - send_ip_fib_details (am, reg, fib_table, pfx, api_rpaths, mp->context); - vec_free (api_rpaths); - } +static fib_table_walk_rc_t +vl_api_ip_fib_dump_walk (fib_node_index_t fei, void *arg) +{ + vl_api_ip_fib_dump_walk_ctx_t *ctx = arg; - vec_free (ctx.feis); + vec_add1 (ctx->feis, fei); + + return (FIB_TABLE_WALK_CONTINUE); } static void -send_ip6_fib_details (vpe_api_main_t * am, - vl_api_registration_t * reg, - const fib_table_t * table, - const fib_prefix_t * pfx, - fib_route_path_encode_t * api_rpaths, u32 context) -{ - vl_api_ip6_fib_details_t *mp; - fib_route_path_encode_t *api_rpath; +send_ip_route_details (vpe_api_main_t * am, + vl_api_registration_t * reg, + u32 context, fib_node_index_t fib_entry_index) +{ + fib_route_path_t *rpaths, *rpath; + vl_api_ip_route_details_t *mp; + const fib_prefix_t *pfx; vl_api_fib_path_t *fp; int path_count; - path_count = vec_len (api_rpaths); + rpaths = NULL; + pfx = fib_entry_get_prefix (fib_entry_index); + rpaths = fib_entry_encode (fib_entry_index); + + path_count = vec_len (rpaths); mp = vl_msg_api_alloc (sizeof (*mp) + path_count * sizeof (*fp)); if (!mp) return; clib_memset (mp, 0, sizeof (*mp)); - mp->_vl_msg_id = ntohs (VL_API_IP6_FIB_DETAILS); + mp->_vl_msg_id = ntohs (VL_API_IP_ROUTE_DETAILS); mp->context = context; - mp->table_id = htonl (table->ft_table_id); - mp->address_length = pfx->fp_len; - memcpy (mp->address, &pfx->fp_addr.ip6, sizeof (pfx->fp_addr.ip6)); - memcpy (mp->table_name, table->ft_desc, - clib_min (vec_len (table->ft_desc), sizeof (mp->table_name))); - mp->stats_index = - htonl (fib_table_entry_get_stats_index (table->ft_index, pfx)); - - mp->count = htonl (path_count); - fp = mp->path; - vec_foreach (api_rpath, api_rpaths) + ip_prefix_encode (pfx, &mp->route.prefix); + mp->route.table_id = + htonl (fib_table_get_table_id + (fib_entry_get_fib_index (fib_entry_index), pfx->fp_proto)); + mp->route.n_paths = path_count; + mp->route.stats_index = + htonl (fib_table_entry_get_stats_index + (fib_entry_get_fib_index (fib_entry_index), pfx)); + + fp = mp->route.paths; + vec_foreach (rpath, rpaths) { - fib_api_path_encode (api_rpath, fp); + fib_api_path_encode (rpath, fp); fp++; } @@ -353,232 +317,144 @@ typedef struct apt_ip6_fib_show_ctx_t_ fib_node_index_t *entries; } api_ip6_fib_show_ctx_t; -static fib_table_walk_rc_t -api_ip6_fib_table_put_entries (fib_node_index_t fei, void *arg) -{ - api_ip6_fib_show_ctx_t *ctx = arg; - - vec_add1 (ctx->entries, fei); - - return (FIB_TABLE_WALK_CONTINUE); -} - static void -api_ip6_fib_table_get_all (vl_api_registration_t * reg, - vl_api_ip6_fib_dump_t * mp, - fib_table_t * fib_table) +vl_api_ip_route_dump_t_handler (vl_api_ip_route_dump_t * mp) { vpe_api_main_t *am = &vpe_api_main; fib_node_index_t *fib_entry_index; - api_ip6_fib_show_ctx_t ctx = { - .entries = NULL, - }; - fib_route_path_encode_t *api_rpaths; - const fib_prefix_t *pfx; - - ip6_fib_table_walk (fib_table->ft_index, - api_ip6_fib_table_put_entries, &ctx); - - vec_sort_with_function (ctx.entries, fib_entry_cmp_for_sort); - - vec_foreach (fib_entry_index, ctx.entries) - { - pfx = fib_entry_get_prefix (*fib_entry_index); - api_rpaths = NULL; - fib_entry_encode (*fib_entry_index, &api_rpaths); - send_ip6_fib_details (am, reg, fib_table, pfx, api_rpaths, mp->context); - vec_free (api_rpaths); - } - - vec_free (ctx.entries); -} - -static void -vl_api_ip6_fib_dump_t_handler (vl_api_ip6_fib_dump_t * mp) -{ vl_api_registration_t *reg; - ip6_main_t *im6 = &ip6_main; - fib_table_t *fib_table; + fib_protocol_t fproto; + u32 fib_index; reg = vl_api_client_index_to_registration (mp->client_index); if (!reg) return; - /* *INDENT-OFF* */ - pool_foreach (fib_table, im6->fibs, - ({ - /* don't send link locals */ - if (fib_table->ft_flags & FIB_TABLE_FLAG_IP6_LL) - continue; - - api_ip6_fib_table_get_all(reg, mp, fib_table); - })); - /* *INDENT-ON* */ -} - -static void -send_ip_mfib_details (vl_api_registration_t * reg, - u32 context, u32 table_id, fib_node_index_t mfei) -{ - fib_route_path_encode_t *api_rpath, *api_rpaths = NULL; - vl_api_ip_mfib_details_t *mp; - const mfib_prefix_t *pfx; - mfib_entry_t *mfib_entry; - vl_api_mfib_path_t *fp; - int path_count; + vl_api_ip_fib_dump_walk_ctx_t ctx = { + .feis = NULL, + }; - mfib_entry = mfib_entry_get (mfei); - pfx = mfib_entry_get_prefix (mfei); - mfib_entry_encode (mfei, &api_rpaths); + fproto = (mp->table.is_ip6 ? FIB_PROTOCOL_IP6 : FIB_PROTOCOL_IP4); + fib_index = fib_table_find (fproto, ntohl (mp->table.table_id)); - path_count = vec_len (api_rpaths); - mp = vl_msg_api_alloc (sizeof (*mp) + path_count * sizeof (*fp)); - if (!mp) + if (INDEX_INVALID == fib_index) return; - clib_memset (mp, 0, sizeof (*mp)); - mp->_vl_msg_id = ntohs (VL_API_IP_MFIB_DETAILS); - mp->context = context; - mp->rpf_id = mfib_entry->mfe_rpf_id; - mp->entry_flags = mfib_entry->mfe_flags; - mp->table_id = htonl (table_id); - mp->address_length = pfx->fp_len; - memcpy (mp->grp_address, &pfx->fp_grp_addr.ip4, - sizeof (pfx->fp_grp_addr.ip4)); - memcpy (mp->src_address, &pfx->fp_src_addr.ip4, - sizeof (pfx->fp_src_addr.ip4)); - - mp->count = htonl (path_count); - fp = mp->path; - vec_foreach (api_rpath, api_rpaths) + fib_table_walk (fib_index, fproto, vl_api_ip_fib_dump_walk, &ctx); + + vec_foreach (fib_entry_index, ctx.feis) { - fib_api_path_encode (api_rpath, &fp->path); - fp->itf_flags = ntohl (api_rpath->rpath.frp_mitf_flags); - fp++; + send_ip_route_details (am, reg, mp->context, *fib_entry_index); } - vec_free (api_rpaths); - vl_api_send_msg (reg, (u8 *) mp); + vec_free (ctx.feis); } -typedef struct vl_api_ip_mfib_dump_ctc_t_ +static void +send_ip_mtable_details (vl_api_registration_t * reg, + u32 context, const mfib_table_t * mfib_table) { - fib_node_index_t *entries; -} vl_api_ip_mfib_dump_ctc_t; + vl_api_ip_mtable_details_t *mp; -static int -vl_api_ip_mfib_table_dump_walk (fib_node_index_t fei, void *arg) -{ - vl_api_ip_mfib_dump_ctc_t *ctx = arg; + mp = vl_msg_api_alloc (sizeof (*mp)); + if (!mp) + return; + memset (mp, 0, sizeof (*mp)); + mp->_vl_msg_id = ntohs (VL_API_IP_MTABLE_DETAILS); + mp->context = context; - vec_add1 (ctx->entries, fei); + mp->table.table_id = htonl (mfib_table->mft_table_id); + mp->table.is_ip6 = (FIB_PROTOCOL_IP6 == mfib_table->mft_proto); - return (0); + vl_api_send_msg (reg, (u8 *) mp); } static void -vl_api_ip_mfib_dump_t_handler (vl_api_ip_mfib_dump_t * mp) +vl_api_ip_mtable_dump_t_handler (vl_api_ip_mtable_dump_t * mp) { vl_api_registration_t *reg; - ip4_main_t *im = &ip4_main; mfib_table_t *mfib_table; - fib_node_index_t *mfeip; - vl_api_ip_mfib_dump_ctc_t ctx = { - .entries = NULL, - }; reg = vl_api_client_index_to_registration (mp->client_index); if (!reg) return; /* *INDENT-OFF* */ - pool_foreach (mfib_table, im->mfibs, + pool_foreach (mfib_table, ip4_main.mfibs, + ({ + send_ip_mtable_details (reg, mp->context, mfib_table); + })); + pool_foreach (mfib_table, ip6_main.mfibs, ({ - ip4_mfib_table_walk(&mfib_table->v4, - vl_api_ip_mfib_table_dump_walk, - &ctx); + send_ip_mtable_details (reg, mp->context, mfib_table); + })); + /* *INDENT-ON* */ +} - vec_sort_with_function (ctx.entries, mfib_entry_cmp_for_sort); +typedef struct vl_api_ip_mfib_dump_ctx_t_ +{ + fib_node_index_t *entries; +} vl_api_ip_mfib_dump_ctx_t; - vec_foreach (mfeip, ctx.entries) - { - send_ip_mfib_details (reg, mp->context, - mfib_table->mft_table_id, - *mfeip); - } - vec_reset_length (ctx.entries); +static int +mfib_route_dump_walk (fib_node_index_t fei, void *arg) +{ + vl_api_ip_mfib_dump_ctx_t *ctx = arg; - })); - /* *INDENT-ON* */ + vec_add1 (ctx->entries, fei); - vec_free (ctx.entries); + return (0); } static void -send_ip6_mfib_details (vpe_api_main_t * am, - vl_api_registration_t * reg, - u32 table_id, - const mfib_prefix_t * pfx, - fib_route_path_encode_t * api_rpaths, u32 context) +send_ip_mroute_details (vpe_api_main_t * am, + vl_api_registration_t * reg, + u32 context, fib_node_index_t mfib_entry_index) { - vl_api_ip6_mfib_details_t *mp; - fib_route_path_encode_t *api_rpath; + fib_route_path_t *rpaths, *rpath; + vl_api_ip_mroute_details_t *mp; + const mfib_prefix_t *pfx; vl_api_mfib_path_t *fp; int path_count; - path_count = vec_len (api_rpaths); + rpaths = NULL; + pfx = mfib_entry_get_prefix (mfib_entry_index); + rpaths = mfib_entry_encode (mfib_entry_index); + + path_count = vec_len (rpaths); mp = vl_msg_api_alloc (sizeof (*mp) + path_count * sizeof (*fp)); if (!mp) return; clib_memset (mp, 0, sizeof (*mp)); - mp->_vl_msg_id = ntohs (VL_API_IP6_MFIB_DETAILS); + mp->_vl_msg_id = ntohs (VL_API_IP_MROUTE_DETAILS); mp->context = context; - mp->table_id = htonl (table_id); - mp->address_length = pfx->fp_len; - memcpy (mp->grp_address, &pfx->fp_grp_addr.ip6, - sizeof (pfx->fp_grp_addr.ip6)); - memcpy (mp->src_address, &pfx->fp_src_addr.ip6, - sizeof (pfx->fp_src_addr.ip6)); - - mp->count = htonl (path_count); - fp = mp->path; - vec_foreach (api_rpath, api_rpaths) + ip_mprefix_encode (pfx, &mp->route.prefix); + mp->route.table_id = + htonl (mfib_table_get_table_id + (mfib_entry_get_fib_index (mfib_entry_index), pfx->fp_proto)); + mp->route.n_paths = htonl (path_count); + fp = mp->route.paths; + vec_foreach (rpath, rpaths) { - fib_api_path_encode (api_rpath, &fp->path); - fp->itf_flags = ntohl (api_rpath->rpath.frp_mitf_flags); + mfib_api_path_encode (rpath, fp); fp++; } vl_api_send_msg (reg, (u8 *) mp); -} - -typedef struct vl_api_ip6_mfib_dump_ctc_t_ -{ - fib_node_index_t *entries; -} vl_api_ip6_mfib_dump_ctc_t; - -static int -vl_api_ip6_mfib_table_dump_walk (fib_node_index_t fei, void *arg) -{ - vl_api_ip6_mfib_dump_ctc_t *ctx = arg; - - vec_add1 (ctx->entries, fei); - - return (0); + vec_free (rpaths); } static void -vl_api_ip6_mfib_dump_t_handler (vl_api_ip6_mfib_dump_t * mp) +vl_api_ip_mroute_dump_t_handler (vl_api_ip_mroute_dump_t * mp) { vpe_api_main_t *am = &vpe_api_main; vl_api_registration_t *reg; - ip6_main_t *im = &ip6_main; - mfib_table_t *mfib_table; - const mfib_prefix_t *pfx; fib_node_index_t *mfeip; - fib_route_path_encode_t *api_rpaths = NULL; - vl_api_ip6_mfib_dump_ctc_t ctx = { + fib_protocol_t fproto; + u32 fib_index; + + vl_api_ip_mfib_dump_ctx_t ctx = { .entries = NULL, }; @@ -586,33 +462,22 @@ vl_api_ip6_mfib_dump_t_handler (vl_api_ip6_mfib_dump_t * mp) if (!reg) return; + fproto = fib_ip_proto (mp->table.is_ip6); + fib_index = mfib_table_find (fproto, ntohl (mp->table.table_id)); - /* *INDENT-OFF* */ - pool_foreach (mfib_table, im->mfibs, - ({ - ip6_mfib_table_walk(&mfib_table->v6, - vl_api_ip6_mfib_table_dump_walk, - &ctx); + if (INDEX_INVALID == fib_index) + return; - vec_sort_with_function (ctx.entries, mfib_entry_cmp_for_sort); + mfib_table_walk (fib_index, fproto, mfib_route_dump_walk, &ctx); - vec_foreach(mfeip, ctx.entries) - { - pfx = mfib_entry_get_prefix (*mfeip); - mfib_entry_encode (*mfeip, &api_rpaths); - send_ip6_mfib_details (am, reg, - mfib_table->mft_table_id, - pfx, api_rpaths, - mp->context); - } - vec_reset_length (api_rpaths); - vec_reset_length (ctx.entries); + vec_sort_with_function (ctx.entries, mfib_entry_cmp_for_sort); - })); - /* *INDENT-ON* */ + vec_foreach (mfeip, ctx.entries) + { + send_ip_mroute_details (am, reg, mp->context, *mfeip); + } vec_free (ctx.entries); - vec_free (api_rpaths); } static void @@ -698,7 +563,7 @@ vl_api_ip_neighbor_add_del_t_handler (vl_api_ip_neighbor_add_del_t * mp, ip46_address_t ip; mac_address_t mac; ip46_type_t type; - int rv = 0; + int rv; VALIDATE_SW_IF_INDEX ((&mp->neighbor)); @@ -767,13 +632,14 @@ void vl_api_ip_table_add_del_t_handler (vl_api_ip_table_add_del_t * mp) { vl_api_ip_table_add_del_reply_t *rmp; - fib_protocol_t fproto = (mp->is_ipv6 ? FIB_PROTOCOL_IP6 : FIB_PROTOCOL_IP4); - u32 table_id = ntohl (mp->table_id); + fib_protocol_t fproto = (mp->table.is_ip6 ? + FIB_PROTOCOL_IP6 : FIB_PROTOCOL_IP4); + u32 table_id = ntohl (mp->table.table_id); int rv = 0; if (mp->is_add) { - ip_table_create (fproto, table_id, 1, mp->name); + ip_table_create (fproto, table_id, 1, mp->table.name); } else { @@ -783,398 +649,71 @@ vl_api_ip_table_add_del_t_handler (vl_api_ip_table_add_del_t * mp) REPLY_MACRO (VL_API_IP_TABLE_ADD_DEL_REPLY); } -int -add_del_route_t_handler (u8 is_multipath, - u8 is_add, - u8 is_drop, - u8 is_unreach, - u8 is_prohibit, - u8 is_local, - u8 is_multicast, - u8 is_classify, - u32 classify_table_index, - u8 is_resolve_host, - u8 is_resolve_attached, - u8 is_interface_rx, - u8 is_rpf_id, - u8 is_dvr, - u8 is_source_lookup, - u8 is_udp_encap, - u32 fib_index, - const fib_prefix_t * prefix, - dpo_proto_t next_hop_proto, - const ip46_address_t * next_hop, - u32 next_hop_id, - u32 next_hop_sw_if_index, - u8 next_hop_fib_index, - u16 next_hop_weight, - u16 next_hop_preference, - mpls_label_t next_hop_via_label, - fib_mpls_label_t * next_hop_out_label_stack) -{ - vnet_classify_main_t *cm = &vnet_classify_main; - fib_route_path_flags_t path_flags = FIB_ROUTE_PATH_FLAG_NONE; - fib_route_path_t path = { - .frp_proto = next_hop_proto, - .frp_addr = (NULL == next_hop ? zero_addr : *next_hop), - .frp_sw_if_index = next_hop_sw_if_index, - .frp_fib_index = next_hop_fib_index, - .frp_weight = next_hop_weight, - .frp_preference = next_hop_preference, - .frp_label_stack = next_hop_out_label_stack, - }; - fib_route_path_t *paths = NULL; - fib_entry_flag_t entry_flags = FIB_ENTRY_FLAG_NONE; - - /* - * the special INVALID label means we are not recursing via a - * label. Exp-null value is never a valid via-label so that - * also means it's not a via-label and means clients that set - * it to 0 by default get the expected behaviour - */ - if ((MPLS_LABEL_INVALID != next_hop_via_label) && (0 != next_hop_via_label)) - { - path.frp_proto = DPO_PROTO_MPLS; - path.frp_local_label = next_hop_via_label; - path.frp_eos = MPLS_NON_EOS; - } - if (is_local) - { - path_flags |= FIB_ROUTE_PATH_LOCAL; - if (~0 != next_hop_sw_if_index) - { - entry_flags |= (FIB_ENTRY_FLAG_CONNECTED | FIB_ENTRY_FLAG_LOCAL); - } - } - if (is_dvr) - path_flags |= FIB_ROUTE_PATH_DVR; - if (is_resolve_host) - path_flags |= FIB_ROUTE_PATH_RESOLVE_VIA_HOST; - if (is_resolve_attached) - path_flags |= FIB_ROUTE_PATH_RESOLVE_VIA_ATTACHED; - if (is_interface_rx) - path_flags |= FIB_ROUTE_PATH_INTF_RX; - if (is_rpf_id) - path_flags |= FIB_ROUTE_PATH_RPF_ID; - if (is_source_lookup) - path_flags |= FIB_ROUTE_PATH_SOURCE_LOOKUP; - if (is_multicast) - entry_flags |= FIB_ENTRY_FLAG_MULTICAST; - if (is_udp_encap) - { - path_flags |= FIB_ROUTE_PATH_UDP_ENCAP; - path.frp_udp_encap_id = next_hop_id; - } - if (path.frp_sw_if_index == ~0 && ip46_address_is_zero (&path.frp_addr) - && path.frp_fib_index != ~0) - { - path_flags |= FIB_ROUTE_PATH_DEAG; - } - - path.frp_flags = path_flags; - - if (is_drop || (is_local && (~0 == next_hop_sw_if_index)) || - is_classify || is_unreach || is_prohibit) - { - /* - * special route types that link directly to the adj - */ - if (is_add) - { - dpo_id_t dpo = DPO_INVALID; - dpo_proto_t dproto; - - dproto = fib_proto_to_dpo (prefix->fp_proto); - - if (is_drop) - ip_null_dpo_add_and_lock (dproto, IP_NULL_ACTION_NONE, &dpo); - else if (is_local) - receive_dpo_add_or_lock (dproto, ~0, NULL, &dpo); - else if (is_unreach) - ip_null_dpo_add_and_lock (dproto, - IP_NULL_ACTION_SEND_ICMP_UNREACH, &dpo); - else if (is_prohibit) - ip_null_dpo_add_and_lock (dproto, - IP_NULL_ACTION_SEND_ICMP_PROHIBIT, - &dpo); - else if (is_classify) - { - if (pool_is_free_index (cm->tables, - ntohl (classify_table_index))) - { - return VNET_API_ERROR_NO_SUCH_TABLE; - } - - dpo_set (&dpo, DPO_CLASSIFY, dproto, - classify_dpo_create (dproto, - ntohl (classify_table_index))); - } - else - { - return VNET_API_ERROR_NO_SUCH_TABLE; - } - - fib_table_entry_special_dpo_update (fib_index, - prefix, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_EXCLUSIVE, &dpo); - dpo_reset (&dpo); - } - else - { - fib_table_entry_special_remove (fib_index, prefix, FIB_SOURCE_API); - } - } - else if (is_multipath) - { - vec_add1 (paths, path); - - if (is_add) - fib_table_entry_path_add2 (fib_index, - prefix, - FIB_SOURCE_API, entry_flags, paths); - else - fib_table_entry_path_remove2 (fib_index, - prefix, FIB_SOURCE_API, paths); - - vec_free (paths); - } - else - { - if (is_add) - { - vec_add1 (paths, path); - fib_table_entry_update (fib_index, - prefix, FIB_SOURCE_API, entry_flags, paths); - vec_free (paths); - } - else - { - fib_table_entry_delete (fib_index, prefix, FIB_SOURCE_API); - } - } - - return (0); -} - -int -add_del_route_check (fib_protocol_t table_proto, - u32 table_id, - u32 next_hop_sw_if_index, - dpo_proto_t next_hop_table_proto, - u32 next_hop_table_id, - u8 is_rpf_id, u32 * fib_index, u32 * next_hop_fib_index) -{ - vnet_main_t *vnm = vnet_get_main (); - - *fib_index = fib_table_find (table_proto, ntohl (table_id)); - if (~0 == *fib_index) - { - /* No such VRF, and we weren't asked to create one */ - return VNET_API_ERROR_NO_SUCH_FIB; - } - - if (!is_rpf_id && ~0 != ntohl (next_hop_sw_if_index)) - { - if (pool_is_free_index (vnm->interface_main.sw_interfaces, - ntohl (next_hop_sw_if_index))) - { - return VNET_API_ERROR_NO_MATCHING_INTERFACE; - } - } - else - { - fib_protocol_t fib_nh_proto; - - if (next_hop_table_proto > DPO_PROTO_MPLS) - return (0); - - fib_nh_proto = dpo_proto_to_fib (next_hop_table_proto); - - if (is_rpf_id) - *next_hop_fib_index = mfib_table_find (fib_nh_proto, - ntohl (next_hop_table_id)); - else - *next_hop_fib_index = fib_table_find (fib_nh_proto, - ntohl (next_hop_table_id)); - - if (~0 == *next_hop_fib_index) - { - /* No such VRF, and we weren't asked to create one */ - return VNET_API_ERROR_NO_SUCH_FIB; - } - } - - return (0); -} - static int -ip4_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp, - u32 * stats_index) +ip_route_add_del_t_handler (vl_api_ip_route_add_del_t * mp, u32 * stats_index) { - u32 fib_index, next_hop_fib_index; - fib_mpls_label_t *label_stack = NULL; - int rv, ii, n_labels;; + fib_route_path_t *rpaths = NULL, *rpath; + fib_entry_flag_t entry_flags; + vl_api_fib_path_t *apath; + fib_prefix_t pfx; + u32 fib_index; + int rv, ii; - rv = add_del_route_check (FIB_PROTOCOL_IP4, - mp->table_id, - mp->next_hop_sw_if_index, - DPO_PROTO_IP4, - mp->next_hop_table_id, - 0, &fib_index, &next_hop_fib_index); + entry_flags = FIB_ENTRY_FLAG_NONE; + ip_prefix_decode (&mp->route.prefix, &pfx); + rv = fib_api_table_id_decode (pfx.fp_proto, + ntohl (mp->route.table_id), &fib_index); if (0 != rv) - return (rv); - - fib_prefix_t pfx = { - .fp_len = mp->dst_address_length, - .fp_proto = FIB_PROTOCOL_IP4, - }; - clib_memcpy (&pfx.fp_addr.ip4, mp->dst_address, sizeof (pfx.fp_addr.ip4)); - - ip46_address_t nh; - clib_memset (&nh, 0, sizeof (nh)); - memcpy (&nh.ip4, mp->next_hop_address, sizeof (nh.ip4)); + goto out; - n_labels = mp->next_hop_n_out_labels; - if (n_labels == 0) - ; - else + if (0 == mp->route.n_paths) { - vec_validate (label_stack, n_labels - 1); - for (ii = 0; ii < n_labels; ii++) - { - label_stack[ii].fml_value = - ntohl (mp->next_hop_out_label_stack[ii].label); - label_stack[ii].fml_ttl = mp->next_hop_out_label_stack[ii].ttl; - label_stack[ii].fml_exp = mp->next_hop_out_label_stack[ii].exp; - label_stack[ii].fml_mode = - (mp->next_hop_out_label_stack[ii].is_uniform ? - FIB_MPLS_LSP_MODE_UNIFORM : FIB_MPLS_LSP_MODE_PIPE); - } + rv = VNET_API_ERROR_NO_PATHS_IN_ROUTE; + goto out; } - rv = add_del_route_t_handler (mp->is_multipath, - mp->is_add, - mp->is_drop, - mp->is_unreach, - mp->is_prohibit, - mp->is_local, 0, - mp->is_classify, - mp->classify_table_index, - mp->is_resolve_host, - mp->is_resolve_attached, 0, 0, - mp->is_dvr, - mp->is_source_lookup, - mp->is_udp_encap, - fib_index, &pfx, DPO_PROTO_IP4, - &nh, - ntohl (mp->next_hop_id), - ntohl (mp->next_hop_sw_if_index), - next_hop_fib_index, - mp->next_hop_weight, - mp->next_hop_preference, - ntohl (mp->next_hop_via_label), label_stack); - - if (mp->is_add && 0 == rv) - *stats_index = fib_table_entry_get_stats_index (fib_index, &pfx); - - return (rv); -} - -static int -ip6_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp, - u32 * stats_index) -{ - fib_mpls_label_t *label_stack = NULL; - u32 fib_index, next_hop_fib_index; - int rv, ii, n_labels;; + vec_validate (rpaths, mp->route.n_paths - 1); - rv = add_del_route_check (FIB_PROTOCOL_IP6, - mp->table_id, - mp->next_hop_sw_if_index, - DPO_PROTO_IP6, - mp->next_hop_table_id, - 0, &fib_index, &next_hop_fib_index); + for (ii = 0; ii < mp->route.n_paths; ii++) + { + apath = &mp->route.paths[ii]; + rpath = &rpaths[ii]; - if (0 != rv) - return (rv); + rv = fib_api_path_decode (apath, rpath); - fib_prefix_t pfx = { - .fp_len = mp->dst_address_length, - .fp_proto = FIB_PROTOCOL_IP6, - }; - clib_memcpy (&pfx.fp_addr.ip6, mp->dst_address, sizeof (pfx.fp_addr.ip6)); - - ip46_address_t nh; - clib_memset (&nh, 0, sizeof (nh)); - memcpy (&nh.ip6, mp->next_hop_address, sizeof (nh.ip6)); + if ((rpath->frp_flags & FIB_ROUTE_PATH_LOCAL) && + (~0 == rpath->frp_sw_if_index)) + entry_flags |= (FIB_ENTRY_FLAG_CONNECTED | FIB_ENTRY_FLAG_LOCAL); - n_labels = mp->next_hop_n_out_labels; - if (n_labels == 0) - ; - else - { - vec_validate (label_stack, n_labels - 1); - for (ii = 0; ii < n_labels; ii++) - { - label_stack[ii].fml_value = - ntohl (mp->next_hop_out_label_stack[ii].label); - label_stack[ii].fml_ttl = mp->next_hop_out_label_stack[ii].ttl; - label_stack[ii].fml_exp = mp->next_hop_out_label_stack[ii].exp; - label_stack[ii].fml_mode = - (mp->next_hop_out_label_stack[ii].is_uniform ? - FIB_MPLS_LSP_MODE_UNIFORM : FIB_MPLS_LSP_MODE_PIPE); - } + if (0 != rv) + goto out; } - rv = add_del_route_t_handler (mp->is_multipath, - mp->is_add, - mp->is_drop, - mp->is_unreach, - mp->is_prohibit, - mp->is_local, 0, - mp->is_classify, - mp->classify_table_index, - mp->is_resolve_host, - mp->is_resolve_attached, 0, 0, - mp->is_dvr, - mp->is_source_lookup, - mp->is_udp_encap, - fib_index, &pfx, DPO_PROTO_IP6, - &nh, ntohl (mp->next_hop_id), - ntohl (mp->next_hop_sw_if_index), - next_hop_fib_index, - mp->next_hop_weight, - mp->next_hop_preference, - ntohl (mp->next_hop_via_label), label_stack); + fib_api_route_add_del (mp->is_add, + mp->is_multipath, + fib_index, &pfx, entry_flags, rpaths); if (mp->is_add && 0 == rv) *stats_index = fib_table_entry_get_stats_index (fib_index, &pfx); +out: + vec_free (rpaths); + return (rv); } void -vl_api_ip_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp) +vl_api_ip_route_add_del_t_handler (vl_api_ip_route_add_del_t * mp) { - vl_api_ip_add_del_route_reply_t *rmp; - u32 stats_index; + vl_api_ip_route_add_del_reply_t *rmp; + u32 stats_index = ~0; int rv; - vnet_main_t *vnm = vnet_get_main (); - - vnm->api_errno = 0; - stats_index = ~0; - if (mp->is_ipv6) - rv = ip6_add_del_route_t_handler (mp, &stats_index); - else - rv = ip4_add_del_route_t_handler (mp, &stats_index); - - rv = (rv == 0) ? vnm->api_errno : rv; + rv = ip_route_add_del_t_handler (mp, &stats_index); /* *INDENT-OFF* */ - REPLY_MACRO2 (VL_API_IP_ADD_DEL_ROUTE_REPLY, + REPLY_MACRO2 (VL_API_IP_ROUTE_ADD_DEL_REPLY, ({ rmp->stats_index = htonl (stats_index); })) @@ -1221,80 +760,37 @@ ip_table_create (fib_protocol_t fproto, } } -static int -add_del_mroute_check (fib_protocol_t table_proto, - u32 table_id, - u32 next_hop_sw_if_index, u8 is_local, u32 * fib_index) -{ - vnet_main_t *vnm = vnet_get_main (); - - *fib_index = mfib_table_find (table_proto, ntohl (table_id)); - if (~0 == *fib_index) - { - /* No such table */ - return VNET_API_ERROR_NO_SUCH_FIB; - } - - if (~0 != ntohl (next_hop_sw_if_index)) - { - if (pool_is_free_index (vnm->interface_main.sw_interfaces, - ntohl (next_hop_sw_if_index))) - { - return VNET_API_ERROR_NO_MATCHING_INTERFACE; - } - } - - return (0); -} - -static fib_node_index_t +static u32 mroute_add_del_handler (u8 is_add, - u8 is_local, + u8 is_multipath, u32 fib_index, const mfib_prefix_t * prefix, - dpo_proto_t nh_proto, u32 entry_flags, - fib_rpf_id_t rpf_id, - u32 next_hop_sw_if_index, - ip46_address_t * nh, u32 itf_flags, u32 bier_imp) + u32 rpf_id, fib_route_path_t * rpaths) { - fib_node_index_t mfib_entry_index = ~0; - - fib_route_path_t path = { - .frp_sw_if_index = next_hop_sw_if_index, - .frp_proto = nh_proto, - .frp_addr = *nh, - }; + u32 mfib_entry_index = ~0; - if (is_local) - path.frp_flags |= FIB_ROUTE_PATH_LOCAL; - - if (DPO_PROTO_BIER == nh_proto) - { - path.frp_bier_imp = bier_imp; - path.frp_flags = FIB_ROUTE_PATH_BIER_IMP; - } - else if (!is_local && ~0 == next_hop_sw_if_index) + if (0 == vec_len (rpaths)) { mfib_entry_index = mfib_table_entry_update (fib_index, prefix, MFIB_SOURCE_API, rpf_id, entry_flags); - goto done; - } - - if (is_add) - { - mfib_entry_index = mfib_table_entry_path_update (fib_index, prefix, - MFIB_SOURCE_API, - &path, itf_flags); } else { - mfib_table_entry_path_remove (fib_index, prefix, - MFIB_SOURCE_API, &path); + if (is_add) + { + mfib_entry_index = + mfib_table_entry_paths_update (fib_index, prefix, + MFIB_SOURCE_API, rpaths); + } + else + { + mfib_table_entry_paths_remove (fib_index, prefix, + MFIB_SOURCE_API, rpaths); + } } -done: return (mfib_entry_index); } @@ -1302,64 +798,43 @@ static int api_mroute_add_del_t_handler (vl_api_ip_mroute_add_del_t * mp, u32 * stats_index) { + fib_route_path_t *rpath, *rpaths = NULL; fib_node_index_t mfib_entry_index; - fib_protocol_t fproto; - dpo_proto_t nh_proto; - ip46_address_t nh; + mfib_prefix_t pfx; u32 fib_index; int rv; + u16 ii; - nh_proto = mp->next_hop_afi; - fproto = (mp->is_ipv6 ? FIB_PROTOCOL_IP6 : FIB_PROTOCOL_IP4); - rv = add_del_mroute_check (fproto, - mp->table_id, - mp->next_hop_sw_if_index, - mp->is_local, &fib_index); + ip_mprefix_decode (&mp->route.prefix, &pfx); + rv = mfib_api_table_id_decode (pfx.fp_proto, + ntohl (mp->route.table_id), &fib_index); if (0 != rv) - return (rv); + goto out; - mfib_prefix_t pfx = { - .fp_len = ntohs (mp->grp_address_length), - .fp_proto = fproto, - }; + vec_validate (rpaths, mp->route.n_paths - 1); - if (FIB_PROTOCOL_IP4 == fproto) - { - clib_memcpy (&pfx.fp_grp_addr.ip4, mp->grp_address, - sizeof (pfx.fp_grp_addr.ip4)); - clib_memcpy (&pfx.fp_src_addr.ip4, mp->src_address, - sizeof (pfx.fp_src_addr.ip4)); - clib_memset (&nh.ip6, 0, sizeof (nh.ip6)); - clib_memcpy (&nh.ip4, mp->nh_address, sizeof (nh.ip4)); - if (!ip46_address_is_zero (&pfx.fp_src_addr)) - pfx.fp_len = 64; - } - else + for (ii = 0; ii < mp->route.n_paths; ii++) { - clib_memcpy (&pfx.fp_grp_addr.ip6, mp->grp_address, - sizeof (pfx.fp_grp_addr.ip6)); - clib_memcpy (&pfx.fp_src_addr.ip6, mp->src_address, - sizeof (pfx.fp_src_addr.ip6)); - clib_memcpy (&nh.ip6, mp->nh_address, sizeof (nh.ip6)); - if (!ip46_address_is_zero (&pfx.fp_src_addr)) - pfx.fp_len = 256; + rpath = &rpaths[ii]; + + rv = mfib_api_path_decode (&mp->route.paths[ii], rpath); + + if (0 != rv) + goto out; } mfib_entry_index = mroute_add_del_handler (mp->is_add, - mp->is_local, + mp->is_add, fib_index, &pfx, - nh_proto, - ntohl (mp->entry_flags), - ntohl (mp->rpf_id), - ntohl (mp->next_hop_sw_if_index), - &nh, - ntohl (mp->itf_flags), - ntohl (mp->bier_imp)); + ntohl (mp->route.entry_flags), + ntohl (mp->route.rpf_id), + rpaths); if (~0 != mfib_entry_index) *stats_index = mfib_entry_get_stats_index (mfib_entry_index); +out: return (rv); } @@ -1367,14 +842,9 @@ void vl_api_ip_mroute_add_del_t_handler (vl_api_ip_mroute_add_del_t * mp) { vl_api_ip_mroute_add_del_reply_t *rmp; - vnet_main_t *vnm; - u32 stats_index; + u32 stats_index = ~0; int rv; - vnm = vnet_get_main (); - vnm->api_errno = 0; - stats_index = ~0; - rv = api_mroute_add_del_t_handler (mp, &stats_index); /* *INDENT-OFF* */ @@ -1406,8 +876,8 @@ send_ip_details (vpe_api_main_t * am, static void send_ip_address_details (vpe_api_main_t * am, vl_api_registration_t * reg, - u8 * ip, u16 prefix_length, - u32 sw_if_index, u8 is_ipv6, u32 context) + const fib_prefix_t * pfx, + u32 sw_if_index, u32 context) { vl_api_ip_address_details_t *mp; @@ -1415,19 +885,9 @@ send_ip_address_details (vpe_api_main_t * am, clib_memset (mp, 0, sizeof (*mp)); mp->_vl_msg_id = ntohs (VL_API_IP_ADDRESS_DETAILS); - if (is_ipv6) - { - clib_memcpy (&mp->ip, ip, sizeof (mp->ip)); - } - else - { - u32 *tp = (u32 *) mp->ip; - *tp = *(u32 *) ip; - } - mp->prefix_length = prefix_length; + ip_prefix_encode (pfx, &mp->prefix); mp->context = context; mp->sw_if_index = htonl (sw_if_index); - mp->is_ipv6 = is_ipv6; vl_api_send_msg (reg, (u8 *) mp); } @@ -1437,8 +897,6 @@ vl_api_ip_address_dump_t_handler (vl_api_ip_address_dump_t * mp) { vpe_api_main_t *am = &vpe_api_main; vl_api_registration_t *reg; - ip6_address_t *r6; - ip4_address_t *r4; ip6_main_t *im6 = &ip6_main; ip4_main_t *im4 = &ip4_main; ip_lookup_main_t *lm6 = &im6->lookup_main; @@ -1464,10 +922,12 @@ vl_api_ip_address_dump_t_handler (vl_api_ip_address_dump_t * mp) * than one interface */ foreach_ip_interface_address (lm6, ia, sw_if_index, 0, ({ - r6 = ip_interface_address_get_address (lm6, ia); - u16 prefix_length = ia->address_length; - send_ip_address_details(am, reg, (u8*)r6, prefix_length, - sw_if_index, 1, mp->context); + fib_prefix_t pfx = { + .fp_addr.ip6 = *(ip6_address_t *)ip_interface_address_get_address (lm6, ia), + .fp_len = ia->address_length, + .fp_proto = FIB_PROTOCOL_IP6, + }; + send_ip_address_details(am, reg, &pfx, sw_if_index, mp->context); })); /* *INDENT-ON* */ } @@ -1476,10 +936,13 @@ vl_api_ip_address_dump_t_handler (vl_api_ip_address_dump_t * mp) /* *INDENT-OFF* */ foreach_ip_interface_address (lm4, ia, sw_if_index, 0, ({ - r4 = ip_interface_address_get_address (lm4, ia); - u16 prefix_length = ia->address_length; - send_ip_address_details(am, reg, (u8*)r4, prefix_length, - sw_if_index, 0, mp->context); + fib_prefix_t pfx = { + .fp_addr.ip4 = *(ip4_address_t *)ip_interface_address_get_address (lm4, ia), + .fp_len = ia->address_length, + .fp_proto = FIB_PROTOCOL_IP4, + }; + + send_ip_address_details(am, reg, &pfx, sw_if_index, mp->context); })); /* *INDENT-ON* */ } @@ -1883,22 +1346,7 @@ vl_mfib_signal_send_one (vl_api_registration_t * reg, mp->table_id = ntohl (mfib->mft_table_id); mp->sw_if_index = ntohl (mfi->mfi_sw_if_index); - if (FIB_PROTOCOL_IP4 == prefix->fp_proto) - { - mp->grp_address_len = ntohs (prefix->fp_len); - - memcpy (mp->grp_address, &prefix->fp_grp_addr.ip4, 4); - if (prefix->fp_len > 32) - { - memcpy (mp->src_address, &prefix->fp_src_addr.ip4, 4); - } - } - else - { - mp->grp_address_len = ntohs (prefix->fp_len); - - ASSERT (0); - } + ip_mprefix_encode (prefix, &mp->prefix); if (0 != mfs->mfs_buffer_len) { @@ -3369,9 +2817,11 @@ static walk_rc_t send_ip_punt_redirect_details (u32 rx_sw_if_index, const ip_punt_redirect_rx_t * ipr, void *arg) { - fib_route_path_encode_t *api_rpaths = NULL; ip_punt_redirect_walk_ctx_t *ctx = arg; vl_api_ip_punt_redirect_details_t *mp; + fib_path_encode_ctx_t path_ctx = { + .rpaths = NULL, + }; mp = vl_msg_api_alloc (sizeof (*mp)); if (!mp) @@ -3381,17 +2831,17 @@ send_ip_punt_redirect_details (u32 rx_sw_if_index, mp->_vl_msg_id = ntohs (VL_API_IP_PUNT_REDIRECT_DETAILS); mp->context = ctx->context; - fib_path_list_walk_w_ext (ipr->pl, NULL, fib_path_encode, &api_rpaths); + fib_path_list_walk_w_ext (ipr->pl, NULL, fib_path_encode, &path_ctx); mp->punt.rx_sw_if_index = htonl (rx_sw_if_index); - mp->punt.tx_sw_if_index = htonl (api_rpaths[0].rpath.frp_sw_if_index); + mp->punt.tx_sw_if_index = htonl (path_ctx.rpaths[0].frp_sw_if_index); - ip_address_encode (&api_rpaths[0].rpath.frp_addr, + ip_address_encode (&path_ctx.rpaths[0].frp_addr, fib_proto_to_ip46 (ipr->fproto), &mp->punt.nh); vl_api_send_msg (ctx->reg, (u8 *) mp); - vec_free (api_rpaths); + vec_free (path_ctx.rpaths); return (WALK_CONTINUE); } @@ -3461,8 +2911,8 @@ ip_api_hookup (vlib_main_t * vm) /* * Mark the route add/del API as MP safe */ - am->is_mp_safe[VL_API_IP_ADD_DEL_ROUTE] = 1; - am->is_mp_safe[VL_API_IP_ADD_DEL_ROUTE_REPLY] = 1; + am->is_mp_safe[VL_API_IP_ROUTE_ADD_DEL] = 1; + am->is_mp_safe[VL_API_IP_ROUTE_ADD_DEL_REPLY] = 1; /* * Set up the (msg_name, crc, message-id) table diff --git a/src/vnet/ip/ip_types_api.c b/src/vnet/ip/ip_types_api.c index fd8d24f36fe..6ad2c366dff 100644 --- a/src/vnet/ip/ip_types_api.c +++ b/src/vnet/ip/ip_types_api.c @@ -229,6 +229,9 @@ ip_mprefix_decode (const vl_api_mprefix_t * in, mfib_prefix_t * out) ip_address_union_decode (&in->grp_address, in->af, &out->fp_grp_addr); ip_address_union_decode (&in->src_address, in->af, &out->fp_src_addr); + + if (!ip46_address_is_zero (&out->fp_src_addr)) + out->fp_len = (out->fp_proto == FIB_PROTOCOL_IP6 ? 256 : 64); } /* diff --git a/src/vnet/ip/lookup.c b/src/vnet/ip/lookup.c index 5c6fec1810b..8c89ed4f490 100644 --- a/src/vnet/ip/lookup.c +++ b/src/vnet/ip/lookup.c @@ -441,7 +441,7 @@ vnet_ip_route_cmd (vlib_main_t * vm, } else if (0 < vec_len (rpaths)) { - u32 k, j, n, incr; + u32 k, n, incr; ip46_address_t dst = prefixs[i].fp_addr; f64 t[2]; n = count; @@ -451,25 +451,20 @@ vnet_ip_route_cmd (vlib_main_t * vm, for (k = 0; k < n; k++) { - for (j = 0; j < vec_len (rpaths); j++) - { - fib_prefix_t rpfx = { - .fp_len = prefixs[i].fp_len, - .fp_proto = prefixs[i].fp_proto, - .fp_addr = dst, - }; - - if (is_del) - fib_table_entry_path_remove2 (fib_index, - &rpfx, - FIB_SOURCE_CLI, &rpaths[j]); - else - fib_table_entry_path_add2 (fib_index, - &rpfx, - FIB_SOURCE_CLI, - FIB_ENTRY_FLAG_NONE, - &rpaths[j]); - } + fib_prefix_t rpfx = { + .fp_len = prefixs[i].fp_len, + .fp_proto = prefixs[i].fp_proto, + .fp_addr = dst, + }; + + if (is_del) + fib_table_entry_path_remove2 (fib_index, + &rpfx, FIB_SOURCE_CLI, rpaths); + else + fib_table_entry_path_add2 (fib_index, + &rpfx, + FIB_SOURCE_CLI, + FIB_ENTRY_FLAG_NONE, rpaths); if (FIB_PROTOCOL_IP4 == prefixs[0].fp_proto) { @@ -485,9 +480,9 @@ vnet_ip_route_cmd (vlib_main_t * vm, clib_host_to_net_u64 (incr + clib_net_to_host_u64 (dst.ip6.as_u64 [bucket])); - } } + t[1] = vlib_time_now (vm); if (count > 1) vlib_cli_output (vm, "%.6e routes/sec", count / (t[1] - t[0])); @@ -499,7 +494,6 @@ vnet_ip_route_cmd (vlib_main_t * vm, } } - done: vec_free (dpos); vec_free (prefixs); @@ -805,20 +799,17 @@ vnet_ip_mroute_cmd (vlib_main_t * vm, unformat_input_t * main_input, vlib_cli_command_t * cmd) { unformat_input_t _line_input, *line_input = &_line_input; + fib_route_path_t rpath, *rpaths = NULL; clib_error_t *error = NULL; - fib_route_path_t rpath; - u32 table_id, is_del; - vnet_main_t *vnm; + u32 table_id, is_del, payload_proto; mfib_prefix_t pfx; u32 fib_index; - mfib_itf_flags_t iflags = 0; mfib_entry_flags_t eflags = 0; u32 gcount, scount, ss, gg, incr; f64 timet[2]; u32 rpf_id = MFIB_RPF_ID_NONE; gcount = scount = 1; - vnm = vnet_get_main (); is_del = 0; table_id = 0; clib_memset (&pfx, 0, sizeof (pfx)); @@ -887,51 +878,6 @@ vnet_ip_mroute_cmd (vlib_main_t * vm, pfx.fp_proto = FIB_PROTOCOL_IP6; pfx.fp_len = 128; } - else if (unformat (line_input, "via %U %U %U", - unformat_ip4_address, &rpath.frp_addr.ip4, - unformat_vnet_sw_interface, vnm, - &rpath.frp_sw_if_index, - unformat_mfib_itf_flags, &iflags)) - { - rpath.frp_weight = 1; - } - else if (unformat (line_input, "via %U %U %U", - unformat_ip6_address, &rpath.frp_addr.ip6, - unformat_vnet_sw_interface, vnm, - &rpath.frp_sw_if_index, - unformat_mfib_itf_flags, &iflags)) - { - rpath.frp_weight = 1; - } - else if (unformat (line_input, "via %U %U", - unformat_vnet_sw_interface, vnm, - &rpath.frp_sw_if_index, - unformat_mfib_itf_flags, &iflags)) - { - clib_memset (&rpath.frp_addr, 0, sizeof (rpath.frp_addr)); - rpath.frp_weight = 1; - } - else if (unformat (line_input, "via %U %U", - unformat_ip4_address, &rpath.frp_addr.ip4, - unformat_vnet_sw_interface, vnm, - &rpath.frp_sw_if_index)) - { - rpath.frp_weight = 1; - } - else if (unformat (line_input, "via %U %U", - unformat_ip6_address, &rpath.frp_addr.ip6, - unformat_vnet_sw_interface, vnm, - &rpath.frp_sw_if_index)) - { - rpath.frp_weight = 1; - } - else if (unformat (line_input, "via %U", - unformat_vnet_sw_interface, vnm, - &rpath.frp_sw_if_index)) - { - clib_memset (&rpath.frp_addr, 0, sizeof (rpath.frp_addr)); - rpath.frp_weight = 1; - } else if (unformat (line_input, "via local Forward")) { clib_memset (&rpath.frp_addr, 0, sizeof (rpath.frp_addr)); @@ -942,9 +888,17 @@ vnet_ip_mroute_cmd (vlib_main_t * vm, * set the path proto appropriately for the prefix */ rpath.frp_proto = fib_proto_to_dpo (pfx.fp_proto); - iflags = MFIB_ITF_FLAG_FORWARD; + rpath.frp_mitf_flags = MFIB_ITF_FLAG_FORWARD; + } + else if (unformat (line_input, "via %U", + unformat_fib_route_path, &rpath, &payload_proto)) + { + vec_add1 (rpaths, rpath); } else if (unformat (line_input, "%U", + unformat_mfib_itf_flags, &rpath.frp_mitf_flags)) + ; + else if (unformat (line_input, "%U", unformat_mfib_entry_flags, &eflags)) ; else @@ -987,7 +941,7 @@ vnet_ip_mroute_cmd (vlib_main_t * vm, { for (gg = 0; gg < gcount; gg++) { - if (is_del && 0 == rpath.frp_weight) + if (is_del && 0 == vec_len (rpaths)) { /* no path provided => route delete */ mfib_table_entry_delete (fib_index, &pfx, MFIB_SOURCE_CLI); @@ -1001,11 +955,10 @@ vnet_ip_mroute_cmd (vlib_main_t * vm, { if (is_del) mfib_table_entry_path_remove (fib_index, - &pfx, MFIB_SOURCE_CLI, &rpath); + &pfx, MFIB_SOURCE_CLI, rpaths); else mfib_table_entry_path_update (fib_index, - &pfx, MFIB_SOURCE_CLI, &rpath, - iflags); + &pfx, MFIB_SOURCE_CLI, rpaths); } if (FIB_PROTOCOL_IP4 == pfx.fp_proto) @@ -1050,6 +1003,7 @@ vnet_ip_mroute_cmd (vlib_main_t * vm, (scount * gcount) / (timet[1] - timet[0])); done: + vec_free (rpaths); unformat_free (line_input); return error; diff --git a/src/vnet/mfib/ip6_mfib.c b/src/vnet/mfib/ip6_mfib.c index 31a92687e1a..5b15c8d1736 100644 --- a/src/vnet/mfib/ip6_mfib.c +++ b/src/vnet/mfib/ip6_mfib.c @@ -141,8 +141,9 @@ ip6_create_mfib_with_table_id (u32 table_id, .frp_addr = zero_addr, .frp_sw_if_index = 0xffffffff, .frp_fib_index = ~0, - .frp_weight = 0, + .frp_weight = 1, .frp_flags = FIB_ROUTE_PATH_LOCAL, + .frp_mitf_flags = MFIB_ITF_FLAG_FORWARD, }; pool_get_aligned(ip6_main.mfibs, mfib_table, CLIB_CACHE_LINE_BYTES); @@ -180,8 +181,7 @@ ip6_create_mfib_with_table_id (u32 table_id, mfib_table_entry_path_update(mfib_table->mft_index, &pfx, MFIB_SOURCE_SPECIAL, - &path_for_us, - MFIB_ITF_FLAG_FORWARD); + &path_for_us); })); return (mfib_table->mft_index); @@ -200,7 +200,7 @@ ip6_mfib_table_destroy (ip6_mfib_t *mfib) .frp_addr = zero_addr, .frp_sw_if_index = 0xffffffff, .frp_fib_index = ~0, - .frp_weight = 0, + .frp_weight = 1, .frp_flags = FIB_ROUTE_PATH_LOCAL, }; @@ -236,7 +236,8 @@ ip6_mfib_interface_enable_disable (u32 sw_if_index, int is_enable) .frp_addr = zero_addr, .frp_sw_if_index = sw_if_index, .frp_fib_index = ~0, - .frp_weight = 0, + .frp_weight = 1, + .frp_mitf_flags = MFIB_ITF_FLAG_ACCEPT, }; mfib_prefix_t pfx = { .fp_proto = FIB_PROTOCOL_IP6, @@ -253,8 +254,7 @@ ip6_mfib_interface_enable_disable (u32 sw_if_index, int is_enable) mfib_table_entry_path_update(mfib_index, &pfx, MFIB_SOURCE_SPECIAL, - &path, - MFIB_ITF_FLAG_ACCEPT); + &path); }); } else diff --git a/src/vnet/mfib/mfib_api.c b/src/vnet/mfib/mfib_api.c new file mode 100644 index 00000000000..bcab83ba0e5 --- /dev/null +++ b/src/vnet/mfib/mfib_api.c @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2018 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/vnet.h> +#include <vlibmemory/api.h> +#include <vnet/mfib/mfib_api.h> +#include <vnet/mfib/mfib_table.h> +#include <vnet/fib/fib_api.h> +#include <vnet/ip/ip_types_api.h> + +#include <vnet/vnet_msg_enum.h> + +#define vl_typedefs /* define message structures */ +#include <vnet/vnet_all_api_h.h> +#undef vl_typedefs + +#define vl_endianfun /* define message structures */ +#include <vnet/vnet_all_api_h.h> +#undef vl_endianfun + +/* instantiate all the print functions we know about */ +#define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__) +#define vl_printfun +#include <vnet/vnet_all_api_h.h> +#undef vl_printfun + +static vl_api_mfib_itf_flags_t +mfib_api_path_itf_flags_encode (mfib_itf_flags_t flags) +{ + vl_api_mfib_itf_flags_t out = MFIB_API_ITF_FLAG_NONE; + + switch (flags) + { + case MFIB_ITF_FLAG_NONE: + out = MFIB_API_ITF_FLAG_NONE; + break; + case MFIB_ITF_FLAG_NEGATE_SIGNAL: + out = MFIB_API_ITF_FLAG_NEGATE_SIGNAL; + break; + case MFIB_ITF_FLAG_ACCEPT: + out = MFIB_API_ITF_FLAG_ACCEPT; + break; + case MFIB_ITF_FLAG_FORWARD: + out = MFIB_API_ITF_FLAG_FORWARD; + break; + case MFIB_ITF_FLAG_SIGNAL_PRESENT: + out = MFIB_API_ITF_FLAG_SIGNAL_PRESENT; + break; + case MFIB_ITF_FLAG_DONT_PRESERVE: + out = MFIB_API_ITF_FLAG_DONT_PRESERVE; + break; + } + return (ntohl(out)); +} + +void +mfib_api_path_encode (const fib_route_path_t *in, + vl_api_mfib_path_t *out) +{ + out->itf_flags = mfib_api_path_itf_flags_encode(in->frp_mitf_flags); + + fib_api_path_encode(in, &out->path); +} + +static void +mfib_api_path_itf_flags_decode (vl_api_mfib_itf_flags_t in, + mfib_itf_flags_t *out) +{ + in = clib_net_to_host_u32(in); + + if (in & MFIB_API_ITF_FLAG_NONE) + *out |= MFIB_ITF_FLAG_NONE; + if (in & MFIB_API_ITF_FLAG_NEGATE_SIGNAL) + *out |= MFIB_ITF_FLAG_NEGATE_SIGNAL; + if (in & MFIB_API_ITF_FLAG_ACCEPT) + *out |= MFIB_ITF_FLAG_ACCEPT; + if (in & MFIB_API_ITF_FLAG_FORWARD) + *out |= MFIB_ITF_FLAG_FORWARD; + if (in & MFIB_API_ITF_FLAG_SIGNAL_PRESENT) + *out |= MFIB_ITF_FLAG_SIGNAL_PRESENT; + if (in & MFIB_API_ITF_FLAG_DONT_PRESERVE) + *out |= MFIB_ITF_FLAG_DONT_PRESERVE; +} + +int +mfib_api_path_decode (vl_api_mfib_path_t *in, + fib_route_path_t *out) +{ + mfib_api_path_itf_flags_decode(in->itf_flags, &out->frp_mitf_flags); + + return (fib_api_path_decode(&in->path, out)); +} + +int +mfib_api_table_id_decode (fib_protocol_t fproto, + u32 table_id, + u32 *fib_index) +{ + *fib_index = mfib_table_find(fproto, table_id); + + if (INDEX_INVALID == *fib_index) + { + return VNET_API_ERROR_NO_SUCH_FIB; + } + + return (0); +} diff --git a/src/vnet/mfib/mfib_api.h b/src/vnet/mfib/mfib_api.h new file mode 100644 index 00000000000..f9c0a74bedb --- /dev/null +++ b/src/vnet/mfib/mfib_api.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2018 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. + */ + +#ifndef __MFIB_API_H__ +#define __MFIB_API_H__ + +#include <vnet/mfib/mfib_types.h> + +/** + * Forward declare the API type, no need to include the generated api headers + */ +struct _vl_api_mfib_path; + +/** + * Encode and decode functions from the API types to internal types + */ +extern void mfib_api_path_encode(const fib_route_path_t *in, + struct _vl_api_mfib_path *out); +extern int mfib_api_path_decode(struct _vl_api_mfib_path *in, + fib_route_path_t *out); + +extern int mfib_api_table_id_decode(fib_protocol_t fproto, + u32 table_id, + u32 *fib_index); + +#endif /* __MFIB_API_H__ */ diff --git a/src/vnet/mfib/mfib_entry.c b/src/vnet/mfib/mfib_entry.c index 18562219ce2..f169dc0886e 100644 --- a/src/vnet/mfib/mfib_entry.c +++ b/src/vnet/mfib/mfib_entry.c @@ -673,21 +673,12 @@ mfib_entry_stack (mfib_entry_t *mfib_entry, &bw_ctx); } -static fib_node_index_t -mfib_entry_src_path_add (mfib_entry_src_t *msrc, - const fib_route_path_t *rpath) +static fib_node_index_t* +mfib_entry_src_paths_add (mfib_entry_src_t *msrc, + const fib_route_path_t *rpaths) { - fib_node_index_t path_index; - fib_route_path_t *rpaths; - ASSERT(!(MFIB_ENTRY_FLAG_EXCLUSIVE & msrc->mfes_flags)); - /* - * path-lists require a vector of paths - */ - rpaths = NULL; - vec_add1(rpaths, rpath[0]); - if (FIB_NODE_INDEX_INVALID == msrc->mfes_pl) { /* A non-shared path-list */ @@ -696,33 +687,16 @@ mfib_entry_src_path_add (mfib_entry_src_t *msrc, fib_path_list_lock(msrc->mfes_pl); } - path_index = fib_path_list_path_add(msrc->mfes_pl, rpaths); - - vec_free(rpaths); - - return (path_index); + return (fib_path_list_paths_add(msrc->mfes_pl, rpaths)); } -static fib_node_index_t -mfib_entry_src_path_remove (mfib_entry_src_t *msrc, - const fib_route_path_t *rpath) +static fib_node_index_t* +mfib_entry_src_paths_remove (mfib_entry_src_t *msrc, + const fib_route_path_t *rpaths) { - fib_node_index_t path_index; - fib_route_path_t *rpaths; - ASSERT(!(MFIB_ENTRY_FLAG_EXCLUSIVE & msrc->mfes_flags)); - /* - * path-lists require a vector of paths - */ - rpaths = NULL; - vec_add1(rpaths, rpath[0]); - - path_index = fib_path_list_path_remove(msrc->mfes_pl, rpaths); - - vec_free(rpaths); - - return (path_index); + return (fib_path_list_paths_remove(msrc->mfes_pl, rpaths)); } static void @@ -819,7 +793,12 @@ mfib_entry_src_ok_for_delete (const mfib_entry_src_t *msrc) { return ((INDEX_INVALID == msrc->mfes_cover && MFIB_ENTRY_FLAG_NONE == msrc->mfes_flags && - 0 == fib_path_list_get_n_paths(msrc->mfes_pl))); + 0 == fib_path_list_get_n_paths(msrc->mfes_pl)) && + (0 == hash_elts(msrc->mfes_itfs))); + + /* return ((MFIB_ENTRY_FLAG_NONE == msrc->mfes_flags) && */ + /* (0 == fib_path_list_get_n_paths(msrc->mfes_pl)) && */ + /* (0 == hash_elts(msrc->mfes_itfs))); */ } @@ -931,18 +910,26 @@ mfib_entry_itf_remove (mfib_entry_src_t *msrc, hash_unset(msrc->mfes_itfs, sw_if_index); } +static int +mfib_entry_path_itf_based (const fib_route_path_t *rpath) +{ + return (!(rpath->frp_flags & FIB_ROUTE_PATH_BIER_IMP) && + ~0 != rpath->frp_sw_if_index); +} + void mfib_entry_path_update (fib_node_index_t mfib_entry_index, mfib_source_t source, - const fib_route_path_t *rpath, - mfib_itf_flags_t itf_flags) + const fib_route_path_t *rpaths) { - fib_node_index_t path_index; + fib_node_index_t* path_indices, path_index; + const fib_route_path_t *rpath; mfib_source_t current_best; mfib_path_ext_t *path_ext; mfib_entry_t *mfib_entry; mfib_entry_src_t *msrc; mfib_itf_flags_t old; + u32 ii; mfib_entry = mfib_entry_get(mfib_entry_index); ASSERT(NULL != mfib_entry); @@ -953,61 +940,73 @@ mfib_entry_path_update (fib_node_index_t mfib_entry_index, * add the path to the path-list. If it's a duplicate we'll get * back the original path. */ - path_index = mfib_entry_src_path_add(msrc, rpath); + path_indices = mfib_entry_src_paths_add(msrc, rpaths); - /* - * find the path extension for that path - */ - path_ext = mfib_entry_path_ext_find(msrc->mfes_exts, path_index); - - if (NULL == path_ext) + vec_foreach_index(ii, path_indices) { - old = MFIB_ITF_FLAG_NONE; - path_ext = mfib_path_ext_add(msrc, path_index, itf_flags); - } - else - { - old = path_ext->mfpe_flags; - path_ext->mfpe_flags = itf_flags; - } + path_index = path_indices[ii]; + rpath = &rpaths[ii]; - /* - * Has the path changed its contribution to the input interface set. - * Which only paths with interfaces can do... - */ - if (~0 != rpath[0].frp_sw_if_index) - { - mfib_itf_t *mfib_itf; + if (FIB_NODE_INDEX_INVALID == path_index) + continue; + + /* + * find the path extension for that path + */ + path_ext = mfib_entry_path_ext_find(msrc->mfes_exts, path_index); - if (old != itf_flags) + if (NULL == path_ext) { - /* - * change of flag contributions - */ - mfib_itf = mfib_entry_itf_find(msrc->mfes_itfs, - rpath[0].frp_sw_if_index); + old = MFIB_ITF_FLAG_NONE; + path_ext = mfib_path_ext_add(msrc, path_index, + rpath->frp_mitf_flags); + } + else + { + old = path_ext->mfpe_flags; + path_ext->mfpe_flags = rpath->frp_mitf_flags; + } - if (NULL == mfib_itf) - { - mfib_entry_itf_add(msrc, - rpath[0].frp_sw_if_index, - mfib_itf_create(path_index, itf_flags)); - } - else + /* + * Has the path changed its contribution to the input interface set. + * Which only paths with interfaces can do... + */ + if (mfib_entry_path_itf_based(rpath)) + { + mfib_itf_t *mfib_itf; + + if (old != rpath->frp_mitf_flags) { - if (mfib_itf_update(mfib_itf, - path_index, - itf_flags)) + /* + * change of flag contributions + */ + mfib_itf = mfib_entry_itf_find(msrc->mfes_itfs, + rpath->frp_sw_if_index); + + if (NULL == mfib_itf) { - /* - * no more interface flags on this path, remove - * from the data-plane set - */ - mfib_entry_itf_remove(msrc, rpath[0].frp_sw_if_index); + mfib_entry_itf_add(msrc, + rpath->frp_sw_if_index, + mfib_itf_create(path_index, + rpath->frp_mitf_flags)); + } + else + { + if (mfib_itf_update(mfib_itf, + path_index, + rpath->frp_mitf_flags)) + { + /* + * no more interface flags on this path, remove + * from the data-plane set + */ + mfib_entry_itf_remove(msrc, rpath->frp_sw_if_index); + } } } } } + vec_free(path_indices); mfib_entry_recalculate_forwarding(mfib_entry, current_best); } @@ -1021,12 +1020,14 @@ mfib_entry_path_update (fib_node_index_t mfib_entry_index, int mfib_entry_path_remove (fib_node_index_t mfib_entry_index, mfib_source_t source, - const fib_route_path_t *rpath) + const fib_route_path_t *rpaths) { - fib_node_index_t path_index; + fib_node_index_t path_index, *path_indices; + const fib_route_path_t *rpath; mfib_source_t current_best; mfib_entry_t *mfib_entry; mfib_entry_src_t *msrc; + u32 ii; mfib_entry = mfib_entry_get(mfib_entry_index); ASSERT(NULL != mfib_entry); @@ -1042,23 +1043,29 @@ mfib_entry_path_remove (fib_node_index_t mfib_entry_index, } /* - * remove the path from the path-list. If it's not there we'll get - * back invalid + * remove the paths from the path-list. If it's not there we'll get + * back an empty vector */ - path_index = mfib_entry_src_path_remove(msrc, rpath); + path_indices = mfib_entry_src_paths_remove(msrc, rpaths); - if (FIB_NODE_INDEX_INVALID != path_index) + vec_foreach_index(ii, path_indices) { + path_index = path_indices[ii]; + rpath = &rpaths[ii]; + + if (FIB_NODE_INDEX_INVALID == path_index) + continue; + /* * don't need the extension, nor the interface anymore */ mfib_path_ext_remove(msrc, path_index); - if (~0 != rpath[0].frp_sw_if_index) + if (mfib_entry_path_itf_based(rpath)) { mfib_itf_t *mfib_itf; mfib_itf = mfib_entry_itf_find(msrc->mfes_itfs, - rpath[0].frp_sw_if_index); + rpath->frp_sw_if_index); if (mfib_itf_update(mfib_itf, path_index, @@ -1068,19 +1075,20 @@ mfib_entry_path_remove (fib_node_index_t mfib_entry_index, * no more interface flags on this path, remove * from the data-plane set */ - mfib_entry_itf_remove(msrc, rpath[0].frp_sw_if_index); + mfib_entry_itf_remove(msrc, rpath->frp_sw_if_index); } } - } - if (mfib_entry_src_ok_for_delete(msrc)) - { - /* - * this source has no interfaces and no flags. - * it has nothing left to give - remove it - */ - mfib_entry_src_remove(mfib_entry, source); + if (mfib_entry_src_ok_for_delete(msrc)) + { + /* + * this source has no interfaces and no flags. + * it has nothing left to give - remove it + */ + mfib_entry_src_remove(mfib_entry, source); + } } + vec_free(path_indices); mfib_entry_recalculate_forwarding(mfib_entry, current_best); @@ -1321,12 +1329,14 @@ mfib_entry_module_init (void) mfib_entry_logger = vlib_log_register_class("mfib", "entry"); } -void -mfib_entry_encode (fib_node_index_t mfib_entry_index, - fib_route_path_encode_t **api_rpaths) +fib_route_path_t* +mfib_entry_encode (fib_node_index_t mfib_entry_index) { - fib_route_path_encode_t *api_rpath; + fib_path_encode_ctx_t ctx = { + .rpaths = NULL, + }; mfib_entry_t *mfib_entry; + fib_route_path_t *rpath; mfib_entry_src_t *bsrc; mfib_entry = mfib_entry_get(mfib_entry_index); @@ -1337,20 +1347,22 @@ mfib_entry_encode (fib_node_index_t mfib_entry_index, fib_path_list_walk_w_ext(bsrc->mfes_pl, NULL, fib_path_encode, - api_rpaths); + &ctx); } - vec_foreach(api_rpath, *api_rpaths) + vec_foreach(rpath, ctx.rpaths) { mfib_itf_t *mfib_itf; mfib_itf = mfib_entry_itf_find(bsrc->mfes_itfs, - api_rpath->rpath.frp_sw_if_index); + rpath->frp_sw_if_index); if (mfib_itf) { - api_rpath->rpath.frp_mitf_flags = mfib_itf->mfi_flags; + rpath->frp_mitf_flags = mfib_itf->mfi_flags; } } + + return (ctx.rpaths); } const mfib_prefix_t * diff --git a/src/vnet/mfib/mfib_entry.h b/src/vnet/mfib/mfib_entry.h index 8ab7cee5ea7..4a1121bc9d5 100644 --- a/src/vnet/mfib/mfib_entry.h +++ b/src/vnet/mfib/mfib_entry.h @@ -135,8 +135,7 @@ extern int mfib_entry_special_add(fib_node_index_t fib_entry_index, extern void mfib_entry_path_update(fib_node_index_t fib_entry_index, mfib_source_t source, - const fib_route_path_t *rpath, - mfib_itf_flags_t itf_flags); + const fib_route_path_t *rpath); extern int mfib_entry_path_remove(fib_node_index_t fib_entry_index, @@ -188,8 +187,7 @@ extern void mfib_entry_contribute_forwarding( mfib_entry_fwd_flags_t flags, dpo_id_t *dpo); -extern void mfib_entry_encode(fib_node_index_t fib_entry_index, - fib_route_path_encode_t **api_rpaths); +extern fib_route_path_t* mfib_entry_encode(fib_node_index_t fib_entry_index); extern void mfib_entry_module_init(void); diff --git a/src/vnet/mfib/mfib_table.c b/src/vnet/mfib/mfib_table.c index 68154b37ff8..504333a2474 100644 --- a/src/vnet/mfib/mfib_table.c +++ b/src/vnet/mfib/mfib_table.c @@ -286,12 +286,11 @@ mfib_table_entry_update (u32 fib_index, return (mfib_entry_index); } -fib_node_index_t -mfib_table_entry_path_update (u32 fib_index, - const mfib_prefix_t *prefix, - mfib_source_t source, - const fib_route_path_t *rpath, - mfib_itf_flags_t itf_flags) +static fib_node_index_t +mfib_table_entry_paths_update_i (u32 fib_index, + const mfib_prefix_t *prefix, + mfib_source_t source, + const fib_route_path_t *rpaths) { fib_node_index_t mfib_entry_index; mfib_table_t *mfib_table; @@ -308,30 +307,53 @@ mfib_table_entry_path_update (u32 fib_index, MFIB_ENTRY_FLAG_NONE, INDEX_INVALID); - mfib_entry_path_update(mfib_entry_index, - source, - rpath, - itf_flags); + mfib_entry_path_update(mfib_entry_index, source, rpaths); mfib_table_entry_insert(mfib_table, prefix, mfib_entry_index); } else { - mfib_entry_path_update(mfib_entry_index, - source, - rpath, - itf_flags); + mfib_entry_path_update(mfib_entry_index, source, rpaths); } return (mfib_entry_index); } -void -mfib_table_entry_path_remove (u32 fib_index, + +fib_node_index_t +mfib_table_entry_path_update (u32 fib_index, const mfib_prefix_t *prefix, mfib_source_t source, const fib_route_path_t *rpath) { fib_node_index_t mfib_entry_index; + fib_route_path_t *rpaths = NULL; + + vec_add1(rpaths, *rpath); + + mfib_entry_index = mfib_table_entry_paths_update_i(fib_index, prefix, + source, rpaths); + + vec_free(rpaths); + return (mfib_entry_index); +} + +fib_node_index_t +mfib_table_entry_paths_update (u32 fib_index, + const mfib_prefix_t *prefix, + mfib_source_t source, + const fib_route_path_t *rpaths) +{ + return (mfib_table_entry_paths_update_i(fib_index, prefix, + source, rpaths)); +} + +static void +mfib_table_entry_paths_remove_i (u32 fib_index, + const mfib_prefix_t *prefix, + mfib_source_t source, + const fib_route_path_t *rpaths) +{ + fib_node_index_t mfib_entry_index; mfib_table_t *mfib_table; mfib_table = mfib_table_get(fib_index, prefix->fp_proto); @@ -340,7 +362,7 @@ mfib_table_entry_path_remove (u32 fib_index, if (FIB_NODE_INDEX_INVALID == mfib_entry_index) { /* - * removing an etry that does not exist. i'll allow it. + * removing an entry that does not exist. i'll allow it. */ } else @@ -354,7 +376,7 @@ mfib_table_entry_path_remove (u32 fib_index, no_more_sources = mfib_entry_path_remove(mfib_entry_index, source, - rpath); + rpaths); if (no_more_sources) { @@ -367,6 +389,35 @@ mfib_table_entry_path_remove (u32 fib_index, mfib_entry_unlock(mfib_entry_index); } } +void +mfib_table_entry_paths_remove (u32 fib_index, + const mfib_prefix_t *prefix, + mfib_source_t source, + const fib_route_path_t *rpaths) +{ + mfib_table_entry_paths_remove_i(fib_index, + prefix, + source, + rpaths); +} + +void +mfib_table_entry_path_remove (u32 fib_index, + const mfib_prefix_t *prefix, + mfib_source_t source, + const fib_route_path_t *rpath) +{ + fib_route_path_t *rpaths = NULL; + + vec_add1(rpaths, *rpath); + + mfib_table_entry_paths_remove_i(fib_index, + prefix, + source, + rpaths); + + vec_free(rpaths); +} fib_node_index_t mfib_table_entry_special_add (u32 fib_index, @@ -464,12 +515,10 @@ void mfib_table_entry_delete_index (fib_node_index_t mfib_entry_index, mfib_source_t source) { - const mfib_prefix_t *prefix; - - prefix = mfib_entry_get_prefix(mfib_entry_index); - mfib_table_entry_delete_i(mfib_entry_get_fib_index(mfib_entry_index), - mfib_entry_index, prefix, source); + mfib_entry_index, + mfib_entry_get_prefix(mfib_entry_index), + source); } u32 diff --git a/src/vnet/mfib/mfib_table.h b/src/vnet/mfib/mfib_table.h index 6be4f798cd7..47461375a10 100644 --- a/src/vnet/mfib/mfib_table.h +++ b/src/vnet/mfib/mfib_table.h @@ -164,8 +164,11 @@ extern fib_node_index_t mfib_table_entry_update(u32 fib_index, extern fib_node_index_t mfib_table_entry_path_update(u32 fib_index, const mfib_prefix_t *prefix, mfib_source_t source, - const fib_route_path_t *rpath, - mfib_itf_flags_t flags); + const fib_route_path_t *rpath); +extern fib_node_index_t mfib_table_entry_paths_update(u32 fib_index, + const mfib_prefix_t *prefix, + mfib_source_t source, + const fib_route_path_t *rpath); /** * @brief @@ -190,6 +193,10 @@ extern void mfib_table_entry_path_remove(u32 fib_index, const mfib_prefix_t *prefix, mfib_source_t source, const fib_route_path_t *paths); +extern void mfib_table_entry_paths_remove(u32 fib_index, + const mfib_prefix_t *prefix, + mfib_source_t source, + const fib_route_path_t *paths); @@ -320,6 +327,20 @@ extern u32 mfib_table_get_table_id(u32 fib_index, fib_protocol_t proto); */ extern u32 mfib_table_find(fib_protocol_t proto, u32 table_id); +/** + * @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 diff --git a/src/vnet/mfib/mfib_types.api b/src/vnet/mfib/mfib_types.api new file mode 100644 index 00000000000..b2ba4329ea5 --- /dev/null +++ b/src/vnet/mfib/mfib_types.api @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2018 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. + */ + +import "vnet/fib/fib_types.api"; +import "vnet/ip/ip_types.api"; + +enum mfib_itf_flags +{ + MFIB_API_ITF_FLAG_NONE = 0, + MFIB_API_ITF_FLAG_NEGATE_SIGNAL = 0x1, + MFIB_API_ITF_FLAG_ACCEPT = 0x2, + MFIB_API_ITF_FLAG_FORWARD = 0x4, + MFIB_API_ITF_FLAG_SIGNAL_PRESENT = 0x8, + MFIB_API_ITF_FLAG_DONT_PRESERVE = 0x10, +}; + +/** \brief mFIB path +*/ +typeonly define mfib_path +{ + vl_api_mfib_itf_flags_t itf_flags; + vl_api_fib_path_t path; +}; diff --git a/src/vnet/mpls/mpls.api b/src/vnet/mpls/mpls.api index ca1aa3a8513..5d85812807a 100644 --- a/src/vnet/mpls/mpls.api +++ b/src/vnet/mpls/mpls.api @@ -15,6 +15,7 @@ option version = "1.1.0"; import "vnet/fib/fib_types.api"; +import "vnet/ip/ip_types.api"; /** \brief Bind/Unbind an MPLS local label to an IP prefix. i.e. create a per-prefix label entry. @@ -36,28 +37,24 @@ autoreply define mpls_ip_bind_unbind u32 mb_label; u32 mb_ip_table_id; u8 mb_is_bind; - u8 mb_is_ip4; - u8 mb_address_length; - u8 mb_address[16]; + vl_api_prefix_t mb_prefix; }; +typeonly define mpls_tunnel +{ + u32 mt_sw_if_index; + u32 mt_tunnel_index; + u8 mt_l2_only; + u8 mt_is_multicast; + u8 mt_n_paths; + vl_api_fib_path_t mt_paths[mt_n_paths]; +}; define mpls_tunnel_add_del { u32 client_index; u32 context; - u32 mt_sw_if_index; u8 mt_is_add; - u8 mt_l2_only; - u8 mt_is_multicast; - u8 mt_next_hop_proto_is_ip4; - u8 mt_next_hop_weight; - u8 mt_next_hop_preference; - u8 mt_next_hop[16]; - u8 mt_next_hop_n_out_labels; - u32 mt_next_hop_via_label; - u32 mt_next_hop_sw_if_index; - u32 mt_next_hop_table_id; - vl_api_fib_mpls_label_t mt_next_hop_out_label_stack[mt_next_hop_n_out_labels]; + vl_api_mpls_tunnel_t mt_tunnel; }; /** \brief Reply for MPLS tunnel add / del request @@ -90,12 +87,7 @@ define mpls_tunnel_dump manual_endian manual_print define mpls_tunnel_details { u32 context; - u32 mt_sw_if_index; - u32 mt_tunnel_index; - u8 mt_l2_only; - u8 mt_is_multicast; - u32 mt_count; - vl_api_fib_path_t mt_paths[mt_count]; + vl_api_mpls_tunnel_t mt_tunnel; }; /** \brief MPLS Route Add / del route @@ -107,68 +99,71 @@ manual_endian manual_print define mpls_tunnel_details is not set by the client, then VPP will generate something meaningfull. */ +typeonly define mpls_table +{ + u32 mt_table_id; + u8 mt_name[64]; +}; autoreply define mpls_table_add_del { u32 client_index; u32 context; - u32 mt_table_id; u8 mt_is_add; - u8 mt_name[64]; + vl_api_mpls_table_t mt_table; }; -/** \brief MPLS Route Add / del route +/** \brief Dump MPLS fib table @param client_index - opaque cookie to identify the sender - @param context - sender context, to match reply w/ request +*/ +define mpls_table_dump +{ + u32 client_index; + u32 context; +}; + +define mpls_table_details +{ + u32 context; + vl_api_mpls_table_t mt_table; +}; + +/** \brief MPLS Route @param mr_label - The MPLS label value @param mr_eos - The End of stack bit + @param mr_eos_proto - If EOS then this is the DPO packect's proto post pop @param mr_table_id - The MPLS table-id the route is added in - @param mr_classify_table_index - If this is a classify route, - this is the classify table index - create them @param mr_is_add - Is this a route add or delete - @param mr_is_classify - Is this route result a classify @param mr_is_multicast - Is this a multicast route + @param mr_n_paths - The number of paths + @param mr_paths - The paths +*/ +typeonly define mpls_route +{ + u32 mr_table_id; + u32 mr_label; + u8 mr_eos; + u8 mr_eos_proto; + u8 mr_is_multicast; + u8 mr_n_paths; + vl_api_fib_path_t mr_paths[mr_n_paths]; +}; + +/** \brief MPLS Route Add / del route + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request + @param mr_table_id - The MPLS table-id the route is added in + @param mr_is_add - Is this a route add or delete @param mr_is_multipath - Is this route update a multipath - i.e. is this a path addition to an existing route - @param mr_is_resolve_host - Recurse resolution constraint via a host prefix - @param mr_is_resolve_attached - Recurse resolution constraint via attached prefix - @param mr_is_interface_rx - Interface Receive path - @param mr_is_interface_rx - RPF-ID Receive path. The next-hop interface - is used as the RPF-ID - @param mr_next_hop_proto - The next-hop protocol, of type dpo_proto_t - @param mr_next_hop_weight - The weight, for UCMP - @param mr_next_hop[16] - the nextop address - @param mr_next_hop_sw_if_index - the next-hop SW interface - @param mr_next_hop_table_id - the next-hop table-id (if appropriate) - @param mr_next_hop_n_out_labels - the number of labels in the label stack - @param mr_next_hop_out_label_stack - the next-hop output label stack, outer most first - @param next_hop_via_label - The next-hop is a resolved via a local label + @param mr_route - The Route */ define mpls_route_add_del { u32 client_index; u32 context; - u32 mr_label; - u8 mr_eos; - u32 mr_table_id; - u32 mr_classify_table_index; u8 mr_is_add; - u8 mr_is_classify; - u8 mr_is_multicast; u8 mr_is_multipath; - u8 mr_is_resolve_host; - u8 mr_is_resolve_attached; - u8 mr_is_interface_rx; - u8 mr_is_rpf_id; - u8 mr_next_hop_proto; - u8 mr_next_hop_weight; - u8 mr_next_hop_preference; - u8 mr_next_hop[16]; - u8 mr_next_hop_n_out_labels; - u32 mr_next_hop_sw_if_index; - u32 mr_next_hop_table_id; - u32 mr_next_hop_via_label; - vl_api_fib_mpls_label_t mr_next_hop_out_label_stack[mr_next_hop_n_out_labels]; + vl_api_mpls_route_t mr_route; }; define mpls_route_add_del_reply @@ -181,10 +176,11 @@ define mpls_route_add_del_reply /** \brief Dump MPLS fib table @param client_index - opaque cookie to identify the sender */ -define mpls_fib_dump +define mpls_route_dump { u32 client_index; u32 context; + vl_api_mpls_table_t table; }; /** \brief mpls FIB table response @@ -194,15 +190,10 @@ define mpls_fib_dump @param count - the number of fib_path in path @param path - array of of fib_path structures */ -manual_endian manual_print define mpls_fib_details +manual_endian manual_print define mpls_route_details { u32 context; - u32 table_id; - u8 table_name[64]; - u8 eos_bit; - u32 label; - u32 count; - vl_api_fib_path_t path[count]; + vl_api_mpls_route_t mr_route; }; /** \brief Enable or Disable MPLS on and interface diff --git a/src/vnet/mpls/mpls_api.c b/src/vnet/mpls/mpls_api.c index 52434dae8aa..cb20df5695b 100644 --- a/src/vnet/mpls/mpls_api.c +++ b/src/vnet/mpls/mpls_api.c @@ -28,6 +28,7 @@ #include <vnet/fib/fib_api.h> #include <vnet/fib/mpls_fib.h> #include <vnet/fib/fib_path_list.h> +#include <vnet/ip/ip_types_api.h> #include <vnet/vnet_msg_enum.h> @@ -54,7 +55,8 @@ _(MPLS_TABLE_ADD_DEL, mpls_table_add_del) \ _(MPLS_TUNNEL_ADD_DEL, mpls_tunnel_add_del) \ _(MPLS_TUNNEL_DUMP, mpls_tunnel_dump) \ _(SW_INTERFACE_SET_MPLS_ENABLE, sw_interface_set_mpls_enable) \ -_(MPLS_FIB_DUMP, mpls_fib_dump) +_(MPLS_TABLE_DUMP, mpls_table_dump) \ +_(MPLS_ROUTE_DUMP, mpls_route_dump) void mpls_table_delete (u32 table_id, u8 is_api) @@ -90,9 +92,10 @@ vl_api_mpls_table_add_del_t_handler (vl_api_mpls_table_add_del_t * mp) vnm->api_errno = 0; if (mp->mt_is_add) - mpls_table_create (ntohl (mp->mt_table_id), 1, mp->mt_name); + mpls_table_create (ntohl (mp->mt_table.mt_table_id), + 1, mp->mt_table.mt_name); else - mpls_table_delete (ntohl (mp->mt_table_id), 1); + mpls_table_delete (ntohl (mp->mt_table.mt_table_id), 1); // NB: Nothing sets rv; none of the above returns an error @@ -104,6 +107,7 @@ mpls_ip_bind_unbind_handler (vnet_main_t * vnm, vl_api_mpls_ip_bind_unbind_t * mp) { u32 mpls_fib_index, ip_fib_index; + fib_prefix_t pfx; mpls_fib_index = fib_table_find (FIB_PROTOCOL_MPLS, ntohl (mp->mb_mpls_table_id)); @@ -113,30 +117,12 @@ mpls_ip_bind_unbind_handler (vnet_main_t * vnm, return VNET_API_ERROR_NO_SUCH_FIB; } - ip_fib_index = fib_table_find ((mp->mb_is_ip4 ? - FIB_PROTOCOL_IP4 : - FIB_PROTOCOL_IP6), - ntohl (mp->mb_ip_table_id)); + ip_prefix_decode (&mp->mb_prefix, &pfx); + + ip_fib_index = fib_table_find (pfx.fp_proto, ntohl (mp->mb_ip_table_id)); if (~0 == ip_fib_index) return VNET_API_ERROR_NO_SUCH_FIB; - fib_prefix_t pfx = { - .fp_len = mp->mb_address_length, - }; - - if (mp->mb_is_ip4) - { - pfx.fp_proto = FIB_PROTOCOL_IP4; - clib_memcpy (&pfx.fp_addr.ip4, mp->mb_address, - sizeof (pfx.fp_addr.ip4)); - } - else - { - pfx.fp_proto = FIB_PROTOCOL_IP6; - clib_memcpy (&pfx.fp_addr.ip6, mp->mb_address, - sizeof (pfx.fp_addr.ip6)); - } - if (mp->mb_is_bind) fib_table_entry_local_label_add (ip_fib_index, &pfx, ntohl (mp->mb_label)); @@ -168,92 +154,58 @@ mpls_route_add_del_t_handler (vnet_main_t * vnm, vl_api_mpls_route_add_del_t * mp, u32 * stats_index) { - fib_mpls_label_t *label_stack = NULL; - u32 fib_index, next_hop_fib_index; - int rv, ii, n_labels;; + fib_route_path_t *rpaths = NULL, *rpath; + vl_api_fib_path_t *apath; + u32 fib_index; + int rv, ii; fib_prefix_t pfx = { .fp_len = 21, .fp_proto = FIB_PROTOCOL_MPLS, - .fp_eos = mp->mr_eos, - .fp_label = ntohl (mp->mr_label), + .fp_eos = mp->mr_route.mr_eos, + .fp_label = ntohl (mp->mr_route.mr_label), }; if (pfx.fp_eos) { - pfx.fp_payload_proto = mp->mr_next_hop_proto; + pfx.fp_payload_proto = mp->mr_route.mr_eos_proto; } else { pfx.fp_payload_proto = DPO_PROTO_MPLS; } - rv = add_del_route_check (FIB_PROTOCOL_MPLS, - mp->mr_table_id, - mp->mr_next_hop_sw_if_index, - pfx.fp_payload_proto, - mp->mr_next_hop_table_id, - mp->mr_is_rpf_id, - &fib_index, &next_hop_fib_index); - + rv = fib_api_table_id_decode (FIB_PROTOCOL_MPLS, + ntohl (mp->mr_route.mr_table_id), &fib_index); if (0 != rv) - return (rv); - - ip46_address_t nh; - clib_memset (&nh, 0, sizeof (nh)); + goto out; - if (DPO_PROTO_IP4 == mp->mr_next_hop_proto) - memcpy (&nh.ip4, mp->mr_next_hop, sizeof (nh.ip4)); - else if (DPO_PROTO_IP6 == mp->mr_next_hop_proto) - memcpy (&nh.ip6, mp->mr_next_hop, sizeof (nh.ip6)); + vec_validate (rpaths, mp->mr_route.mr_n_paths - 1); - n_labels = mp->mr_next_hop_n_out_labels; - if (n_labels == 0) - ; - else + for (ii = 0; ii < mp->mr_route.mr_n_paths; ii++) { - vec_validate (label_stack, n_labels - 1); - for (ii = 0; ii < n_labels; ii++) - { - label_stack[ii].fml_value = - ntohl (mp->mr_next_hop_out_label_stack[ii].label); - label_stack[ii].fml_ttl = mp->mr_next_hop_out_label_stack[ii].ttl; - label_stack[ii].fml_exp = mp->mr_next_hop_out_label_stack[ii].exp; - label_stack[ii].fml_mode = - (mp->mr_next_hop_out_label_stack[ii].is_uniform ? - FIB_MPLS_LSP_MODE_UNIFORM : FIB_MPLS_LSP_MODE_PIPE); - } + apath = &mp->mr_route.mr_paths[ii]; + rpath = &rpaths[ii]; + + rv = fib_api_path_decode (apath, rpath); + + if (0 != rv) + goto out; } - /* *INDENT-OFF* */ - rv = add_del_route_t_handler (mp->mr_is_multipath, mp->mr_is_add, - 0, // mp->is_drop, - 0, // mp->is_unreach, - 0, // mp->is_prohibit, - 0, // mp->is_local, - mp->mr_is_multicast, - mp->mr_is_classify, - mp->mr_classify_table_index, - mp->mr_is_resolve_host, - mp->mr_is_resolve_attached, - mp->mr_is_interface_rx, - mp->mr_is_rpf_id, - 0, // l2_bridged - 0, // is source_lookup - 0, // is_udp_encap - fib_index, &pfx, - mp->mr_next_hop_proto, - &nh, ~0, // next_hop_id - ntohl (mp->mr_next_hop_sw_if_index), - next_hop_fib_index, - mp->mr_next_hop_weight, - mp->mr_next_hop_preference, - ntohl (mp->mr_next_hop_via_label), - label_stack); - /* *INDENT-ON* */ + fib_api_route_add_del (mp->mr_is_add, + mp->mr_is_multipath, + fib_index, + &pfx, + (mp->mr_route.mr_is_multicast ? + FIB_ENTRY_FLAG_MULTICAST : + FIB_ENTRY_FLAG_NONE), rpaths); if (mp->mr_is_add && 0 == rv) *stats_index = fib_table_entry_get_stats_index (fib_index, &pfx); +out: + vec_free (rpaths); + return (rv); } @@ -308,73 +260,30 @@ mpls_table_create (u32 table_id, u8 is_api, const u8 * name) static void vl_api_mpls_tunnel_add_del_t_handler (vl_api_mpls_tunnel_add_del_t * mp) { - u32 tunnel_sw_if_index = ~0, tunnel_index = ~0, next_hop_via_label; + u32 tunnel_sw_if_index = ~0, tunnel_index = ~0; vl_api_mpls_tunnel_add_del_reply_t *rmp; - fib_route_path_t rpath, *rpaths = NULL; + fib_route_path_t *rpath, *rpaths = NULL; int ii, rv = 0; - clib_memset (&rpath, 0, sizeof (rpath)); + vec_validate (rpaths, mp->mt_tunnel.mt_n_paths - 1); - if (mp->mt_next_hop_proto_is_ip4) + for (ii = 0; ii < mp->mt_tunnel.mt_n_paths; ii++) { - rpath.frp_proto = DPO_PROTO_IP4; - clib_memcpy (&rpath.frp_addr.ip4, - mp->mt_next_hop, sizeof (rpath.frp_addr.ip4)); - } - else - { - rpath.frp_proto = DPO_PROTO_IP6; - clib_memcpy (&rpath.frp_addr.ip6, - mp->mt_next_hop, sizeof (rpath.frp_addr.ip6)); - } - rpath.frp_sw_if_index = ntohl (mp->mt_next_hop_sw_if_index); - rpath.frp_weight = mp->mt_next_hop_weight; - rpath.frp_preference = mp->mt_next_hop_preference; + rpath = &rpaths[ii]; - next_hop_via_label = ntohl (mp->mt_next_hop_via_label); - if ((MPLS_LABEL_INVALID != next_hop_via_label) && (0 != next_hop_via_label)) - { - rpath.frp_proto = DPO_PROTO_MPLS; - rpath.frp_local_label = next_hop_via_label; - rpath.frp_eos = MPLS_NON_EOS; - } + rv = fib_api_path_decode (&mp->mt_tunnel.mt_paths[ii], rpath); - if (rpath.frp_sw_if_index == ~0) - { /* recursive path, set fib index */ - rpath.frp_fib_index = - fib_table_find (dpo_proto_to_fib (rpath.frp_proto), - ntohl (mp->mt_next_hop_table_id)); - if (rpath.frp_fib_index == ~0) - { - rv = VNET_API_ERROR_NO_SUCH_FIB; - goto out; - } + if (0 != rv) + goto out; } - - if (mp->mt_is_add) - { - for (ii = 0; ii < mp->mt_next_hop_n_out_labels; ii++) - { - fib_mpls_label_t fml = { - .fml_value = ntohl (mp->mt_next_hop_out_label_stack[ii].label), - .fml_ttl = mp->mt_next_hop_out_label_stack[ii].ttl, - .fml_exp = mp->mt_next_hop_out_label_stack[ii].exp, - .fml_mode = (mp->mt_next_hop_out_label_stack[ii].is_uniform ? - FIB_MPLS_LSP_MODE_UNIFORM : FIB_MPLS_LSP_MODE_PIPE), - }; - vec_add1 (rpath.frp_label_stack, fml); - } - } - - vec_add1 (rpaths, rpath); - - tunnel_sw_if_index = ntohl (mp->mt_sw_if_index); + tunnel_sw_if_index = ntohl (mp->mt_tunnel.mt_sw_if_index); if (mp->mt_is_add) { if (~0 == tunnel_sw_if_index) - tunnel_sw_if_index = vnet_mpls_tunnel_create (mp->mt_l2_only, - mp->mt_is_multicast); + tunnel_sw_if_index = + vnet_mpls_tunnel_create (mp->mt_tunnel.mt_l2_only, + mp->mt_tunnel.mt_is_multicast); vnet_mpls_tunnel_path_add (tunnel_sw_if_index, rpaths); tunnel_index = vnet_mpls_tunnel_get_index (tunnel_sw_if_index); @@ -382,7 +291,7 @@ vl_api_mpls_tunnel_add_del_t_handler (vl_api_mpls_tunnel_add_del_t * mp) else { tunnel_index = vnet_mpls_tunnel_get_index (tunnel_sw_if_index); - tunnel_sw_if_index = ntohl (mp->mt_sw_if_index); + tunnel_sw_if_index = ntohl (mp->mt_tunnel.mt_sw_if_index); if (!vnet_mpls_tunnel_path_remove (tunnel_sw_if_index, rpaths)) vnet_mpls_tunnel_del (tunnel_sw_if_index); } @@ -426,10 +335,13 @@ typedef struct mpls_tunnel_send_walk_ctx_t_ static void send_mpls_tunnel_entry (u32 mti, void *arg) { - fib_route_path_encode_t *api_rpaths = NULL, *api_rpath; mpls_tunnel_send_walk_ctx_t *ctx; vl_api_mpls_tunnel_details_t *mp; + fib_path_encode_ctx_t path_ctx = { + .rpaths = NULL, + }; const mpls_tunnel_t *mt; + fib_route_path_t *rpath; vl_api_fib_path_t *fp; u32 n; @@ -448,21 +360,25 @@ send_mpls_tunnel_entry (u32 mti, void *arg) mp->_vl_msg_id = ntohs (VL_API_MPLS_TUNNEL_DETAILS); mp->context = ctx->context; - mp->mt_tunnel_index = ntohl (mti); - mp->mt_sw_if_index = ntohl (mt->mt_sw_if_index); - mp->mt_count = ntohl (n); + mp->mt_tunnel.mt_n_paths = ntohl (n); + mp->mt_tunnel.mt_sw_if_index = ntohl (mt->mt_sw_if_index); + mp->mt_tunnel.mt_tunnel_index = ntohl (mti); + mp->mt_tunnel.mt_l2_only = ! !(MPLS_TUNNEL_FLAG_L2 & mt->mt_flags); + mp->mt_tunnel.mt_is_multicast = ! !(MPLS_TUNNEL_FLAG_MCAST & mt->mt_flags); fib_path_list_walk_w_ext (mt->mt_path_list, - &mt->mt_path_exts, fib_path_encode, &api_rpaths); + &mt->mt_path_exts, fib_path_encode, &path_ctx); - fp = mp->mt_paths; - vec_foreach (api_rpath, api_rpaths) + fp = mp->mt_tunnel.mt_paths; + vec_foreach (rpath, path_ctx.rpaths) { - fib_api_path_encode (api_rpath, fp); + fib_api_path_encode (rpath, fp); fp++; } vl_api_send_msg (ctx->reg, (u8 *) mp); + + vec_free (path_ctx.rpaths); } static void @@ -483,51 +399,95 @@ vl_api_mpls_tunnel_dump_t_handler (vl_api_mpls_tunnel_dump_t * mp) } static void -send_mpls_fib_details (vpe_api_main_t * am, - vl_api_registration_t * reg, - const fib_table_t * table, - const fib_prefix_t * pfx, - fib_route_path_encode_t * api_rpaths, u32 context) +send_mpls_table_details (vpe_api_main_t * am, + vl_api_registration_t * reg, + u32 context, const fib_table_t * table) +{ + vl_api_mpls_table_details_t *mp; + + mp = vl_msg_api_alloc (sizeof (*mp)); + memset (mp, 0, sizeof (*mp)); + mp->_vl_msg_id = ntohs (VL_API_MPLS_TABLE_DETAILS); + mp->context = context; + + mp->mt_table.mt_table_id = htonl (table->ft_table_id); + memcpy (mp->mt_table.mt_name, + table->ft_desc, + clib_min (vec_len (table->ft_desc), sizeof (mp->mt_table.mt_name))); + + vl_api_send_msg (reg, (u8 *) mp); +} + +static void +vl_api_mpls_table_dump_t_handler (vl_api_mpls_table_dump_t * mp) { - vl_api_mpls_fib_details_t *mp; - fib_route_path_encode_t *api_rpath; + vpe_api_main_t *am = &vpe_api_main; + vl_api_registration_t *reg; + mpls_main_t *mm = &mpls_main; + fib_table_t *fib_table; + + reg = vl_api_client_index_to_registration (mp->client_index); + if (!reg) + return; + + /* *INDENT-OFF* */ + pool_foreach (fib_table, mm->fibs, + ({ + send_mpls_table_details(am, reg, mp->context, fib_table); + })); + /* *INDENT-ON* */ +} + +static void +send_mpls_route_details (vpe_api_main_t * am, + vl_api_registration_t * reg, + u32 context, fib_node_index_t fib_entry_index) +{ + fib_route_path_t *rpaths, *rpath; + vl_api_mpls_route_details_t *mp; + const fib_prefix_t *pfx; vl_api_fib_path_t *fp; int path_count; - path_count = vec_len (api_rpaths); + rpaths = fib_entry_encode (fib_entry_index); + pfx = fib_entry_get_prefix (fib_entry_index); + + path_count = vec_len (rpaths); mp = vl_msg_api_alloc (sizeof (*mp) + path_count * sizeof (*fp)); if (!mp) return; clib_memset (mp, 0, sizeof (*mp)); - mp->_vl_msg_id = ntohs (VL_API_MPLS_FIB_DETAILS); + mp->_vl_msg_id = ntohs (VL_API_MPLS_ROUTE_DETAILS); mp->context = context; - mp->table_id = htonl (table->ft_table_id); - memcpy (mp->table_name, table->ft_desc, - clib_min (vec_len (table->ft_desc), sizeof (mp->table_name))); - mp->eos_bit = pfx->fp_eos; - mp->label = htonl (pfx->fp_label); + mp->mr_route.mr_table_id = + htonl (fib_table_get_table_id + (fib_entry_get_fib_index (fib_entry_index), pfx->fp_proto)); + mp->mr_route.mr_eos = pfx->fp_eos; + mp->mr_route.mr_eos_proto = pfx->fp_payload_proto; + mp->mr_route.mr_label = htonl (pfx->fp_label); - mp->count = htonl (path_count); - fp = mp->path; - vec_foreach (api_rpath, api_rpaths) + mp->mr_route.mr_n_paths = path_count; + fp = mp->mr_route.mr_paths; + vec_foreach (rpath, rpaths) { - fib_api_path_encode (api_rpath, fp); + fib_api_path_encode (rpath, fp); fp++; } + vec_free (rpaths); vl_api_send_msg (reg, (u8 *) mp); } -typedef struct vl_api_mpls_fib_dump_table_walk_ctx_t_ +typedef struct vl_api_mpls_route_dump_table_walk_ctx_t_ { fib_node_index_t *lfeis; -} vl_api_mpls_fib_dump_table_walk_ctx_t; +} vl_api_mpls_route_dump_table_walk_ctx_t; static fib_table_walk_rc_t -vl_api_mpls_fib_dump_table_walk (fib_node_index_t fei, void *arg) +vl_api_mpls_route_dump_table_walk (fib_node_index_t fei, void *arg) { - vl_api_mpls_fib_dump_table_walk_ctx_t *ctx = arg; + vl_api_mpls_route_dump_table_walk_ctx_t *ctx = arg; vec_add1 (ctx->lfeis, fei); @@ -535,47 +495,37 @@ vl_api_mpls_fib_dump_table_walk (fib_node_index_t fei, void *arg) } static void -vl_api_mpls_fib_dump_t_handler (vl_api_mpls_fib_dump_t * mp) +vl_api_mpls_route_dump_t_handler (vl_api_mpls_route_dump_t * mp) { vpe_api_main_t *am = &vpe_api_main; vl_api_registration_t *reg; - mpls_main_t *mm = &mpls_main; - fib_table_t *fib_table; - mpls_fib_t *mpls_fib; fib_node_index_t *lfeip = NULL; - const fib_prefix_t *pfx; - u32 fib_index; - fib_route_path_encode_t *api_rpaths; - vl_api_mpls_fib_dump_table_walk_ctx_t ctx = { + vl_api_mpls_route_dump_table_walk_ctx_t ctx = { .lfeis = NULL, }; + u32 fib_index; reg = vl_api_client_index_to_registration (mp->client_index); if (!reg) return; - /* *INDENT-OFF* */ - pool_foreach (mpls_fib, mm->mpls_fibs, - ({ - mpls_fib_table_walk (mpls_fib, - vl_api_mpls_fib_dump_table_walk, - &ctx); - })); - /* *INDENT-ON* */ - vec_sort_with_function (ctx.lfeis, fib_entry_cmp_for_sort); + fib_index = fib_table_find (FIB_PROTOCOL_MPLS, + ntohl (mp->table.mt_table_id)); - vec_foreach (lfeip, ctx.lfeis) - { - pfx = fib_entry_get_prefix (*lfeip); - fib_index = fib_entry_get_fib_index (*lfeip); - fib_table = fib_table_get (fib_index, pfx->fp_proto); - api_rpaths = NULL; - fib_entry_encode (*lfeip, &api_rpaths); - send_mpls_fib_details (am, reg, fib_table, pfx, api_rpaths, mp->context); - vec_free (api_rpaths); - } + if (INDEX_INVALID != fib_index) + { + fib_table_walk (fib_index, + FIB_PROTOCOL_MPLS, + vl_api_mpls_route_dump_table_walk, &ctx); + vec_sort_with_function (ctx.lfeis, fib_entry_cmp_for_sort); - vec_free (ctx.lfeis); + vec_foreach (lfeip, ctx.lfeis) + { + send_mpls_route_details (am, reg, mp->context, *lfeip); + } + + vec_free (ctx.lfeis); + } } /* diff --git a/src/vnet/mpls/mpls_tunnel.c b/src/vnet/mpls/mpls_tunnel.c index 8db08c3a387..b7bcbfd14f7 100644 --- a/src/vnet/mpls/mpls_tunnel.c +++ b/src/vnet/mpls/mpls_tunnel.c @@ -242,7 +242,7 @@ mpls_tunnel_stack (adj_index_t ai) mt = mpls_tunnel_get_from_sw_if_index(sw_if_index); - if (NULL == mt) + if (NULL == mt || FIB_NODE_INDEX_INVALID == mt->mt_path_list) return; if (FIB_NODE_INDEX_INVALID == mt->mt_path_list) @@ -654,6 +654,7 @@ void vnet_mpls_tunnel_path_add (u32 sw_if_index, fib_route_path_t *rpaths) { + fib_route_path_t *rpath; mpls_tunnel_t *mt; u32 mti; @@ -695,10 +696,13 @@ vnet_mpls_tunnel_path_add (u32 sw_if_index, */ fib_path_ext_list_resolve(&mt->mt_path_exts, mt->mt_path_list); } - fib_path_ext_list_insert(&mt->mt_path_exts, - mt->mt_path_list, - FIB_PATH_EXT_MPLS, - rpaths); + vec_foreach(rpath, rpaths) + { + fib_path_ext_list_insert(&mt->mt_path_exts, + mt->mt_path_list, + FIB_PATH_EXT_MPLS, + rpath); + } mpls_tunnel_restack(mt); } diff --git a/src/vnet/udp/udp_encap.c b/src/vnet/udp/udp_encap.c index c8268276288..df4a811f3dd 100644 --- a/src/vnet/udp/udp_encap.c +++ b/src/vnet/udp/udp_encap.c @@ -211,7 +211,7 @@ format_udp_encap_i (u8 * s, va_list * args) ue = udp_encap_get (uei); // FIXME - s = format (s, "udp-ecap:[%d]: ip-fib-index:%d ", uei, ue->ue_fib_index); + s = format (s, "udp-encap:[%d]: ip-fib-index:%d ", uei, ue->ue_fib_index); if (FIB_PROTOCOL_IP4 == ue->ue_ip_proto) { s = format (s, "ip:[src:%U, dst:%U] udp:[src:%d, dst:%d]", diff --git a/src/vnet/vxlan-gbp/vxlan_gbp.c b/src/vnet/vxlan-gbp/vxlan_gbp.c index 001de73b840..7b09b57bd59 100644 --- a/src/vnet/vxlan-gbp/vxlan_gbp.c +++ b/src/vnet/vxlan-gbp/vxlan_gbp.c @@ -557,6 +557,7 @@ int vnet_vxlan_gbp_tunnel_add_del .frp_fib_index = ~0, .frp_weight = 0, .frp_flags = FIB_ROUTE_PATH_LOCAL, + .frp_mitf_flags = MFIB_ITF_FLAG_FORWARD, }; const mfib_prefix_t mpfx = { .fp_proto = fp, @@ -571,16 +572,15 @@ int vnet_vxlan_gbp_tunnel_add_del */ mfib_table_entry_path_update (t->encap_fib_index, &mpfx, - MFIB_SOURCE_VXLAN_GBP, - &path, MFIB_ITF_FLAG_FORWARD); + MFIB_SOURCE_VXLAN_GBP, &path); path.frp_sw_if_index = a->mcast_sw_if_index; path.frp_flags = FIB_ROUTE_PATH_FLAG_NONE; + path.frp_mitf_flags = MFIB_ITF_FLAG_ACCEPT; mfei = mfib_table_entry_path_update (t->encap_fib_index, &mpfx, MFIB_SOURCE_VXLAN_GBP, - &path, - MFIB_ITF_FLAG_ACCEPT); + &path); /* * Create the mcast adjacency to send traffic to the group diff --git a/src/vnet/vxlan-gpe/vxlan_gpe.c b/src/vnet/vxlan-gpe/vxlan_gpe.c index ca17c12a87b..dd0e544352f 100644 --- a/src/vnet/vxlan-gpe/vxlan_gpe.c +++ b/src/vnet/vxlan-gpe/vxlan_gpe.c @@ -646,8 +646,9 @@ int vnet_vxlan_gpe_add_del_tunnel .frp_addr = zero_addr, .frp_sw_if_index = 0xffffffff, .frp_fib_index = ~0, - .frp_weight = 0, + .frp_weight = 1, .frp_flags = FIB_ROUTE_PATH_LOCAL, + .frp_mitf_flags = MFIB_ITF_FLAG_FORWARD, }; const mfib_prefix_t mpfx = { .fp_proto = fp, @@ -662,16 +663,15 @@ int vnet_vxlan_gpe_add_del_tunnel */ mfib_table_entry_path_update (t->encap_fib_index, &mpfx, - MFIB_SOURCE_VXLAN_GPE, - &path, MFIB_ITF_FLAG_FORWARD); + MFIB_SOURCE_VXLAN_GPE, &path); path.frp_sw_if_index = a->mcast_sw_if_index; path.frp_flags = FIB_ROUTE_PATH_FLAG_NONE; + path.frp_mitf_flags = MFIB_ITF_FLAG_ACCEPT; mfei = mfib_table_entry_path_update (t->encap_fib_index, &mpfx, MFIB_SOURCE_VXLAN_GPE, - &path, - MFIB_ITF_FLAG_ACCEPT); + &path); /* * Create the mcast adjacency to send traffic to the group diff --git a/src/vnet/vxlan/vxlan.c b/src/vnet/vxlan/vxlan.c index 52d0812235f..def306a7846 100644 --- a/src/vnet/vxlan/vxlan.c +++ b/src/vnet/vxlan/vxlan.c @@ -538,8 +538,9 @@ int vnet_vxlan_add_del_tunnel .frp_addr = zero_addr, .frp_sw_if_index = 0xffffffff, .frp_fib_index = ~0, - .frp_weight = 0, + .frp_weight = 1, .frp_flags = FIB_ROUTE_PATH_LOCAL, + .frp_mitf_flags = MFIB_ITF_FLAG_FORWARD, }; const mfib_prefix_t mpfx = { .fp_proto = fp, @@ -553,17 +554,14 @@ int vnet_vxlan_add_del_tunnel * - the accepting interface is that from the API */ mfib_table_entry_path_update (t->encap_fib_index, - &mpfx, - MFIB_SOURCE_VXLAN, - &path, MFIB_ITF_FLAG_FORWARD); + &mpfx, MFIB_SOURCE_VXLAN, &path); path.frp_sw_if_index = a->mcast_sw_if_index; path.frp_flags = FIB_ROUTE_PATH_FLAG_NONE; + path.frp_mitf_flags = MFIB_ITF_FLAG_ACCEPT; mfei = mfib_table_entry_path_update (t->encap_fib_index, &mpfx, - MFIB_SOURCE_VXLAN, - &path, - MFIB_ITF_FLAG_ACCEPT); + MFIB_SOURCE_VXLAN, &path); /* * Create the mcast adjacency to send traffic to the group |