diff options
Diffstat (limited to 'src/vnet/fib')
-rw-r--r-- | src/vnet/fib/fib_api.c | 608 | ||||
-rw-r--r-- | src/vnet/fib/fib_api.h | 73 | ||||
-rw-r--r-- | src/vnet/fib/fib_entry.c | 24 | ||||
-rw-r--r-- | src/vnet/fib/fib_entry.h | 9 | ||||
-rw-r--r-- | src/vnet/fib/fib_entry_src.c | 67 | ||||
-rw-r--r-- | src/vnet/fib/fib_path.c | 138 | ||||
-rw-r--r-- | src/vnet/fib/fib_path.h | 28 | ||||
-rw-r--r-- | src/vnet/fib/fib_path_list.c | 236 | ||||
-rw-r--r-- | src/vnet/fib/fib_path_list.h | 4 | ||||
-rw-r--r-- | src/vnet/fib/fib_table.c | 51 | ||||
-rw-r--r-- | src/vnet/fib/fib_types.api | 127 | ||||
-rw-r--r-- | src/vnet/fib/fib_types.c | 18 | ||||
-rw-r--r-- | src/vnet/fib/fib_types.h | 52 | ||||
-rw-r--r-- | src/vnet/fib/mpls_fib.c | 17 |
14 files changed, 937 insertions, 515 deletions
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) { |