X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Fip%2Fip_api.c;h=222bc822a750fc211fe521a88d18bdc566ac8dc6;hb=af8dfbf6d8d3b5430a437e98e18f95998e9559ca;hp=0ca058ab3a85da3fc9b518c8816bc07e9a7941e3;hpb=141ecc5495985612a23465f0772711bf77f7ce60;p=vpp.git diff --git a/src/vnet/ip/ip_api.c b/src/vnet/ip/ip_api.c index 0ca058ab3a8..222bc822a75 100644 --- a/src/vnet/ip/ip_api.c +++ b/src/vnet/ip/ip_api.c @@ -69,6 +69,9 @@ _(IP_ADDRESS_DUMP, ip_address_dump) \ _(IP_DUMP, ip_dump) \ _(IP_NEIGHBOR_ADD_DEL, ip_neighbor_add_del) \ _(IP_ADD_DEL_ROUTE, ip_add_del_route) \ +_(IP_TABLE_ADD_DEL, ip_table_add_del) \ +_(IP_PUNT_POLICE, ip_punt_police) \ +_(IP_PUNT_REDIRECT, ip_punt_redirect) \ _(SET_IP_FLOW_HASH,set_ip_flow_hash) \ _(SW_INTERFACE_IP6ND_RA_CONFIG, sw_interface_ip6nd_ra_config) \ _(SW_INTERFACE_IP6ND_RA_PREFIX, sw_interface_ip6nd_ra_prefix) \ @@ -76,13 +79,15 @@ _(IP6ND_PROXY_ADD_DEL, ip6nd_proxy_add_del) \ _(IP6ND_PROXY_DUMP, ip6nd_proxy_dump) \ _(SW_INTERFACE_IP6_ENABLE_DISABLE, sw_interface_ip6_enable_disable ) \ _(SW_INTERFACE_IP6_SET_LINK_LOCAL_ADDRESS, \ - sw_interface_ip6_set_link_local_address) + sw_interface_ip6_set_link_local_address) \ +_(IP_CONTAINER_PROXY_ADD_DEL, ip_container_proxy_add_del ) extern void stats_dslock_with_hint (int hint, int tag); extern void stats_dsunlock (void); static void -send_ip_neighbor_details (u8 is_ipv6, +send_ip_neighbor_details (u32 sw_if_index, + u8 is_ipv6, u8 is_static, u8 * mac_address, u8 * ip_address, @@ -94,6 +99,7 @@ send_ip_neighbor_details (u8 is_ipv6, memset (mp, 0, sizeof (*mp)); mp->_vl_msg_id = ntohs (VL_API_IP_NEIGHBOR_DETAILS); mp->context = context; + mp->sw_if_index = htonl (sw_if_index); mp->is_ipv6 = is_ipv6; mp->is_static = is_static; memcpy (mp->mac_address, mac_address, 6); @@ -122,7 +128,8 @@ vl_api_ip_neighbor_dump_t_handler (vl_api_ip_neighbor_dump_t * mp) vec_foreach (n, ns) { send_ip_neighbor_details - (mp->is_ipv6, ((n->flags & IP6_NEIGHBOR_FLAG_STATIC) ? 1 : 0), + (sw_if_index, mp->is_ipv6, + ((n->flags & IP6_NEIGHBOR_FLAG_STATIC) ? 1 : 0), (u8 *) n->link_layer_address, (u8 *) & (n->key.ip6_address.as_u8), q, mp->context); @@ -138,7 +145,7 @@ vl_api_ip_neighbor_dump_t_handler (vl_api_ip_neighbor_dump_t * mp) /* *INDENT-OFF* */ vec_foreach (n, ns) { - send_ip_neighbor_details (mp->is_ipv6, + send_ip_neighbor_details (sw_if_index, mp->is_ipv6, ((n->flags & ETHERNET_ARP_IP4_ENTRY_FLAG_STATIC) ? 1 : 0), (u8*) n->ethernet_address, (u8*) & (n->ip4_address.as_u8), @@ -156,9 +163,9 @@ copy_fib_next_hop (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 == FIB_PROTOCOL_IP4) + if (api_rpath->rpath.frp_proto == DPO_PROTO_IP4) fp->afi = IP46_TYPE_IP4; - else if (api_rpath->rpath.frp_proto == FIB_PROTOCOL_IP6) + else if (api_rpath->rpath.frp_proto == DPO_PROTO_IP6) fp->afi = IP46_TYPE_IP6; else { @@ -179,7 +186,8 @@ copy_fib_next_hop (fib_route_path_encode_t * api_rpath, void *fp_arg) static void send_ip_fib_details (vpe_api_main_t * am, unix_shared_memory_queue_t * q, - u32 table_id, fib_prefix_t * pfx, + 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; @@ -195,7 +203,9 @@ send_ip_fib_details (vpe_api_main_t * am, mp->_vl_msg_id = ntohs (VL_API_IP_FIB_DETAILS); mp->context = context; - mp->table_id = htonl (table_id); + 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)); @@ -231,7 +241,8 @@ send_ip_fib_details (vpe_api_main_t * am, default: break; } - fp->weight = htonl (api_rpath->rpath.frp_weight); + fp->weight = api_rpath->rpath.frp_weight; + fp->preference = api_rpath->rpath.frp_preference; fp->sw_if_index = htonl (api_rpath->rpath.frp_sw_if_index); copy_fib_next_hop (api_rpath, fp); fp++; @@ -240,6 +251,21 @@ send_ip_fib_details (vpe_api_main_t * am, vl_msg_api_send_shmem (q, (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 int +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 (1); +} + static void vl_api_ip_fib_dump_t_handler (vl_api_ip_fib_dump_t * mp) { @@ -247,12 +273,13 @@ vl_api_ip_fib_dump_t_handler (vl_api_ip_fib_dump_t * mp) unix_shared_memory_queue_t *q; ip4_main_t *im = &ip4_main; fib_table_t *fib_table; - fib_node_index_t lfei, *lfeip, *lfeis = NULL; - mpls_label_t key; + fib_node_index_t *lfeip; fib_prefix_t pfx; u32 fib_index; fib_route_path_encode_t *api_rpaths; - int i; + vl_api_ip_fib_dump_walk_ctx_t ctx = { + .feis = NULL, + }; q = vl_api_client_index_to_input_queue (mp->client_index); if (q == 0) @@ -261,32 +288,27 @@ vl_api_ip_fib_dump_t_handler (vl_api_ip_fib_dump_t * mp) /* *INDENT-OFF* */ pool_foreach (fib_table, im->fibs, ({ - for (i = 0; i < ARRAY_LEN (fib_table->v4.fib_entry_by_dst_address); i++) - { - hash_foreach(key, lfei, fib_table->v4.fib_entry_by_dst_address[i], - ({ - vec_add1(lfeis, lfei); - })); - } + fib_table_walk(fib_table->ft_index, + FIB_PROTOCOL_IP4, + vl_api_ip_fib_dump_walk, + &ctx); })); /* *INDENT-ON* */ - vec_sort_with_function (lfeis, fib_entry_cmp_for_sort); + vec_sort_with_function (ctx.feis, fib_entry_cmp_for_sort); - vec_foreach (lfeip, lfeis) + vec_foreach (lfeip, ctx.feis) { fib_entry_get_prefix (*lfeip, &pfx); 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, q, - fib_table->ft_table_id, &pfx, api_rpaths, - mp->context); + send_ip_fib_details (am, q, fib_table, &pfx, api_rpaths, mp->context); vec_free (api_rpaths); } - vec_free (lfeis); + vec_free (ctx.feis); } static void @@ -344,7 +366,8 @@ send_ip6_fib_details (vpe_api_main_t * am, default: break; } - fp->weight = htonl (api_rpath->rpath.frp_weight); + fp->weight = api_rpath->rpath.frp_weight; + fp->preference = api_rpath->rpath.frp_preference; fp->sw_if_index = htonl (api_rpath->rpath.frp_sw_if_index); copy_fib_next_hop (api_rpath, fp); fp++; @@ -377,10 +400,10 @@ api_ip6_fib_table_get_all (unix_shared_memory_queue_t * q, { vpe_api_main_t *am = &vpe_api_main; ip6_main_t *im6 = &ip6_main; - ip6_fib_t *fib = &fib_table->v6; fib_node_index_t *fib_entry_index; api_ip6_fib_show_ctx_t ctx = { - .fib_index = fib->index,.entries = NULL, + .fib_index = fib_table->ft_index, + .entries = NULL, }; fib_route_path_encode_t *api_rpaths; fib_prefix_t pfx; @@ -425,31 +448,36 @@ vl_api_ip6_fib_dump_t_handler (vl_api_ip6_fib_dump_t * mp) } static void -send_ip_mfib_details (vpe_api_main_t * am, - unix_shared_memory_queue_t * q, - u32 table_id, - mfib_prefix_t * pfx, - fib_route_path_encode_t * api_rpaths, u32 context) +send_ip_mfib_details (unix_shared_memory_queue_t * q, + 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; - fib_route_path_encode_t *api_rpath; + mfib_entry_t *mfib_entry; vl_api_fib_path_t *fp; + mfib_prefix_t pfx; int path_count; + mfib_entry = mfib_entry_get (mfei); + mfib_entry_get_prefix (mfei, &pfx); + mfib_entry_encode (mfei, &api_rpaths); + path_count = vec_len (api_rpaths); mp = vl_msg_api_alloc (sizeof (*mp) + path_count * sizeof (*fp)); if (!mp) return; memset (mp, 0, sizeof (*mp)); - mp->_vl_msg_id = ntohs (VL_API_IP_FIB_DETAILS); + 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->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; @@ -462,6 +490,7 @@ send_ip_mfib_details (vpe_api_main_t * am, copy_fib_next_hop (api_rpath, fp); fp++; } + vec_free (api_rpaths); vl_msg_api_send_shmem (q, (u8 *) & mp); } @@ -484,13 +513,10 @@ vl_api_ip_mfib_table_dump_walk (fib_node_index_t fei, void *arg) static void vl_api_ip_mfib_dump_t_handler (vl_api_ip_mfib_dump_t * mp) { - vpe_api_main_t *am = &vpe_api_main; unix_shared_memory_queue_t *q; ip4_main_t *im = &ip4_main; mfib_table_t *mfib_table; fib_node_index_t *mfeip; - mfib_prefix_t pfx; - fib_route_path_encode_t *api_rpaths = NULL; vl_api_ip_mfib_dump_ctc_t ctx = { .entries = NULL, }; @@ -511,21 +537,16 @@ vl_api_ip_mfib_dump_t_handler (vl_api_ip_mfib_dump_t * mp) vec_foreach (mfeip, ctx.entries) { - mfib_entry_get_prefix (*mfeip, &pfx); - mfib_entry_encode (*mfeip, &api_rpaths); - send_ip_mfib_details (am, q, + send_ip_mfib_details (q, mp->context, mfib_table->mft_table_id, - &pfx, api_rpaths, - mp->context); + *mfeip); } - vec_reset_length (api_rpaths); vec_reset_length (ctx.entries); })); /* *INDENT-ON* */ vec_free (ctx.entries); - vec_free (api_rpaths); } static void @@ -545,7 +566,7 @@ send_ip6_mfib_details (vpe_api_main_t * am, if (!mp) return; memset (mp, 0, sizeof (*mp)); - mp->_vl_msg_id = ntohs (VL_API_IP6_FIB_DETAILS); + mp->_vl_msg_id = ntohs (VL_API_IP6_MFIB_DETAILS); mp->context = context; mp->table_id = htonl (table_id); @@ -632,6 +653,64 @@ vl_api_ip6_mfib_dump_t_handler (vl_api_ip6_mfib_dump_t * mp) vec_free (api_rpaths); } +static void +vl_api_ip_punt_police_t_handler (vl_api_ip_punt_police_t * mp, + vlib_main_t * vm) +{ + vl_api_ip_punt_police_reply_t *rmp; + int rv = 0; + + if (mp->is_ip6) + ip6_punt_policer_add_del (mp->is_add, ntohl (mp->policer_index)); + else + ip4_punt_policer_add_del (mp->is_add, ntohl (mp->policer_index)); + + REPLY_MACRO (VL_API_IP_PUNT_POLICE_REPLY); +} + +static void +vl_api_ip_punt_redirect_t_handler (vl_api_ip_punt_redirect_t * mp, + vlib_main_t * vm) +{ + vl_api_ip_punt_redirect_reply_t *rmp; + int rv = 0; + + if (mp->is_add) + { + ip46_address_t nh; + + memset (&nh, 0, sizeof (nh)); + + if (mp->is_ip6) + { + memcpy (&nh.ip6, mp->nh, sizeof (nh.ip6)); + + ip6_punt_redirect_add (ntohl (mp->rx_sw_if_index), + ntohl (mp->tx_sw_if_index), &nh); + } + else + { + memcpy (&nh.ip4, mp->nh, sizeof (nh.ip4)); + + ip4_punt_redirect_add (ntohl (mp->rx_sw_if_index), + ntohl (mp->tx_sw_if_index), &nh); + } + } + else + { + if (mp->is_ip6) + { + ip6_punt_redirect_del (ntohl (mp->rx_sw_if_index)); + } + else + { + ip4_punt_redirect_del (ntohl (mp->rx_sw_if_index)); + } + } + + REPLY_MACRO (VL_API_IP_PUNT_REDIRECT_REPLY); +} + static void vl_api_ip_neighbor_add_del_t_handler (vl_api_ip_neighbor_add_del_t * mp, vlib_main_t * vm) @@ -655,7 +734,8 @@ vl_api_ip_neighbor_add_del_t_handler (vl_api_ip_neighbor_add_del_t * mp, rv = vnet_set_ip6_ethernet_neighbor (vm, ntohl (mp->sw_if_index), (ip6_address_t *) (mp->dst_address), - mp->mac_address, sizeof (mp->mac_address), mp->is_static); + mp->mac_address, sizeof (mp->mac_address), mp->is_static, + mp->is_no_adj_fib); else rv = vnet_unset_ip6_ethernet_neighbor (vm, ntohl (mp->sw_if_index), @@ -671,18 +751,74 @@ vl_api_ip_neighbor_add_del_t_handler (vl_api_ip_neighbor_add_del_t * mp, if (mp->is_add) rv = vnet_arp_set_ip4_over_ethernet (vnm, ntohl (mp->sw_if_index), - &a, mp->is_static); + &a, mp->is_static, + mp->is_no_adj_fib); else rv = vnet_arp_unset_ip4_over_ethernet (vnm, ntohl (mp->sw_if_index), &a); } - BAD_SW_IF_INDEX_LABEL; - stats_dsunlock (); + + BAD_SW_IF_INDEX_LABEL; REPLY_MACRO (VL_API_IP_NEIGHBOR_ADD_DEL_REPLY); } +void +ip_table_delete (fib_protocol_t fproto, u32 table_id, u8 is_api) +{ + u32 fib_index, mfib_index; + + /* + * ignore action on the default table - this is always present + * and cannot be added nor deleted from the API + */ + if (0 != table_id) + { + /* + * The API holds only one lock on the table. + * i.e. it can be added many times via the API but needs to be + * deleted only once. + * The FIB index for unicast and multicast is not necessarily the + * same, since internal VPP systesm (like LISP and SR) create + * their own unicast tables. + */ + fib_index = fib_table_find (fproto, table_id); + mfib_index = mfib_table_find (fproto, table_id); + + if (~0 != fib_index) + { + fib_table_unlock (fib_index, fproto, + (is_api ? FIB_SOURCE_API : FIB_SOURCE_CLI)); + } + if (~0 != mfib_index) + { + mfib_table_unlock (mfib_index, fproto, + (is_api ? MFIB_SOURCE_API : MFIB_SOURCE_CLI)); + } + } +} + +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); + int rv = 0; + + if (mp->is_add) + { + ip_table_create (fproto, table_id, 1, mp->name); + } + else + { + ip_table_delete (fproto, table_id, 1); + } + + REPLY_MACRO (VL_API_IP_TABLE_ADD_DEL_REPLY); +} + int add_del_route_t_handler (u8 is_multipath, u8 is_add, @@ -690,42 +826,73 @@ add_del_route_t_handler (u8 is_multipath, 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_l2_bridged, + u8 is_source_lookup, + u8 is_udp_encap, u32 fib_index, const fib_prefix_t * prefix, - u8 next_hop_proto_is_ip4, + 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, - u32 next_hop_weight, + u16 next_hop_weight, + u16 next_hop_preference, mpls_label_t next_hop_via_label, 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_is_ip4 ? - FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6), + .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; - if (MPLS_LABEL_INVALID != next_hop_via_label) + /* + * the special INVALID label meams 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 = FIB_PROTOCOL_MPLS; + path.frp_proto = DPO_PROTO_MPLS; path.frp_local_label = next_hop_via_label; + path.frp_eos = MPLS_NON_EOS; } + if (is_l2_bridged) + path.frp_proto = DPO_PROTO_ETHERNET; 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; + } path.frp_flags = path_flags; @@ -739,8 +906,7 @@ add_del_route_t_handler (u8 is_multipath, if (is_add) fib_table_entry_path_add2 (fib_index, prefix, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, paths); + FIB_SOURCE_API, entry_flags, paths); else fib_table_entry_path_remove2 (fib_index, prefix, FIB_SOURCE_API, paths); @@ -811,8 +977,7 @@ add_del_route_t_handler (u8 is_multipath, { vec_add1 (paths, path); fib_table_entry_update (fib_index, - prefix, - FIB_SOURCE_API, FIB_ENTRY_FLAG_NONE, paths); + prefix, FIB_SOURCE_API, entry_flags, paths); vec_free (paths); } else @@ -829,20 +994,23 @@ int add_del_route_check (fib_protocol_t table_proto, u32 table_id, u32 next_hop_sw_if_index, - fib_protocol_t next_hop_table_proto, + dpo_proto_t next_hop_table_proto, u32 next_hop_table_id, - u8 create_missing_tables, - u32 * fib_index, u32 * next_hop_fib_index) + u8 is_rpf_id, u32 * fib_index, u32 * next_hop_fib_index) { vnet_main_t *vnm = vnet_get_main (); + /* Temporaray whilst I do the CSIT dance */ + u8 create_missing_tables = 1; + *fib_index = fib_table_find (table_proto, ntohl (table_id)); if (~0 == *fib_index) { if (create_missing_tables) { *fib_index = fib_table_find_or_create_and_lock (table_proto, - ntohl (table_id)); + ntohl (table_id), + FIB_SOURCE_API); } else { @@ -851,7 +1019,7 @@ add_del_route_check (fib_protocol_t table_proto, } } - if (~0 != ntohl (next_hop_sw_if_index)) + 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))) @@ -861,16 +1029,36 @@ add_del_route_check (fib_protocol_t table_proto, } else { - *next_hop_fib_index = fib_table_find (next_hop_table_proto, - ntohl (next_hop_table_id)); + 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) { if (create_missing_tables) { - *next_hop_fib_index = - fib_table_find_or_create_and_lock (next_hop_table_proto, - ntohl (next_hop_table_id)); + if (is_rpf_id) + *next_hop_fib_index = + mfib_table_find_or_create_and_lock (fib_nh_proto, + ntohl + (next_hop_table_id), + MFIB_SOURCE_API); + else + *next_hop_fib_index = + fib_table_find_or_create_and_lock (fib_nh_proto, + ntohl + (next_hop_table_id), + FIB_SOURCE_API); } else { @@ -893,10 +1081,9 @@ ip4_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp) rv = add_del_route_check (FIB_PROTOCOL_IP4, mp->table_id, mp->next_hop_sw_if_index, - FIB_PROTOCOL_IP4, + DPO_PROTO_IP4, mp->next_hop_table_id, - mp->create_vrf_if_needed, - &fib_index, &next_hop_fib_index); + 0, &fib_index, &next_hop_fib_index); if (0 != rv) return (rv); @@ -928,16 +1115,21 @@ ip4_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp) mp->is_drop, mp->is_unreach, mp->is_prohibit, - mp->is_local, + mp->is_local, 0, mp->is_classify, mp->classify_table_index, mp->is_resolve_host, - mp->is_resolve_attached, - fib_index, &pfx, 1, + mp->is_resolve_attached, 0, 0, + mp->is_l2_bridged, + 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)); } @@ -952,10 +1144,9 @@ ip6_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp) rv = add_del_route_check (FIB_PROTOCOL_IP6, mp->table_id, mp->next_hop_sw_if_index, - FIB_PROTOCOL_IP6, + DPO_PROTO_IP6, mp->next_hop_table_id, - mp->create_vrf_if_needed, - &fib_index, &next_hop_fib_index); + 0, &fib_index, &next_hop_fib_index); if (0 != rv) return (rv); @@ -987,15 +1178,20 @@ ip6_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp) mp->is_drop, mp->is_unreach, mp->is_prohibit, - mp->is_local, + mp->is_local, 0, mp->is_classify, mp->classify_table_index, mp->is_resolve_host, - mp->is_resolve_attached, - fib_index, &pfx, 0, - &nh, ntohl (mp->next_hop_sw_if_index), + mp->is_resolve_attached, 0, 0, + mp->is_l2_bridged, + 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)); } @@ -1019,27 +1215,58 @@ vl_api_ip_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp) REPLY_MACRO (VL_API_IP_ADD_DEL_ROUTE_REPLY); } +void +ip_table_create (fib_protocol_t fproto, + u32 table_id, u8 is_api, const u8 * name) +{ + u32 fib_index, mfib_index; + + /* + * ignore action on the default table - this is always present + * and cannot be added nor deleted from the API + */ + if (0 != table_id) + { + /* + * The API holds only one lock on the table. + * i.e. it can be added many times via the API but needs to be + * deleted only once. + * The FIB index for unicast and multicast is not necessarily the + * same, since internal VPP systesm (like LISP and SR) create + * their own unicast tables. + */ + fib_index = fib_table_find (fproto, table_id); + mfib_index = mfib_table_find (fproto, table_id); + + if (~0 == fib_index) + { + fib_table_find_or_create_and_lock_w_name (fproto, table_id, + (is_api ? + FIB_SOURCE_API : + FIB_SOURCE_CLI), name); + } + if (~0 == mfib_index) + { + mfib_table_find_or_create_and_lock_w_name (fproto, table_id, + (is_api ? + MFIB_SOURCE_API : + MFIB_SOURCE_CLI), name); + } + } +} + static int add_del_mroute_check (fib_protocol_t table_proto, u32 table_id, - u32 next_hop_sw_if_index, - u8 is_local, u8 create_missing_tables, u32 * fib_index) + 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) { - if (create_missing_tables) - { - *fib_index = mfib_table_find_or_create_and_lock (table_proto, - ntohl (table_id)); - } - else - { - /* No such VRF, and we weren't asked to create one */ - return VNET_API_ERROR_NO_SUCH_FIB; - } + /* No such table */ + return VNET_API_ERROR_NO_SUCH_FIB; } if (~0 != ntohl (next_hop_sw_if_index)) @@ -1059,39 +1286,45 @@ mroute_add_del_handler (u8 is_add, u8 is_local, u32 fib_index, const mfib_prefix_t * prefix, + dpo_proto_t nh_proto, u32 entry_flags, - u32 next_hop_sw_if_index, u32 itf_flags) + fib_rpf_id_t rpf_id, + u32 next_hop_sw_if_index, u32 itf_flags, u32 bier_imp) { stats_dslock_with_hint (1 /* release hint */ , 2 /* tag */ ); fib_route_path_t path = { .frp_sw_if_index = next_hop_sw_if_index, - .frp_proto = prefix->fp_proto, + .frp_proto = nh_proto, }; if (is_local) path.frp_flags |= FIB_ROUTE_PATH_LOCAL; - - if (!is_local && ~0 == next_hop_sw_if_index) + 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) { mfib_table_entry_update (fib_index, prefix, - MFIB_SOURCE_API, entry_flags); + MFIB_SOURCE_API, rpf_id, entry_flags); + goto done; + } + + if (is_add) + { + mfib_table_entry_path_update (fib_index, prefix, + MFIB_SOURCE_API, &path, itf_flags); } else { - if (is_add) - { - 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); - } + mfib_table_entry_path_remove (fib_index, prefix, + MFIB_SOURCE_API, &path); } +done: stats_dsunlock (); return (0); } @@ -1100,15 +1333,16 @@ static int api_mroute_add_del_t_handler (vl_api_ip_mroute_add_del_t * mp) { fib_protocol_t fproto; + dpo_proto_t nh_proto; u32 fib_index; int rv; + 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, - mp->create_vrf_if_needed, &fib_index); + mp->is_local, &fib_index); if (0 != rv) return (rv); @@ -1136,9 +1370,12 @@ api_mroute_add_del_t_handler (vl_api_ip_mroute_add_del_t * mp) return (mroute_add_del_handler (mp->is_add, mp->is_local, fib_index, &pfx, + nh_proto, ntohl (mp->entry_flags), + ntohl (mp->rpf_id), ntohl (mp->next_hop_sw_if_index), - ntohl (mp->itf_flags))); + ntohl (mp->itf_flags), + ntohl (mp->bier_imp))); } void @@ -1301,9 +1538,17 @@ static void set_ip6_flow_hash (vl_api_set_ip_flow_hash_t * mp) { vl_api_set_ip_flow_hash_reply_t *rmp; - int rv = VNET_API_ERROR_UNIMPLEMENTED; + int rv; + u32 table_id; + flow_hash_config_t flow_hash_config = 0; + + table_id = ntohl (mp->vrf_id); - clib_warning ("unimplemented..."); +#define _(a,b) if (mp->a) flow_hash_config |= b; + foreach_flow_hash_bit; +#undef _ + + rv = vnet_set_ip6_flow_hash (table_id, flow_hash_config); REPLY_MACRO (VL_API_SET_IP_FLOW_HASH_REPLY); } @@ -1628,6 +1873,29 @@ vl_api_mfib_signal_dump_t_handler (vl_api_mfib_signal_dump_t * mp) ; } +static void + vl_api_ip_container_proxy_add_del_t_handler + (vl_api_ip_container_proxy_add_del_t * mp) +{ + vl_api_ip_container_proxy_add_del_reply_t *rmp; + vnet_ip_container_proxy_args_t args; + int rv = 0; + clib_error_t *error; + + memset (&args, 0, sizeof (args)); + ip_set (&args.prefix.fp_addr, mp->ip, mp->is_ip4); + args.prefix.fp_len = mp->plen ? mp->plen : (mp->is_ip4 ? 32 : 128); + args.sw_if_index = clib_net_to_host_u32 (mp->sw_if_index); + args.is_add = mp->is_add; + if ((error = vnet_ip_container_proxy_add_del (&args))) + { + rv = clib_error_get_code (error); + clib_error_report (error); + } + + REPLY_MACRO (VL_API_IP_CONTAINER_PROXY_ADD_DEL_REPLY); +} + #define vl_msg_name_crc_list #include #undef vl_msg_name_crc_list