X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Fip%2Fip_api.c;h=0fdb167312ee587a0339bdc880ac211f60647d31;hb=d792d9c01e60656cbfe1b0f1fd6a9b125f5dab0c;hp=4cbf75a3883f845013f45c84d945bf73f1d9c756;hpb=a0a908f1dfb679c384ab34ee3c1a2a63ba2448df;p=vpp.git diff --git a/src/vnet/ip/ip_api.c b/src/vnet/ip/ip_api.c index 4cbf75a3883..0fdb167312e 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,7 +79,8 @@ _(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); @@ -156,9 +160,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 +183,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 +200,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)); @@ -294,9 +301,7 @@ vl_api_ip_fib_dump_t_handler (vl_api_ip_fib_dump_t * mp) 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); } @@ -360,7 +365,7 @@ send_ip6_fib_details (vpe_api_main_t * am, } fp->weight = api_rpath->rpath.frp_weight; fp->preference = api_rpath->rpath.frp_preference; - fp->sw_if_index = api_rpath->rpath.frp_sw_if_index; + fp->sw_if_index = htonl (api_rpath->rpath.frp_sw_if_index); copy_fib_next_hop (api_rpath, fp); fp++; } @@ -459,7 +464,7 @@ send_ip_mfib_details (unix_shared_memory_queue_t * q, 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; @@ -558,7 +563,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); @@ -645,6 +650,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) @@ -692,12 +755,67 @@ vl_api_ip_neighbor_add_del_t_handler (vl_api_ip_neighbor_add_del_t * mp, 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, @@ -712,10 +830,14 @@ add_del_route_t_handler (u8 is_multipath, 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, u16 next_hop_weight, @@ -726,8 +848,7 @@ add_del_route_t_handler (u8 is_multipath, 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, @@ -738,12 +859,20 @@ add_del_route_t_handler (u8 is_multipath, 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) @@ -752,8 +881,15 @@ add_del_route_t_handler (u8 is_multipath, 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; @@ -855,20 +991,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, 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 { @@ -887,11 +1026,18 @@ add_del_route_check (fib_protocol_t table_proto, } 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 (next_hop_table_proto, + *next_hop_fib_index = mfib_table_find (fib_nh_proto, ntohl (next_hop_table_id)); else - *next_hop_fib_index = fib_table_find (next_hop_table_proto, + *next_hop_fib_index = fib_table_find (fib_nh_proto, ntohl (next_hop_table_id)); if (~0 == *next_hop_fib_index) @@ -900,14 +1046,16 @@ add_del_route_check (fib_protocol_t table_proto, { if (is_rpf_id) *next_hop_fib_index = - mfib_table_find_or_create_and_lock (next_hop_table_proto, + mfib_table_find_or_create_and_lock (fib_nh_proto, ntohl - (next_hop_table_id)); + (next_hop_table_id), + MFIB_SOURCE_API); else *next_hop_fib_index = - fib_table_find_or_create_and_lock (next_hop_table_proto, + fib_table_find_or_create_and_lock (fib_nh_proto, ntohl - (next_hop_table_id)); + (next_hop_table_id), + FIB_SOURCE_API); } else { @@ -930,10 +1078,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, 0, - &fib_index, &next_hop_fib_index); + 0, &fib_index, &next_hop_fib_index); if (0 != rv) return (rv); @@ -970,8 +1117,12 @@ ip4_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp) mp->classify_table_index, mp->is_resolve_host, mp->is_resolve_attached, 0, 0, - fib_index, &pfx, 1, + 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, @@ -990,10 +1141,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, 0, - &fib_index, &next_hop_fib_index); + 0, &fib_index, &next_hop_fib_index); if (0 != rv) return (rv); @@ -1030,8 +1180,12 @@ ip6_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp) mp->classify_table_index, mp->is_resolve_host, mp->is_resolve_attached, 0, 0, - fib_index, &pfx, 0, - &nh, ntohl (mp->next_hop_sw_if_index), + 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, @@ -1058,27 +1212,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)) @@ -1098,40 +1283,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, fib_rpf_id_t rpf_id, - u32 next_hop_sw_if_index, u32 itf_flags) + 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, 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); } @@ -1140,15 +1330,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); @@ -1176,10 +1367,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 @@ -1677,6 +1870,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