X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=vpp%2Fvpp-api%2Fapi.c;h=1ecd148186b75052ed02f2b55f62076a04ae09b4;hb=f6e3dc4778ef910d4ae6114783bd8f50887e6d0d;hp=1de1b55f722db6a5a5179125b03a21dc4b78ad30;hpb=251aec436b9e3be15f92a464fa4559396b115b2a;p=vpp.git diff --git a/vpp/vpp-api/api.c b/vpp/vpp-api/api.c index 1de1b55f722..1ecd148186b 100644 --- a/vpp/vpp-api/api.c +++ b/vpp/vpp-api/api.c @@ -2,7 +2,7 @@ *------------------------------------------------------------------ * api.c - message handler registration * - * Copyright (c) 2010 Cisco and/or its affiliates. + * Copyright (c) 2010-2016 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: @@ -51,9 +51,10 @@ #include #include #include +#include #include #include -#include +#include #include #include #if IPV6SR > 0 @@ -67,12 +68,15 @@ #include #include #include +#include #include #include #include #include #include #include +#include +#include #include #include #include @@ -83,6 +87,8 @@ #include #include #include +#include +#include #undef BIHASH_TYPE #undef __included_bihash_template_h__ @@ -92,9 +98,7 @@ #include #include #endif /* IPSEC */ -#if DPDK > 0 #include -#endif #include #include @@ -106,6 +110,15 @@ #include #include #include +#include + +#include +#include +#include +#include +#include +#include +#include #define f64_endian(a) #define f64_print(a,b) @@ -156,6 +169,52 @@ do { \ vl_msg_api_send_shmem (q, (u8 *)&rmp); \ } while(0); +#define REPLY_MACRO3(t, n, body) \ +do { \ + unix_shared_memory_queue_t * q; \ + rv = vl_msg_api_pd_handler (mp, rv); \ + q = vl_api_client_index_to_input_queue (mp->client_index); \ + if (!q) \ + return; \ + \ + rmp = vl_msg_api_alloc (sizeof (*rmp) + n); \ + rmp->_vl_msg_id = ntohs((t)); \ + rmp->context = mp->context; \ + rmp->retval = ntohl(rv); \ + do {body;} while (0); \ + vl_msg_api_send_shmem (q, (u8 *)&rmp); \ +} while(0); + +#define REPLY_MACRO4(t, n, body) \ +do { \ + unix_shared_memory_queue_t * q; \ + u8 is_error = 0; \ + rv = vl_msg_api_pd_handler (mp, rv); \ + q = vl_api_client_index_to_input_queue (mp->client_index); \ + if (!q) \ + return; \ + \ + rmp = vl_msg_api_alloc_or_null (sizeof (*rmp) + n); \ + if (!rmp) \ + { \ + /* if there isn't enough memory, try to allocate */ \ + /* some at least for returning an error */ \ + rmp = vl_msg_api_alloc (sizeof (*rmp)); \ + if (!rmp) \ + return; \ + \ + memset (rmp, 0, sizeof (*rmp)); \ + rv = VNET_API_ERROR_TABLE_TOO_BIG; \ + is_error = 1; \ + } \ + rmp->_vl_msg_id = ntohs((t)); \ + rmp->context = mp->context; \ + rmp->retval = ntohl(rv); \ + if (!is_error) \ + do {body;} while (0); \ + vl_msg_api_send_shmem (q, (u8 *)&rmp); \ +} while(0); + #if (1 || CLIB_DEBUG > 0) /* "trust, but verify" */ #define VALIDATE_SW_IF_INDEX(mp) \ @@ -225,12 +284,18 @@ _(SW_INTERFACE_DUMP, sw_interface_dump) \ _(SW_INTERFACE_DETAILS, sw_interface_details) \ _(SW_INTERFACE_SET_FLAGS, sw_interface_set_flags) \ _(IP_ADD_DEL_ROUTE, ip_add_del_route) \ +_(MPLS_ROUTE_ADD_DEL, mpls_route_add_del) \ +_(MPLS_IP_BIND_UNBIND, mpls_ip_bind_unbind) \ _(IS_ADDRESS_REACHABLE, is_address_reachable) \ _(SW_INTERFACE_ADD_DEL_ADDRESS, sw_interface_add_del_address) \ _(SW_INTERFACE_SET_TABLE, sw_interface_set_table) \ +_(SW_INTERFACE_SET_MPLS_ENABLE, sw_interface_set_mpls_enable) \ _(SW_INTERFACE_SET_VPATH, sw_interface_set_vpath) \ _(SW_INTERFACE_SET_L2_XCONNECT, sw_interface_set_l2_xconnect) \ _(SW_INTERFACE_SET_L2_BRIDGE, sw_interface_set_l2_bridge) \ +_(SW_INTERFACE_SET_DPDK_HQOS_PIPE, sw_interface_set_dpdk_hqos_pipe) \ +_(SW_INTERFACE_SET_DPDK_HQOS_SUBPORT, sw_interface_set_dpdk_hqos_subport) \ +_(SW_INTERFACE_SET_DPDK_HQOS_TCTBL, sw_interface_set_dpdk_hqos_tctbl) \ _(BRIDGE_DOMAIN_ADD_DEL, bridge_domain_add_del) \ _(BRIDGE_DOMAIN_DUMP, bridge_domain_dump) \ _(BRIDGE_DOMAIN_DETAILS, bridge_domain_details) \ @@ -244,11 +309,9 @@ _(TAP_DELETE, tap_delete) \ _(SW_INTERFACE_TAP_DUMP, sw_interface_tap_dump) \ _(CREATE_VLAN_SUBIF, create_vlan_subif) \ _(CREATE_SUBIF, create_subif) \ -_(MPLS_GRE_ADD_DEL_TUNNEL, mpls_gre_add_del_tunnel) \ _(MPLS_ETHERNET_ADD_DEL_TUNNEL, mpls_ethernet_add_del_tunnel) \ _(MPLS_ETHERNET_ADD_DEL_TUNNEL_2, mpls_ethernet_add_del_tunnel_2) \ _(MPLS_ADD_DEL_ENCAP, mpls_add_del_encap) \ -_(MPLS_ADD_DEL_DECAP, mpls_add_del_decap) \ _(PROXY_ARP_ADD_DEL, proxy_arp_add_del) \ _(PROXY_ARP_INTFC_ENABLE_DISABLE, proxy_arp_intfc_enable_disable) \ _(IP_NEIGHBOR_ADD_DEL, ip_neighbor_add_del) \ @@ -267,8 +330,8 @@ _(SW_INTERFACE_IP6_SET_LINK_LOCAL_ADDRESS, \ _(SW_INTERFACE_SET_UNNUMBERED, sw_interface_set_unnumbered) \ _(CREATE_LOOPBACK, create_loopback) \ _(CONTROL_PING, control_ping) \ -_(NOPRINT_CONTROL_PING, noprint_control_ping) \ _(CLI_REQUEST, cli_request) \ +_(CLI_INBAND, cli_inband) \ _(SET_ARP_NEIGHBOR_LIMIT, set_arp_neighbor_limit) \ _(L2_PATCH_ADD_DEL, l2_patch_add_del) \ _(CLASSIFY_ADD_DEL_TABLE, classify_add_del_table) \ @@ -303,6 +366,7 @@ _(VXLAN_GPE_ADD_DEL_TUNNEL, vxlan_gpe_add_del_tunnel) \ _(VXLAN_GPE_TUNNEL_DUMP, vxlan_gpe_tunnel_dump) \ _(INTERFACE_NAME_RENUMBER, interface_name_renumber) \ _(WANT_IP4_ARP_EVENTS, want_ip4_arp_events) \ +_(WANT_IP6_ND_EVENTS, want_ip6_nd_events) \ _(INPUT_ACL_SET_INTERFACE, input_acl_set_interface) \ _(IPSEC_SPD_ADD_DEL, ipsec_spd_add_del) \ _(IPSEC_INTERFACE_ADD_DEL_SPD, ipsec_interface_add_del_spd) \ @@ -326,9 +390,8 @@ _(COP_INTERFACE_ENABLE_DISABLE, cop_interface_enable_disable) \ _(COP_WHITELIST_ENABLE_DISABLE, cop_whitelist_enable_disable) \ _(GET_NODE_GRAPH, get_node_graph) \ _(SW_INTERFACE_CLEAR_STATS, sw_interface_clear_stats) \ -_(TRACE_PROFILE_ADD, trace_profile_add) \ -_(TRACE_PROFILE_APPLY, trace_profile_apply) \ -_(TRACE_PROFILE_DEL, trace_profile_del) \ +_(IOAM_ENABLE, ioam_enable) \ +_(IOAM_DISABLE, ioam_disable) \ _(LISP_ADD_DEL_LOCATOR_SET, lisp_add_del_locator_set) \ _(LISP_ADD_DEL_LOCATOR, lisp_add_del_locator) \ _(LISP_ADD_DEL_LOCAL_EID, lisp_add_del_local_eid) \ @@ -340,6 +403,7 @@ _(LISP_GPE_ADD_DEL_IFACE, lisp_gpe_add_del_iface) \ _(LISP_ADD_DEL_REMOTE_MAPPING, lisp_add_del_remote_mapping) \ _(LISP_ADD_DEL_ADJACENCY, lisp_add_del_adjacency) \ _(LISP_PITR_SET_LOCATOR_SET, lisp_pitr_set_locator_set) \ +_(LISP_MAP_REQUEST_MODE, lisp_map_request_mode) \ _(LISP_EID_TABLE_ADD_DEL_MAP, lisp_eid_table_add_del_map) \ _(LISP_LOCATOR_SET_DUMP, lisp_locator_set_dump) \ _(LISP_LOCATOR_DUMP, lisp_locator_dump) \ @@ -347,11 +411,14 @@ _(LISP_EID_TABLE_DUMP, lisp_eid_table_dump) \ _(LISP_GPE_TUNNEL_DUMP, lisp_gpe_tunnel_dump) \ _(LISP_MAP_RESOLVER_DUMP, lisp_map_resolver_dump) \ _(LISP_EID_TABLE_MAP_DUMP, lisp_eid_table_map_dump) \ +_(LISP_EID_TABLE_VNI_DUMP, lisp_eid_table_vni_dump) \ +_(LISP_ADJACENCIES_GET, lisp_adjacencies_get) \ _(SHOW_LISP_STATUS, show_lisp_status) \ _(LISP_ADD_DEL_MAP_REQUEST_ITR_RLOCS, \ lisp_add_del_map_request_itr_rlocs) \ _(LISP_GET_MAP_REQUEST_ITR_RLOCS, lisp_get_map_request_itr_rlocs) \ _(SHOW_LISP_PITR, show_lisp_pitr) \ +_(SHOW_LISP_MAP_REQUEST_MODE, show_lisp_map_request_mode) \ _(SR_MULTICAST_MAP_ADD_DEL, sr_multicast_map_add_del) \ _(AF_PACKET_CREATE, af_packet_create) \ _(AF_PACKET_DELETE, af_packet_delete) \ @@ -361,21 +428,25 @@ _(POLICER_CLASSIFY_SET_INTERFACE, policer_classify_set_interface) \ _(POLICER_CLASSIFY_DUMP, policer_classify_dump) \ _(NETMAP_CREATE, netmap_create) \ _(NETMAP_DELETE, netmap_delete) \ -_(MPLS_GRE_TUNNEL_DUMP, mpls_gre_tunnel_dump) \ -_(MPLS_GRE_TUNNEL_DETAILS, mpls_gre_tunnel_details) \ _(MPLS_ETH_TUNNEL_DUMP, mpls_eth_tunnel_dump) \ _(MPLS_ETH_TUNNEL_DETAILS, mpls_eth_tunnel_details) \ _(MPLS_FIB_ENCAP_DUMP, mpls_fib_encap_dump) \ _(MPLS_FIB_ENCAP_DETAILS, mpls_fib_encap_details) \ -_(MPLS_FIB_DECAP_DUMP, mpls_fib_decap_dump) \ -_(MPLS_FIB_DECAP_DETAILS, mpls_fib_decap_details) \ +_(MPLS_FIB_DUMP, mpls_fib_dump) \ +_(MPLS_FIB_DETAILS, mpls_fib_details) \ _(CLASSIFY_TABLE_IDS,classify_table_ids) \ _(CLASSIFY_TABLE_BY_INTERFACE, classify_table_by_interface) \ _(CLASSIFY_TABLE_INFO,classify_table_info) \ _(CLASSIFY_SESSION_DUMP,classify_session_dump) \ _(CLASSIFY_SESSION_DETAILS,classify_session_details) \ -_(IPFIX_ENABLE,ipfix_enable) \ -_(IPFIX_DUMP,ipfix_dump) \ +_(SET_IPFIX_EXPORTER, set_ipfix_exporter) \ +_(IPFIX_EXPORTER_DUMP, ipfix_exporter_dump) \ +_(SET_IPFIX_CLASSIFY_STREAM, set_ipfix_classify_stream) \ +_(IPFIX_CLASSIFY_STREAM_DUMP, ipfix_classify_stream_dump) \ +_(IPFIX_CLASSIFY_TABLE_ADD_DEL, ipfix_classify_table_add_del) \ +_(IPFIX_CLASSIFY_TABLE_DUMP, ipfix_classify_table_dump) \ +_(SW_INTERFACE_SPAN_ENABLE_DISABLE, sw_interface_span_enable_disable) \ +_(SW_INTERFACE_SPAN_DUMP, sw_interface_span_dump) \ _(GET_NEXT_INDEX, get_next_index) \ _(PG_CREATE_INTERFACE, pg_create_interface) \ _(PG_CAPTURE, pg_capture) \ @@ -385,7 +456,17 @@ _(IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL, \ _(IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL, \ ip_source_and_port_range_check_interface_add_del) \ _(IPSEC_GRE_ADD_DEL_TUNNEL, ipsec_gre_add_del_tunnel) \ -_(IPSEC_GRE_TUNNEL_DUMP, ipsec_gre_tunnel_dump) +_(IPSEC_GRE_TUNNEL_DUMP, ipsec_gre_tunnel_dump) \ +_(DELETE_SUBIF, delete_subif) \ +_(L2_INTERFACE_PBB_TAG_REWRITE, l2_interface_pbb_tag_rewrite) \ +_(PUNT, punt) \ +_(FLOW_CLASSIFY_SET_INTERFACE, flow_classify_set_interface) \ +_(FLOW_CLASSIFY_DUMP, flow_classify_dump) \ +_(IPSEC_SPD_DUMP, ipsec_spd_dump) \ +_(IP_FIB_DUMP, ip_fib_dump) \ +_(IP_FIB_DETAILS, ip_fib_details) \ +_(IP6_FIB_DUMP, ip6_fib_dump) \ +_(IP6_FIB_DETAILS, ip6_fib_details) #define QUOTE_(x) #x #define QUOTE(x) QUOTE_(x) @@ -425,12 +506,15 @@ typedef struct /* notifications happen really early in the game */ u8 link_state_process_up; - /* ip4 pending route adds */ + /* ip4 and ip6 pending route adds */ pending_route_t *pending_routes; /* ip4 arp event registration pool */ vl_api_ip4_arp_event_t *arp_events; + /* ip6 nd event registration pool */ + vl_api_ip6_nd_event_t *nd_events; + /* convenience */ vlib_main_t *vlib_main; vnet_main_t *vnet_main; @@ -447,6 +531,7 @@ static void send_sw_interface_flags_deleted (vpe_api_main_t * am, u32 sw_if_index); static int arp_change_delete_callback (u32 pool_index, u8 * notused); +static int nd_change_delete_callback (u32 pool_index, u8 * notused); /* Clean up all registrations belonging to the indicated client */ @@ -629,17 +714,25 @@ reply: \ REPLY_MACRO (VL_API_WANT_##UCA##_REPLY); \ } +/* *INDENT-OFF* */ pub_sub_handler (interface_events, INTERFACE_EVENTS) pub_sub_handler (oam_events, OAM_EVENTS) +/* *INDENT-ON* */ + #define RESOLUTION_EVENT 1 #define RESOLUTION_PENDING_EVENT 2 #define IP4_ARP_EVENT 3 - static int ip4_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp); - static int ip6_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp); - static int mpls_ethernet_add_del_tunnel_2_t_handler - (vl_api_mpls_ethernet_add_del_tunnel_2_t * mp); +#define IP6_ND_EVENT 4 + +static int ip4_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp); - void handle_ip4_arp_event (u32 pool_index) +static int ip6_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp); + +static int mpls_ethernet_add_del_tunnel_2_t_handler + (vl_api_mpls_ethernet_add_del_tunnel_2_t * mp); + +void +handle_ip4_arp_event (u32 pool_index) { vpe_api_main_t *vam = &vpe_api_main; vnet_main_t *vnm = vam->vnet_main; @@ -687,6 +780,55 @@ pub_sub_handler (oam_events, OAM_EVENTS) } } +void +handle_ip6_nd_event (u32 pool_index) +{ + vpe_api_main_t *vam = &vpe_api_main; + vnet_main_t *vnm = vam->vnet_main; + vlib_main_t *vm = vam->vlib_main; + vl_api_ip6_nd_event_t *event; + vl_api_ip6_nd_event_t *mp; + unix_shared_memory_queue_t *q; + + /* Client can cancel, die, etc. */ + if (pool_is_free_index (vam->nd_events, pool_index)) + return; + + event = pool_elt_at_index (vam->nd_events, pool_index); + + q = vl_api_client_index_to_input_queue (event->client_index); + if (!q) + { + (void) vnet_add_del_ip6_nd_change_event + (vnm, nd_change_delete_callback, + event->pid, &event->address, + vpe_resolver_process_node.index, IP6_ND_EVENT, + ~0 /* pool index, notused */ , 0 /* is_add */ ); + return; + } + + if (q->cursize < q->maxsize) + { + mp = vl_msg_api_alloc (sizeof (*mp)); + clib_memcpy (mp, event, sizeof (*mp)); + vl_msg_api_send_shmem (q, (u8 *) & mp); + } + else + { + static f64 last_time; + /* + * Throttle syslog msgs. + * It's pretty tempting to just revoke the registration... + */ + if (vlib_time_now (vm) > last_time + 10.0) + { + clib_warning ("ip6 nd event for %U to pid %d: queue stuffed!", + format_ip6_address, &event->address, event->pid); + last_time = vlib_time_now (vm); + } + } +} + static uword resolver_process (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f) @@ -774,6 +916,11 @@ resolver_process (vlib_main_t * vm, handle_ip4_arp_event (event_data[i]); break; + case IP6_ND_EVENT: + for (i = 0; i < vec_len (event_data); i++) + handle_ip6_nd_event (event_data[i]); + break; + case ~0: /* timeout, retry pending resolutions */ /* *INDENT-OFF* */ pool_foreach (pr, vam->pending_routes, @@ -891,251 +1038,174 @@ VLIB_REGISTER_NODE (vpe_resolver_process_node,static) = { /* *INDENT-ON* */ static int -ip4_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp) +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_classify, + u32 classify_table_index, + u8 is_resolve_host, + u8 is_resolve_attached, + u32 fib_index, + const fib_prefix_t * prefix, + u8 next_hop_proto_is_ip4, + const ip46_address_t * next_hop, + u32 next_hop_sw_if_index, + u8 next_hop_fib_index, + u32 next_hop_weight, u32 next_hop_out_label) { - ip4_main_t *im = &ip4_main; - ip_lookup_main_t *lm = &im->lookup_main; vnet_classify_main_t *cm = &vnet_classify_main; stats_main_t *sm = &stats_main; - ip4_add_del_route_args_t a; - ip4_address_t next_hop_address; - u32 fib_index; - vpe_api_main_t *vam = &vpe_api_main; - vnet_main_t *vnm = vam->vnet_main; - vlib_main_t *vm = vlib_get_main (); - pending_route_t *pr; - vl_api_ip_add_del_route_t *adr; - uword *p; - clib_error_t *e; - u32 ai; - ip_adjacency_t *adj; - - p = hash_get (im->fib_index_by_table_id, ntohl (mp->vrf_id)); - if (!p) - { - if (mp->create_vrf_if_needed) - { - ip4_fib_t *f; - f = find_ip4_fib_by_table_index_or_id (im, ntohl (mp->vrf_id), - 0 /* flags */ ); - fib_index = f->index; - } - else - { - /* No such VRF, and we weren't asked to create one */ - return VNET_API_ERROR_NO_SUCH_FIB; - } - } - else - { - fib_index = p[0]; - } - - if (~0 != mp->next_hop_sw_if_index && - pool_is_free_index (vnm->interface_main.sw_interfaces, - ntohl (mp->next_hop_sw_if_index))) - return VNET_API_ERROR_NO_MATCHING_INTERFACE; - - clib_memcpy (next_hop_address.data, mp->next_hop_address, - sizeof (next_hop_address.data)); - - /* Arp for the next_hop if necessary */ - if (mp->is_add && mp->resolve_if_needed && ~0 != mp->next_hop_sw_if_index) - { - u32 lookup_result; - ip_adjacency_t *adj; - - lookup_result = ip4_fib_lookup_with_table - (im, fib_index, &next_hop_address, 1 /* disable default route */ ); - - adj = ip_get_adjacency (lm, lookup_result); - - if (adj->lookup_next_index == IP_LOOKUP_NEXT_ARP) - { - pool_get (vam->pending_routes, pr); - pr->resolve_type = RESOLVE_IP4_ADD_DEL_ROUTE; - adr = &pr->r; - clib_memcpy (adr, mp, sizeof (*adr)); - /* recursion block, "just in case" */ - adr->resolve_if_needed = 0; - adr->resolve_attempts = ntohl (mp->resolve_attempts); - vnet_register_ip4_arp_resolution_event - (vnm, &next_hop_address, vpe_resolver_process_node.index, - RESOLUTION_EVENT, pr - vam->pending_routes); - - vlib_process_signal_event - (vm, vpe_resolver_process_node.index, - RESOLUTION_PENDING_EVENT, 0 /* data */ ); - - /* The interface may be down, etc. */ - e = ip4_probe_neighbor - (vm, (ip4_address_t *) & (mp->next_hop_address), - ntohl (mp->next_hop_sw_if_index)); - - if (e) - clib_error_report (e); - - return VNET_API_ERROR_IN_PROGRESS; - } - } - if (mp->is_multipath) + if (is_multipath) { - u32 flags; + fib_route_path_flags_t path_flags = FIB_ROUTE_PATH_FLAG_NONE; dslock (sm, 1 /* release hint */ , 10 /* tag */ ); - if (mp->is_add) - flags = IP4_ROUTE_FLAG_ADD; + 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_add) + fib_table_entry_path_add (fib_index, + prefix, + FIB_SOURCE_API, + FIB_ENTRY_FLAG_NONE, + (next_hop_proto_is_ip4 ? + FIB_PROTOCOL_IP4 : + FIB_PROTOCOL_IP6), + next_hop, + next_hop_sw_if_index, + next_hop_fib_index, + next_hop_weight, + next_hop_out_label, path_flags); else - flags = IP4_ROUTE_FLAG_DEL; - - if (mp->not_last) - flags |= IP4_ROUTE_FLAG_NOT_LAST_IN_GROUP; - - ip4_add_del_route_next_hop (im, flags, - (ip4_address_t *) mp->dst_address, - (u32) mp->dst_address_length, - (ip4_address_t *) mp->next_hop_address, - ntohl (mp->next_hop_sw_if_index), - (u32) mp->next_hop_weight, - ~0 /* adj_index */ , - fib_index); + fib_table_entry_path_remove (fib_index, + prefix, + FIB_SOURCE_API, + (next_hop_proto_is_ip4 ? + FIB_PROTOCOL_IP4 : + FIB_PROTOCOL_IP6), + next_hop, + next_hop_sw_if_index, + next_hop_fib_index, + next_hop_weight, path_flags); + dsunlock (sm); return 0; } - memset (&a, 0, sizeof (a)); - clib_memcpy (a.dst_address.data, mp->dst_address, - sizeof (a.dst_address.data)); - - a.dst_address_length = mp->dst_address_length; - - a.flags = (mp->is_add ? IP4_ROUTE_FLAG_ADD : IP4_ROUTE_FLAG_DEL); - a.flags |= IP4_ROUTE_FLAG_FIB_INDEX; - a.table_index_or_table_id = fib_index; - a.add_adj = 0; - a.n_add_adj = 0; - - if (mp->not_last) - a.flags |= IP4_ROUTE_FLAG_NOT_LAST_IN_GROUP; - dslock (sm, 1 /* release hint */ , 2 /* tag */ ); - if (mp->is_add) + if (is_drop || is_local || is_classify || is_unreach || is_prohibit) { - if (mp->is_drop) - ai = lm->drop_adj_index; - else if (mp->is_local) - ai = lm->local_adj_index; - else if (mp->is_classify) + /* + * special route types that link directly to the adj + */ + if (is_add) { - if (pool_is_free_index - (cm->tables, ntohl (mp->classify_table_index))) + dpo_id_t dpo = DPO_INVALID; + dpo_proto_t dproto; + + dproto = fib_proto_to_dpo (prefix->fp_proto); + + if (is_drop) + ip_null_dpo_add_and_lock (dproto, IP_NULL_ACTION_NONE, &dpo); + else if (is_local) + receive_dpo_add_or_lock (dproto, ~0, NULL, &dpo); + else if (is_unreach) + ip_null_dpo_add_and_lock (dproto, + IP_NULL_ACTION_SEND_ICMP_UNREACH, &dpo); + else if (is_prohibit) + ip_null_dpo_add_and_lock (dproto, + IP_NULL_ACTION_SEND_ICMP_PROHIBIT, + &dpo); + else if (is_classify) { - dsunlock (sm); - return VNET_API_ERROR_NO_SUCH_TABLE; - } - adj = ip_add_adjacency (lm, - /* template */ 0, - /* block size */ 1, - &ai); + if (pool_is_free_index (cm->tables, + ntohl (classify_table_index))) + { + dsunlock (sm); + return VNET_API_ERROR_NO_SUCH_TABLE; + } - adj->lookup_next_index = IP_LOOKUP_NEXT_CLASSIFY; - adj->classify.table_index = ntohl (mp->classify_table_index); - } - else if (mp->lookup_in_vrf) - { - p = hash_get (im->fib_index_by_table_id, ntohl (mp->lookup_in_vrf)); - if (p) - { - adj = ip_add_adjacency (lm, - /* template */ 0, - /* block size */ 1, - &ai); - adj->explicit_fib_index = p[0]; + dpo_set (&dpo, DPO_CLASSIFY, dproto, + classify_dpo_create (dproto, + ntohl (classify_table_index))); } else { dsunlock (sm); - return VNET_API_ERROR_NO_SUCH_INNER_FIB; + return VNET_API_ERROR_NO_SUCH_TABLE; } + + fib_table_entry_special_dpo_update (fib_index, + prefix, + FIB_SOURCE_API, + FIB_ENTRY_FLAG_EXCLUSIVE, &dpo); + dpo_reset (&dpo); } else - ai = ip4_route_get_next_hop_adj (im, - fib_index, - &next_hop_address, - ntohl (mp->next_hop_sw_if_index), - fib_index); - - if (ai == lm->miss_adj_index) { - dsunlock (sm); - return VNET_API_ERROR_NO_SUCH_INNER_FIB; + fib_table_entry_special_remove (fib_index, prefix, FIB_SOURCE_API); } } else { - ip_adjacency_t *adj; - int disable_default_route = 1; - - /* Trying to delete the default route? */ - if (a.dst_address.as_u32 == 0 && a.dst_address_length == 0) - disable_default_route = 0; - - ai = ip4_fib_lookup_with_table - (im, fib_index, &a.dst_address, disable_default_route); - if (ai == lm->miss_adj_index) + if (is_add) { - dsunlock (sm); - return VNET_API_ERROR_UNKNOWN_DESTINATION; + fib_route_path_flags_t path_flags = FIB_ROUTE_PATH_FLAG_NONE; + + if (is_resolve_host) + path_flags |= FIB_ROUTE_PATH_RESOLVE_VIA_HOST; + if (is_resolve_attached) + path_flags |= FIB_ROUTE_PATH_RESOLVE_VIA_ATTACHED; + + fib_table_entry_update_one_path (fib_index, + prefix, + FIB_SOURCE_API, + FIB_ENTRY_FLAG_NONE, + (next_hop_proto_is_ip4 ? + FIB_PROTOCOL_IP4 : + FIB_PROTOCOL_IP6), + next_hop, + next_hop_sw_if_index, + next_hop_fib_index, + next_hop_weight, + next_hop_out_label, path_flags); } - - adj = ip_get_adjacency (lm, ai); - if (adj->lookup_next_index == IP_LOOKUP_NEXT_ARP) + else { - dsunlock (sm); - return VNET_API_ERROR_ADDRESS_MATCHES_INTERFACE_ADDRESS; + fib_table_entry_delete (fib_index, prefix, FIB_SOURCE_API); } } - a.adj_index = ai; - ip4_add_del_route (im, &a); - dsunlock (sm); - return 0; + return (0); } static int -ip6_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp) +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, + u32 next_hop_table_id, + u8 create_missing_tables, + u32 * fib_index, u32 * next_hop_fib_index) { - ip6_main_t *im = &ip6_main; - ip_lookup_main_t *lm = &im->lookup_main; vnet_main_t *vnm = vnet_get_main (); - vlib_main_t *vm = vlib_get_main (); - vpe_api_main_t *vam = &vpe_api_main; - stats_main_t *sm = &stats_main; - ip6_add_del_route_args_t a; - ip6_address_t next_hop_address; - pending_route_t *pr; - vl_api_ip_add_del_route_t *adr; - - u32 fib_index; - uword *p; - clib_error_t *e; - ip_adjacency_t *adj = 0; - u32 ai; - p = hash_get (im->fib_index_by_table_id, ntohl (mp->vrf_id)); - - if (!p) + *fib_index = fib_table_find (table_proto, ntohl (table_id)); + if (~0 == *fib_index) { - if (mp->create_vrf_if_needed) + if (create_missing_tables) { - ip6_fib_t *f; - f = find_ip6_fib_by_table_index_or_id (im, ntohl (mp->vrf_id), - 0 /* flags */ ); - fib_index = f->index; + *fib_index = fib_table_find_or_create_and_lock (table_proto, + ntohl (table_id)); } else { @@ -1143,160 +1213,191 @@ ip6_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp) return VNET_API_ERROR_NO_SUCH_FIB; } } - else + + if (~0 != ntohl (next_hop_sw_if_index)) { - fib_index = p[0]; + if (pool_is_free_index (vnm->interface_main.sw_interfaces, + ntohl (next_hop_sw_if_index))) + { + return VNET_API_ERROR_NO_MATCHING_INTERFACE; + } } - - if (~0 != mp->next_hop_sw_if_index && - pool_is_free_index (vnm->interface_main.sw_interfaces, - ntohl (mp->next_hop_sw_if_index))) - return VNET_API_ERROR_NO_MATCHING_INTERFACE; - - clib_memcpy (next_hop_address.as_u8, mp->next_hop_address, - sizeof (next_hop_address.as_u8)); - - /* Arp for the next_hop if necessary */ - if (mp->is_add && mp->resolve_if_needed && ~0 != mp->next_hop_sw_if_index) + else { - u32 lookup_result; - ip_adjacency_t *adj; + *next_hop_fib_index = fib_table_find (next_hop_table_proto, + ntohl (next_hop_table_id)); - lookup_result = ip6_fib_lookup_with_table - (im, fib_index, &next_hop_address); - - adj = ip_get_adjacency (lm, lookup_result); - - if (adj->lookup_next_index == IP_LOOKUP_NEXT_ARP) + if (~0 == *next_hop_fib_index) { - pool_get (vam->pending_routes, pr); - adr = &pr->r; - pr->resolve_type = RESOLVE_IP6_ADD_DEL_ROUTE; - clib_memcpy (adr, mp, sizeof (*adr)); - /* recursion block, "just in case" */ - adr->resolve_if_needed = 0; - adr->resolve_attempts = ntohl (mp->resolve_attempts); - vnet_register_ip6_neighbor_resolution_event - (vnm, &next_hop_address, vpe_resolver_process_node.index, - RESOLUTION_EVENT, pr - vam->pending_routes); - - vlib_process_signal_event - (vm, vpe_resolver_process_node.index, - RESOLUTION_PENDING_EVENT, 0 /* data */ ); + if (create_missing_tables) + { + *next_hop_fib_index = + fib_table_find_or_create_and_lock (next_hop_table_proto, + ntohl (next_hop_table_id)); + } + else + { + /* No such VRF, and we weren't asked to create one */ + return VNET_API_ERROR_NO_SUCH_FIB; + } + } + } - /* The interface may be down, etc. */ - e = ip6_probe_neighbor - (vm, (ip6_address_t *) & (mp->next_hop_address), - ntohl (mp->next_hop_sw_if_index)); + return (0); +} - if (e) - clib_error_report (e); +static int +ip4_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp) +{ + u32 fib_index, next_hop_fib_index; + int rv; - return VNET_API_ERROR_IN_PROGRESS; - } - } + rv = add_del_route_check (FIB_PROTOCOL_IP4, + mp->table_id, + mp->next_hop_sw_if_index, + FIB_PROTOCOL_IP4, + mp->next_hop_table_id, + mp->create_vrf_if_needed, + &fib_index, &next_hop_fib_index); - if (mp->is_multipath) - { - u32 flags; + if (0 != rv) + return (rv); - dslock (sm, 1 /* release hint */ , 11 /* tag */ ); + fib_prefix_t pfx = { + .fp_len = mp->dst_address_length, + .fp_proto = FIB_PROTOCOL_IP4, + }; + clib_memcpy (&pfx.fp_addr.ip4, mp->dst_address, sizeof (pfx.fp_addr.ip4)); + + ip46_address_t nh; + memset (&nh, 0, sizeof (nh)); + memcpy (&nh.ip4, mp->next_hop_address, sizeof (nh.ip4)); + + return (add_del_route_t_handler (mp->is_multipath, + mp->is_add, + mp->is_drop, + mp->is_unreach, + mp->is_prohibit, + mp->is_local, + mp->is_classify, + mp->classify_table_index, + mp->is_resolve_host, + mp->is_resolve_attached, + fib_index, &pfx, 1, + &nh, + ntohl (mp->next_hop_sw_if_index), + next_hop_fib_index, + mp->next_hop_weight, + ntohl (mp->next_hop_out_label))); +} - if (mp->is_add) - flags = IP6_ROUTE_FLAG_ADD; - else - flags = IP6_ROUTE_FLAG_DEL; - - if (mp->not_last) - flags |= IP6_ROUTE_FLAG_NOT_LAST_IN_GROUP; - - ip6_add_del_route_next_hop (im, flags, - (ip6_address_t *) mp->dst_address, - (u32) mp->dst_address_length, - (ip6_address_t *) mp->next_hop_address, - ntohl (mp->next_hop_sw_if_index), - (u32) mp->next_hop_weight, - ~0 /* adj_index */ , - fib_index); - dsunlock (sm); - return 0; - } +static int +ip6_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp) +{ + u32 fib_index, next_hop_fib_index; + int rv; - memset (&a, 0, sizeof (a)); - clib_memcpy (a.dst_address.as_u8, mp->dst_address, - sizeof (a.dst_address.as_u8)); + rv = add_del_route_check (FIB_PROTOCOL_IP6, + mp->table_id, + mp->next_hop_sw_if_index, + FIB_PROTOCOL_IP6, + mp->next_hop_table_id, + mp->create_vrf_if_needed, + &fib_index, &next_hop_fib_index); - a.dst_address_length = mp->dst_address_length; + if (0 != rv) + return (rv); - a.flags = (mp->is_add ? IP6_ROUTE_FLAG_ADD : IP6_ROUTE_FLAG_DEL); - a.flags |= IP6_ROUTE_FLAG_FIB_INDEX; - a.table_index_or_table_id = fib_index; - a.add_adj = 0; - a.n_add_adj = 0; + fib_prefix_t pfx = { + .fp_len = mp->dst_address_length, + .fp_proto = FIB_PROTOCOL_IP6, + }; + clib_memcpy (&pfx.fp_addr.ip6, mp->dst_address, sizeof (pfx.fp_addr.ip6)); + + ip46_address_t nh; + memset (&nh, 0, sizeof (nh)); + memcpy (&nh.ip6, mp->next_hop_address, sizeof (nh.ip6)); + + return (add_del_route_t_handler (mp->is_multipath, + mp->is_add, + mp->is_drop, + mp->is_unreach, + mp->is_prohibit, + mp->is_local, + 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), + next_hop_fib_index, + mp->next_hop_weight, + ntohl (mp->next_hop_out_label))); +} - if (mp->not_last) - a.flags |= IP6_ROUTE_FLAG_NOT_LAST_IN_GROUP; +static int +mpls_route_add_del_t_handler (vnet_main_t * vnm, + vl_api_mpls_route_add_del_t * mp) +{ + u32 fib_index, next_hop_fib_index; - dslock (sm, 1 /* release hint */ , 3 /* tag */ ); + int rv; - if (mp->is_add) + fib_prefix_t pfx = { + .fp_len = 21, + .fp_proto = FIB_PROTOCOL_MPLS, + .fp_eos = mp->mr_eos, + .fp_label = ntohl (mp->mr_label), + }; + if (pfx.fp_eos) { - if (mp->is_drop) - ai = lm->drop_adj_index; - else if (mp->is_local) - ai = lm->local_adj_index; - else if (mp->lookup_in_vrf) + if (mp->mr_next_hop_proto_is_ip4) { - p = hash_get (im->fib_index_by_table_id, ntohl (mp->lookup_in_vrf)); - if (p) - { - adj = ip_add_adjacency (lm, - /* template */ 0, - /* block size */ 1, - &ai); - adj->explicit_fib_index = p[0]; - } - else - { - dsunlock (sm); - return VNET_API_ERROR_NO_SUCH_INNER_FIB; - } + pfx.fp_payload_proto = DPO_PROTO_IP4; } else - ai = ip6_route_get_next_hop_adj (im, - fib_index, - &next_hop_address, - ntohl (mp->next_hop_sw_if_index), - fib_index); - if (ai == lm->miss_adj_index) { - dsunlock (sm); - return VNET_API_ERROR_NEXT_HOP_NOT_IN_FIB; + pfx.fp_payload_proto = DPO_PROTO_IP6; } } else { - ip_adjacency_t *adj; - - ai = ip6_fib_lookup_with_table (im, fib_index, &a.dst_address); - if (ai == lm->miss_adj_index) - { - dsunlock (sm); - return VNET_API_ERROR_UNKNOWN_DESTINATION; - } - adj = ip_get_adjacency (lm, ai); - if (adj->lookup_next_index == IP_LOOKUP_NEXT_ARP) - { - dsunlock (sm); - return VNET_API_ERROR_ADDRESS_MATCHES_INTERFACE_ADDRESS; - } + pfx.fp_payload_proto = DPO_PROTO_MPLS; } - a.adj_index = ai; - ip6_add_del_route (im, &a); + rv = add_del_route_check (FIB_PROTOCOL_MPLS, + mp->mr_table_id, + mp->mr_next_hop_sw_if_index, + dpo_proto_to_fib (pfx.fp_payload_proto), + mp->mr_next_hop_table_id, + mp->mr_create_table_if_needed, + &fib_index, &next_hop_fib_index); - dsunlock (sm); - return 0; + if (0 != rv) + return (rv); + + ip46_address_t nh; + memset (&nh, 0, sizeof (nh)); + + if (mp->mr_next_hop_proto_is_ip4) + memcpy (&nh.ip4, mp->mr_next_hop, sizeof (nh.ip4)); + else + memcpy (&nh.ip6, mp->mr_next_hop, sizeof (nh.ip6)); + + return (add_del_route_t_handler (mp->mr_is_multipath, mp->mr_is_add, 0, // mp->is_drop, + 0, // mp->is_unreach, + 0, // mp->is_prohibit, + 0, // mp->is_local, + mp->mr_is_classify, + mp->mr_classify_table_index, + mp->mr_is_resolve_host, + mp->mr_is_resolve_attached, + fib_index, &pfx, + mp->mr_next_hop_proto_is_ip4, + &nh, ntohl (mp->mr_next_hop_sw_if_index), + next_hop_fib_index, + mp->mr_next_hop_weight, + ntohl (mp->mr_next_hop_out_label))); } void @@ -1319,45 +1420,92 @@ vl_api_ip_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp) } void -api_config_default_ip_route (u8 is_ipv6, u8 is_add, u32 vrf_id, - u32 sw_if_index, u8 * next_hop_addr) +vl_api_mpls_route_add_del_t_handler (vl_api_mpls_route_add_del_t * mp) { - vl_api_ip_add_del_route_t mp; + vl_api_mpls_route_add_del_reply_t *rmp; + vnet_main_t *vnm; int rv; - memset (&mp, 0, sizeof (vl_api_ip_add_del_route_t)); + vnm = vnet_get_main (); + vnm->api_errno = 0; - /* - * Configure default IP route: - * - ip route add 0.0.0.0/1 via - * - ip route add 128.0.0.0/1 via - */ - mp.next_hop_sw_if_index = ntohl (sw_if_index); - mp.vrf_id = vrf_id; - mp.resolve_attempts = ~0; - mp.resolve_if_needed = 1; - mp.is_add = is_add; - mp.is_ipv6 = is_ipv6; - mp.next_hop_weight = 1; + rv = mpls_route_add_del_t_handler (vnm, mp); - clib_memcpy (&mp.next_hop_address[0], next_hop_addr, 16); + rv = (rv == 0) ? vnm->api_errno : rv; - if (is_ipv6) - rv = ip6_add_del_route_t_handler (&mp); - else + REPLY_MACRO (VL_API_MPLS_ROUTE_ADD_DEL_REPLY); +} + +static int +mpls_ip_bind_unbind_handler (vnet_main_t * vnm, + vl_api_mpls_ip_bind_unbind_t * mp) +{ + u32 mpls_fib_index, ip_fib_index; + + mpls_fib_index = + fib_table_find (FIB_PROTOCOL_MPLS, ntohl (mp->mb_mpls_table_id)); + + if (~0 == mpls_fib_index) { - mp.dst_address_length = 1; + if (mp->mb_create_table_if_needed) + { + mpls_fib_index = + fib_table_find_or_create_and_lock (FIB_PROTOCOL_MPLS, + ntohl (mp->mb_mpls_table_id)); + } + else + return VNET_API_ERROR_NO_SUCH_FIB; + } - mp.dst_address[0] = 0; - rv = ip4_add_del_route_t_handler (&mp); + ip_fib_index = fib_table_find ((mp->mb_is_ip4 ? + FIB_PROTOCOL_IP4 : + FIB_PROTOCOL_IP6), + ntohl (mp->mb_ip_table_id)); + if (~0 == ip_fib_index) + return VNET_API_ERROR_NO_SUCH_FIB; + + fib_prefix_t pfx = { + .fp_len = mp->mb_address_length, + }; - mp.dst_address[0] = 128; - rv |= ip4_add_del_route_t_handler (&mp); + if (mp->mb_is_ip4) + { + pfx.fp_proto = FIB_PROTOCOL_IP4; + clib_memcpy (&pfx.fp_addr.ip4, mp->mb_address, + sizeof (pfx.fp_addr.ip4)); + } + else + { + pfx.fp_proto = FIB_PROTOCOL_IP6; + clib_memcpy (&pfx.fp_addr.ip6, mp->mb_address, + sizeof (pfx.fp_addr.ip6)); } - if (rv) - clib_error_return (0, "failed to config default IP route"); + if (mp->mb_is_bind) + fib_table_entry_local_label_add (ip_fib_index, &pfx, + ntohl (mp->mb_label)); + else + fib_table_entry_local_label_remove (ip_fib_index, &pfx, + ntohl (mp->mb_label)); + + return (0); +} + +void +vl_api_mpls_ip_bind_unbind_t_handler (vl_api_mpls_ip_bind_unbind_t * mp) +{ + vl_api_mpls_route_add_del_reply_t *rmp; + vnet_main_t *vnm; + int rv; + + vnm = vnet_get_main (); + vnm->api_errno = 0; + + rv = mpls_ip_bind_unbind_handler (vnm, mp); + + rv = (rv == 0) ? vnm->api_errno : rv; + REPLY_MACRO (VL_API_MPLS_ROUTE_ADD_DEL_REPLY); } static void @@ -1397,6 +1545,7 @@ vl_api_sw_interface_set_table_t_handler (vl_api_sw_interface_set_table_t * mp) u32 sw_if_index = ntohl (mp->sw_if_index); vl_api_sw_interface_set_table_reply_t *rmp; stats_main_t *sm = &stats_main; + u32 fib_index; VALIDATE_SW_IF_INDEX (mp); @@ -1404,35 +1553,20 @@ vl_api_sw_interface_set_table_t_handler (vl_api_sw_interface_set_table_t * mp) if (mp->is_ipv6) { - ip6_main_t *im = &ip6_main; - ip6_fib_t *fib = find_ip6_fib_by_table_index_or_id (im, table_id, - IP6_ROUTE_FLAG_TABLE_ID); - if (fib) - { - vec_validate (im->fib_index_by_sw_if_index, sw_if_index); - im->fib_index_by_sw_if_index[sw_if_index] = fib->index; - } - else - { - rv = VNET_API_ERROR_NO_SUCH_FIB; - } + fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, + table_id); + + vec_validate (ip6_main.fib_index_by_sw_if_index, sw_if_index); + ip6_main.fib_index_by_sw_if_index[sw_if_index] = fib_index; } else { - ip4_main_t *im = &ip4_main; - ip4_fib_t *fib = find_ip4_fib_by_table_index_or_id - (im, table_id, IP4_ROUTE_FLAG_TABLE_ID); - /* Truthfully this can't fail */ - if (fib) - { - vec_validate (im->fib_index_by_sw_if_index, sw_if_index); - im->fib_index_by_sw_if_index[sw_if_index] = fib->index; - } - else - { - rv = VNET_API_ERROR_NO_SUCH_FIB; - } + fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, + table_id); + + vec_validate (ip4_main.fib_index_by_sw_if_index, sw_if_index); + ip4_main.fib_index_by_sw_if_index[sw_if_index] = fib_index; } dsunlock (sm); @@ -1444,79 +1578,21 @@ vl_api_sw_interface_set_table_t_handler (vl_api_sw_interface_set_table_t * mp) static void vl_api_sw_interface_set_vpath_t_handler (vl_api_sw_interface_set_vpath_t * mp) { - vlib_main_t *vm = vlib_get_main (); - ip4_main_t *im4 = &ip4_main; - ip6_main_t *im6 = &ip6_main; vl_api_sw_interface_set_vpath_reply_t *rmp; int rv = 0; - u32 ci; u32 sw_if_index = ntohl (mp->sw_if_index); - ip4_main_t *ip4m = &ip4_main; - ip6_main_t *ip6m = &ip6_main; - ip_lookup_main_t *ip4lm = &ip4m->lookup_main; - ip_lookup_main_t *ip6lm = &ip6m->lookup_main; - ip_config_main_t *rx_cm4u = - &ip4lm->feature_config_mains[VNET_IP_RX_UNICAST_FEAT]; - ip_config_main_t *rx_cm4m = - &ip4lm->feature_config_mains[VNET_IP_RX_MULTICAST_FEAT]; - ip_config_main_t *rx_cm6u = - &ip6lm->feature_config_mains[VNET_IP_RX_UNICAST_FEAT]; - ip_config_main_t *rx_cm6m = - &ip6lm->feature_config_mains[VNET_IP_RX_MULTICAST_FEAT]; VALIDATE_SW_IF_INDEX (mp); l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_VPATH, mp->enable); - if (mp->enable) - { - ci = rx_cm4u->config_index_by_sw_if_index[sw_if_index]; //IP4 unicast - ci = vnet_config_add_feature (vm, &rx_cm4u->config_main, - ci, - im4->ip4_unicast_rx_feature_vpath, 0, 0); - rx_cm4u->config_index_by_sw_if_index[sw_if_index] = ci; - ci = rx_cm4m->config_index_by_sw_if_index[sw_if_index]; //IP4 mcast - ci = vnet_config_add_feature (vm, &rx_cm4m->config_main, - ci, - im4->ip4_multicast_rx_feature_vpath, - 0, 0); - rx_cm4m->config_index_by_sw_if_index[sw_if_index] = ci; - ci = rx_cm6u->config_index_by_sw_if_index[sw_if_index]; //IP6 unicast - ci = vnet_config_add_feature (vm, &rx_cm6u->config_main, - ci, - im6->ip6_unicast_rx_feature_vpath, 0, 0); - rx_cm6u->config_index_by_sw_if_index[sw_if_index] = ci; - ci = rx_cm6m->config_index_by_sw_if_index[sw_if_index]; //IP6 mcast - ci = vnet_config_add_feature (vm, &rx_cm6m->config_main, - ci, - im6->ip6_multicast_rx_feature_vpath, - 0, 0); - rx_cm6m->config_index_by_sw_if_index[sw_if_index] = ci; - } - else - { - ci = rx_cm4u->config_index_by_sw_if_index[sw_if_index]; //IP4 unicast - ci = vnet_config_del_feature (vm, &rx_cm4u->config_main, - ci, - im4->ip4_unicast_rx_feature_vpath, 0, 0); - rx_cm4u->config_index_by_sw_if_index[sw_if_index] = ci; - ci = rx_cm4m->config_index_by_sw_if_index[sw_if_index]; //IP4 mcast - ci = vnet_config_del_feature (vm, &rx_cm4m->config_main, - ci, - im4->ip4_multicast_rx_feature_vpath, - 0, 0); - rx_cm4m->config_index_by_sw_if_index[sw_if_index] = ci; - ci = rx_cm6u->config_index_by_sw_if_index[sw_if_index]; //IP6 unicast - ci = vnet_config_del_feature (vm, &rx_cm6u->config_main, - ci, - im6->ip6_unicast_rx_feature_vpath, 0, 0); - rx_cm6u->config_index_by_sw_if_index[sw_if_index] = ci; - ci = rx_cm6m->config_index_by_sw_if_index[sw_if_index]; //IP6 mcast - ci = vnet_config_del_feature (vm, &rx_cm6m->config_main, - ci, - im6->ip6_multicast_rx_feature_vpath, - 0, 0); - rx_cm6m->config_index_by_sw_if_index[sw_if_index] = ci; - } + vnet_feature_enable_disable ("ip4-unicast", "vpath-input-ip4", + sw_if_index, mp->enable, 0, 0); + vnet_feature_enable_disable ("ip4-multicast", "vpath-input-ip4", + sw_if_index, mp->enable, 0, 0); + vnet_feature_enable_disable ("ip6-unicast", "vpath-input-ip6", + sw_if_index, mp->enable, 0, 0); + vnet_feature_enable_disable ("ip6-multicast", "vpath-input-ip6", + sw_if_index, mp->enable, 0, 0); BAD_SW_IF_INDEX_LABEL; @@ -1588,6 +1664,152 @@ static void REPLY_MACRO (VL_API_SW_INTERFACE_SET_L2_BRIDGE_REPLY); } +static void + vl_api_sw_interface_set_dpdk_hqos_pipe_t_handler + (vl_api_sw_interface_set_dpdk_hqos_pipe_t * mp) +{ + vl_api_sw_interface_set_dpdk_hqos_pipe_reply_t *rmp; + int rv = 0; + +#if DPDK > 0 + dpdk_main_t *dm = &dpdk_main; + dpdk_device_t *xd; + + u32 sw_if_index = ntohl (mp->sw_if_index); + u32 subport = ntohl (mp->subport); + u32 pipe = ntohl (mp->pipe); + u32 profile = ntohl (mp->profile); + vnet_hw_interface_t *hw; + + VALIDATE_SW_IF_INDEX (mp); + + /* hw_if & dpdk device */ + hw = vnet_get_sup_hw_interface (dm->vnet_main, sw_if_index); + + xd = vec_elt_at_index (dm->devices, hw->dev_instance); + + rv = rte_sched_pipe_config (xd->hqos_ht->hqos, subport, pipe, profile); + + BAD_SW_IF_INDEX_LABEL; +#else + clib_warning ("setting HQoS pipe parameters without DPDK not implemented"); + rv = VNET_API_ERROR_UNIMPLEMENTED; +#endif /* DPDK */ + + REPLY_MACRO (VL_API_SW_INTERFACE_SET_DPDK_HQOS_PIPE_REPLY); +} + +static void + vl_api_sw_interface_set_dpdk_hqos_subport_t_handler + (vl_api_sw_interface_set_dpdk_hqos_subport_t * mp) +{ + vl_api_sw_interface_set_dpdk_hqos_subport_reply_t *rmp; + int rv = 0; + +#if DPDK > 0 + dpdk_main_t *dm = &dpdk_main; + dpdk_device_t *xd; + struct rte_sched_subport_params p; + + u32 sw_if_index = ntohl (mp->sw_if_index); + u32 subport = ntohl (mp->subport); + p.tb_rate = ntohl (mp->tb_rate); + p.tb_size = ntohl (mp->tb_size); + p.tc_rate[0] = ntohl (mp->tc_rate[0]); + p.tc_rate[1] = ntohl (mp->tc_rate[1]); + p.tc_rate[2] = ntohl (mp->tc_rate[2]); + p.tc_rate[3] = ntohl (mp->tc_rate[3]); + p.tc_period = ntohl (mp->tc_period); + + vnet_hw_interface_t *hw; + + VALIDATE_SW_IF_INDEX (mp); + + /* hw_if & dpdk device */ + hw = vnet_get_sup_hw_interface (dm->vnet_main, sw_if_index); + + xd = vec_elt_at_index (dm->devices, hw->dev_instance); + + rv = rte_sched_subport_config (xd->hqos_ht->hqos, subport, &p); + + BAD_SW_IF_INDEX_LABEL; +#else + clib_warning + ("setting HQoS subport parameters without DPDK not implemented"); + rv = VNET_API_ERROR_UNIMPLEMENTED; +#endif /* DPDK */ + + REPLY_MACRO (VL_API_SW_INTERFACE_SET_DPDK_HQOS_SUBPORT_REPLY); +} + +static void + vl_api_sw_interface_set_dpdk_hqos_tctbl_t_handler + (vl_api_sw_interface_set_dpdk_hqos_tctbl_t * mp) +{ + vl_api_sw_interface_set_dpdk_hqos_tctbl_reply_t *rmp; + int rv = 0; + +#if DPDK > 0 + dpdk_main_t *dm = &dpdk_main; + vlib_thread_main_t *tm = vlib_get_thread_main (); + dpdk_device_t *xd; + + u32 sw_if_index = ntohl (mp->sw_if_index); + u32 entry = ntohl (mp->entry); + u32 tc = ntohl (mp->tc); + u32 queue = ntohl (mp->queue); + u32 val, i; + + vnet_hw_interface_t *hw; + + VALIDATE_SW_IF_INDEX (mp); + + /* hw_if & dpdk device */ + hw = vnet_get_sup_hw_interface (dm->vnet_main, sw_if_index); + + xd = vec_elt_at_index (dm->devices, hw->dev_instance); + + if (tc >= RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE) + { + clib_warning ("invalid traffic class !!"); + rv = VNET_API_ERROR_INVALID_VALUE; + goto done; + } + if (queue >= RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS) + { + clib_warning ("invalid queue !!"); + rv = VNET_API_ERROR_INVALID_VALUE; + goto done; + } + + /* Detect the set of worker threads */ + uword *p = hash_get_mem (tm->thread_registrations_by_name, "workers"); + + if (p == 0) + { + clib_warning ("worker thread registration AWOL !!"); + rv = VNET_API_ERROR_INVALID_VALUE_2; + goto done; + } + + vlib_thread_registration_t *tr = (vlib_thread_registration_t *) p[0]; + int worker_thread_first = tr->first_index; + int worker_thread_count = tr->count; + + val = tc * RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS + queue; + for (i = 0; i < worker_thread_count; i++) + xd->hqos_wt[worker_thread_first + i].hqos_tc_table[entry] = val; + + BAD_SW_IF_INDEX_LABEL; +done: +#else + clib_warning ("setting HQoS DSCP table entry without DPDK not implemented"); + rv = VNET_API_ERROR_UNIMPLEMENTED; +#endif /* DPDK */ + + REPLY_MACRO (VL_API_SW_INTERFACE_SET_DPDK_HQOS_TCTBL_REPLY); +} + static void vl_api_bridge_domain_add_del_t_handler (vl_api_bridge_domain_add_del_t * mp) { @@ -2118,35 +2340,6 @@ out: /* *INDENT-ON* */ } -static void -vl_api_mpls_gre_add_del_tunnel_t_handler (vl_api_mpls_gre_add_del_tunnel_t * - mp) -{ - vl_api_mpls_gre_add_del_tunnel_reply_t *rmp; - int rv = 0; - stats_main_t *sm = &stats_main; - u32 tunnel_sw_if_index = ~0; - - dslock (sm, 1 /* release hint */ , 5 /* tag */ ); - - rv = vnet_mpls_gre_add_del_tunnel ((ip4_address_t *) (mp->src_address), - (ip4_address_t *) (mp->dst_address), - (ip4_address_t *) (mp->intfc_address), - (u32) (mp->intfc_address_length), - ntohl (mp->inner_vrf_id), - ntohl (mp->outer_vrf_id), - &tunnel_sw_if_index, - mp->l2_only, mp->is_add); - dsunlock (sm); - - /* *INDENT-OFF* */ - REPLY_MACRO2(VL_API_MPLS_GRE_ADD_DEL_TUNNEL_REPLY, - ({ - rmp->tunnel_sw_if_index = ntohl(tunnel_sw_if_index); - })); - /* *INDENT-ON* */ -} - static void vl_api_mpls_ethernet_add_del_tunnel_t_handler (vl_api_mpls_ethernet_add_del_tunnel_t * mp) @@ -2215,10 +2408,10 @@ static int mpls_ethernet_add_del_tunnel_2_t_handler if (inner_fib_index == outer_fib_index) return VNET_API_ERROR_INVALID_VALUE; - lookup_result = ip4_fib_lookup_with_table - (im, outer_fib_index, - (ip4_address_t *) mp->next_hop_ip4_address_in_outer_vrf, - 1 /* disable default route */ ); + // FIXME not an ADJ + lookup_result = ip4_fib_table_lookup_lb (ip4_fib_get (outer_fib_index), + (ip4_address_t *) + mp->next_hop_ip4_address_in_outer_vrf); adj = ip_get_adjacency (lm, lookup_result); tx_sw_if_index = adj->rewrite_header.sw_if_index; @@ -2313,19 +2506,6 @@ vl_api_mpls_add_del_encap_t_handler (vl_api_mpls_add_del_encap_t * mp) REPLY_MACRO (VL_API_MPLS_ADD_DEL_ENCAP_REPLY); } -static void -vl_api_mpls_add_del_decap_t_handler (vl_api_mpls_add_del_decap_t * mp) -{ - vl_api_mpls_add_del_decap_reply_t *rmp; - int rv; - - rv = vnet_mpls_add_del_decap (ntohl (mp->rx_vrf_id), ntohl (mp->tx_vrf_id), - ntohl (mp->label), ntohl (mp->next_index), - mp->s_bit, mp->is_add); - - REPLY_MACRO (VL_API_MPLS_ADD_DEL_DECAP_REPLY); -} - static void vl_api_proxy_arp_add_del_t_handler (vl_api_proxy_arp_add_del_t * mp) { @@ -2401,14 +2581,18 @@ vl_api_ip_neighbor_add_del_t_handler (vl_api_ip_neighbor_add_del_t * mp, { vl_api_ip_neighbor_add_del_reply_t *rmp; vnet_main_t *vnm = vnet_get_main (); - u32 fib_index; - int rv = 0; stats_main_t *sm = &stats_main; + int rv = 0; VALIDATE_SW_IF_INDEX (mp); dslock (sm, 1 /* release hint */ , 7 /* tag */ ); + /* + * there's no validation here of the ND/ARP entry being added. + * The expectation is that the FIB will ensure that nothing bad + * will come of adding bogus entries. + */ if (mp->is_ipv6) { if (mp->is_add) @@ -2424,56 +2608,21 @@ vl_api_ip_neighbor_add_del_t_handler (vl_api_ip_neighbor_add_del_t * mp, } else { - ip4_main_t *im = &ip4_main; - ip_lookup_main_t *lm = &im->lookup_main; ethernet_arp_ip4_over_ethernet_address_t a; - u32 ai; - ip_adjacency_t *nh_adj; - - uword *p = hash_get (im->fib_index_by_table_id, ntohl (mp->vrf_id)); - if (!p) - { - rv = VNET_API_ERROR_NO_SUCH_FIB; - goto out; - } - fib_index = p[0]; - - /* - * Unfortunately, folks have a penchant for - * adding interface addresses to the ARP cache, and - * wondering why the forwarder eventually ASSERTs... - */ - ai = ip4_fib_lookup_with_table - (im, fib_index, (ip4_address_t *) (mp->dst_address), - 1 /* disable default route */ ); - - if (ai != 0) - { - nh_adj = ip_get_adjacency (lm, ai); - /* Never allow manipulation of a local adj! */ - if (nh_adj->lookup_next_index == IP_LOOKUP_NEXT_LOCAL) - { - clib_warning ("%U matches local adj", - format_ip4_address, - (ip4_address_t *) (mp->dst_address)); - rv = VNET_API_ERROR_ADDRESS_MATCHES_INTERFACE_ADDRESS; - goto out; - } - } clib_memcpy (&a.ethernet, mp->mac_address, 6); clib_memcpy (&a.ip4, mp->dst_address, 4); if (mp->is_add) rv = vnet_arp_set_ip4_over_ethernet (vnm, ntohl (mp->sw_if_index), - fib_index, &a, mp->is_static); + &a, mp->is_static); else - rv = vnet_arp_unset_ip4_over_ethernet (vnm, ntohl (mp->sw_if_index), - fib_index, &a); + rv = + vnet_arp_unset_ip4_over_ethernet (vnm, ntohl (mp->sw_if_index), &a); } BAD_SW_IF_INDEX_LABEL; -out: + dsunlock (sm); REPLY_MACRO (VL_API_IP_NEIGHBOR_ADD_DEL_REPLY); } @@ -2516,6 +2665,7 @@ vl_api_is_address_reachable_t_handler (vl_api_is_address_reachable_t * mp) else { lm = &im4->lookup_main; + // FIXME NOT an ADJ adj_index = ip4_fib_lookup (im4, sw_if_index, &addr.ip4); } if (adj_index == ~0) @@ -2583,6 +2733,22 @@ vl_api_sw_interface_set_flags_t_handler (vl_api_sw_interface_set_flags_t * mp) REPLY_MACRO (VL_API_SW_INTERFACE_SET_FLAGS_REPLY); } +static void + vl_api_sw_interface_set_mpls_enable_t_handler + (vl_api_sw_interface_set_mpls_enable_t * mp) +{ + vl_api_sw_interface_set_mpls_enable_reply_t *rmp; + int rv = 0; + + VALIDATE_SW_IF_INDEX (mp); + + mpls_sw_interface_enable_disable (&mpls_main, + ntohl (mp->sw_if_index), mp->enable); + + BAD_SW_IF_INDEX_LABEL; + REPLY_MACRO (VL_API_SW_INTERFACE_SET_MPLS_ENABLE_REPLY); +} + static void vl_api_sw_interface_clear_stats_t_handler (vl_api_sw_interface_clear_stats_t * mp) @@ -2887,12 +3053,12 @@ vl_api_vnet_get_summary_stats_t_handler (vl_api_vnet_get_summary_stats_t * mp) } vnet_interface_counter_unlock (im); - /* Note: in HOST byte order! */ - rmp->total_pkts[VLIB_RX] = total_pkts[VLIB_RX]; - rmp->total_bytes[VLIB_RX] = total_bytes[VLIB_RX]; - rmp->total_pkts[VLIB_TX] = total_pkts[VLIB_TX]; - rmp->total_bytes[VLIB_TX] = total_bytes[VLIB_TX]; - rmp->vector_rate = vlib_last_vector_length_per_node (sm->vlib_main); + rmp->total_pkts[VLIB_RX] = clib_host_to_net_u64 (total_pkts[VLIB_RX]); + rmp->total_bytes[VLIB_RX] = clib_host_to_net_u64 (total_bytes[VLIB_RX]); + rmp->total_pkts[VLIB_TX] = clib_host_to_net_u64 (total_pkts[VLIB_TX]); + rmp->total_bytes[VLIB_TX] = clib_host_to_net_u64 (total_bytes[VLIB_TX]); + rmp->vector_rate = + clib_host_to_net_u64 (vlib_last_vector_length_per_node (sm->vlib_main)); vl_msg_api_send_shmem (q, (u8 *) & rmp); } @@ -2911,10 +3077,9 @@ ip4_reset_fib_t_handler (vl_api_reset_fib_t * mp) vnet_main_t *vnm = vnet_get_main (); vnet_interface_main_t *im = &vnm->interface_main; ip4_main_t *im4 = &ip4_main; - static ip4_route_t *routes; static u32 *sw_if_indices_to_shut; stats_main_t *sm = &stats_main; - ip4_route_t *r; + fib_table_t *fib_table; ip4_fib_t *fib; u32 sw_if_index; int i; @@ -2923,16 +3088,15 @@ ip4_reset_fib_t_handler (vl_api_reset_fib_t * mp) dslock (sm, 1 /* release hint */ , 8 /* tag */ ); - vec_foreach (fib, im4->fibs) - { - vnet_sw_interface_t *si; + /* *INDENT-OFF* */ + pool_foreach (fib_table, im4->fibs, + ({ + fib = &fib_table->v4; + vnet_sw_interface_t * si; if (fib->table_id != target_fib_id) continue; - /* remove any mpls/gre tunnels in this fib */ - vnet_mpls_gre_delete_fib_tunnels (fib->table_id); - /* remove any mpls encap/decap labels */ mpls_fib_reset_labels (fib->table_id); @@ -2945,100 +3109,37 @@ ip4_reset_fib_t_handler (vl_api_reset_fib_t * mp) vec_reset_length (sw_if_indices_to_shut); /* Shut down interfaces in this FIB / clean out intfc routes */ - /* *INDENT-OFF* */ pool_foreach (si, im->sw_interfaces, ({ u32 sw_if_index = si->sw_if_index; if (sw_if_index < vec_len (im4->fib_index_by_sw_if_index) && (im4->fib_index_by_sw_if_index[si->sw_if_index] == - fib - im4->fibs)) + fib->index)) vec_add1 (sw_if_indices_to_shut, si->sw_if_index); })); - /* *INDENT-ON* */ - - for (i = 0; i < vec_len (sw_if_indices_to_shut); i++) - { - sw_if_index = sw_if_indices_to_shut[i]; - // vec_foreach (sw_if_index, sw_if_indices_to_shut) { - u32 flags = vnet_sw_interface_get_flags (vnm, sw_if_index); - flags &= ~(VNET_SW_INTERFACE_FLAG_ADMIN_UP); - vnet_sw_interface_set_flags (vnm, sw_if_index, flags); - } - - vec_reset_length (routes); - - for (i = 0; i < ARRAY_LEN (fib->adj_index_by_dst_address); i++) - { - uword *hash = fib->adj_index_by_dst_address[i]; - hash_pair_t *p; - ip4_route_t x; - - x.address_length = i; - - /* *INDENT-OFF* */ - hash_foreach_pair (p, hash, - ({ - x.address.data_u32 = p->key; - vec_add1 (routes, x); - })); - /* *INDENT-ON* */ - } + for (i = 0; i < vec_len (sw_if_indices_to_shut); i++) { + sw_if_index = sw_if_indices_to_shut[i]; + // vec_foreach (sw_if_index, sw_if_indices_to_shut) { - vec_foreach (r, routes) - { - ip4_add_del_route_args_t a; + u32 flags = vnet_sw_interface_get_flags (vnm, sw_if_index); + flags &= ~(VNET_SW_INTERFACE_FLAG_ADMIN_UP); + vnet_sw_interface_set_flags (vnm, sw_if_index, flags); + } - memset (&a, 0, sizeof (a)); - a.flags = IP4_ROUTE_FLAG_FIB_INDEX | IP4_ROUTE_FLAG_DEL; - a.table_index_or_table_id = fib - im4->fibs; - a.dst_address = r->address; - a.dst_address_length = r->address_length; - a.adj_index = ~0; + fib_table_flush(fib->index, FIB_PROTOCOL_IP4, FIB_SOURCE_API); + fib_table_flush(fib->index, FIB_PROTOCOL_IP4, FIB_SOURCE_INTERFACE); - ip4_add_del_route (im4, &a); - ip4_maybe_remap_adjacencies (im4, fib - im4->fibs, - IP4_ROUTE_FLAG_FIB_INDEX); - } rv = 0; break; - } /* vec_foreach (fib) */ + })); /* pool_foreach (fib) */ + /* *INDENT-ON* */ dsunlock (sm); return rv; } -typedef struct -{ - ip6_address_t address; - u32 address_length; - u32 index; -} ip6_route_t; - -typedef struct -{ - u32 fib_index; - ip6_route_t **routep; -} add_routes_in_fib_arg_t; - -static void -add_routes_in_fib (clib_bihash_kv_24_8_t * kvp, void *arg) -{ - add_routes_in_fib_arg_t *ap = arg; - - if (kvp->key[2] >> 32 == ap->fib_index) - { - ip6_address_t *addr; - ip6_route_t *r; - addr = (ip6_address_t *) kvp; - vec_add2 (*ap->routep, r, 1); - r->address = addr[0]; - r->address_length = kvp->key[2] & 0xFF; - r->index = kvp->value; - } -} - static int ip6_reset_fib_t_handler (vl_api_reset_fib_t * mp) { @@ -3046,22 +3147,21 @@ ip6_reset_fib_t_handler (vl_api_reset_fib_t * mp) vnet_interface_main_t *im = &vnm->interface_main; ip6_main_t *im6 = &ip6_main; stats_main_t *sm = &stats_main; - static ip6_route_t *routes; static u32 *sw_if_indices_to_shut; - ip6_route_t *r; + fib_table_t *fib_table; ip6_fib_t *fib; u32 sw_if_index; int i; int rv = VNET_API_ERROR_NO_SUCH_FIB; u32 target_fib_id = ntohl (mp->vrf_id); - add_routes_in_fib_arg_t _a, *a = &_a; - clib_bihash_24_8_t *h = &im6->ip6_lookup_table; dslock (sm, 1 /* release hint */ , 9 /* tag */ ); - vec_foreach (fib, im6->fibs) - { - vnet_sw_interface_t *si; + /* *INDENT-OFF* */ + pool_foreach (fib_table, im6->fibs, + ({ + vnet_sw_interface_t * si; + fib = &(fib_table->v6); if (fib->table_id != target_fib_id) continue; @@ -3069,52 +3169,29 @@ ip6_reset_fib_t_handler (vl_api_reset_fib_t * mp) vec_reset_length (sw_if_indices_to_shut); /* Shut down interfaces in this FIB / clean out intfc routes */ - /* *INDENT-OFF* */ pool_foreach (si, im->sw_interfaces, - ({ - if (im6->fib_index_by_sw_if_index[si->sw_if_index] == - fib - im6->fibs) - vec_add1 (sw_if_indices_to_shut, si->sw_if_index); - })); - /* *INDENT-ON* */ - - for (i = 0; i < vec_len (sw_if_indices_to_shut); i++) - { - sw_if_index = sw_if_indices_to_shut[i]; - // vec_foreach (sw_if_index, sw_if_indices_to_shut) { - - u32 flags = vnet_sw_interface_get_flags (vnm, sw_if_index); - flags &= ~(VNET_SW_INTERFACE_FLAG_ADMIN_UP); - vnet_sw_interface_set_flags (vnm, sw_if_index, flags); - } - - vec_reset_length (routes); + ({ + if (im6->fib_index_by_sw_if_index[si->sw_if_index] == + fib->index) + vec_add1 (sw_if_indices_to_shut, si->sw_if_index); + })); - a->fib_index = fib - im6->fibs; - a->routep = &routes; + for (i = 0; i < vec_len (sw_if_indices_to_shut); i++) { + sw_if_index = sw_if_indices_to_shut[i]; + // vec_foreach (sw_if_index, sw_if_indices_to_shut) { - clib_bihash_foreach_key_value_pair_24_8 (h, add_routes_in_fib, a); - - vec_foreach (r, routes) - { - ip6_add_del_route_args_t a; + u32 flags = vnet_sw_interface_get_flags (vnm, sw_if_index); + flags &= ~(VNET_SW_INTERFACE_FLAG_ADMIN_UP); + vnet_sw_interface_set_flags (vnm, sw_if_index, flags); + } - memset (&a, 0, sizeof (a)); - a.flags = IP6_ROUTE_FLAG_FIB_INDEX | IP6_ROUTE_FLAG_DEL; - a.table_index_or_table_id = fib - im6->fibs; - a.dst_address = r->address; - a.dst_address_length = r->address_length; - a.adj_index = ~0; + fib_table_flush(fib->index, FIB_PROTOCOL_IP6, FIB_SOURCE_API); + fib_table_flush(fib->index, FIB_PROTOCOL_IP6, FIB_SOURCE_INTERFACE); - ip6_add_del_route (im6, &a); - ip6_maybe_remap_adjacencies (im6, fib - im6->fibs, - IP6_ROUTE_FLAG_FIB_INDEX); - } rv = 0; - /* Reinstall the neighbor / router discovery routes */ - vnet_ip6_fib_init (im6, fib - im6->fibs); break; - } /* vec_foreach (fib) */ + })); /* pool_foreach (fib) */ + /* *INDENT-ON* */ dsunlock (sm); return rv; @@ -3189,16 +3266,12 @@ dhcpv6_proxy_config_2 (vl_api_dhcp_proxy_config_2_t * mp) vl_api_dhcp_proxy_config_reply_t *rmp; int rv = -1; -#if 0 // $$$$ FIXME rv = dhcpv6_proxy_set_server_2 ((ip6_address_t *) (&mp->dhcp_server), (ip6_address_t *) (&mp->dhcp_src_address), (u32) ntohl (mp->rx_vrf_id), (u32) ntohl (mp->server_vrf_id), (int) mp->insert_circuit_id, (int) (mp->is_add == 0)); -#else - rv = VNET_API_ERROR_UNIMPLEMENTED; -#endif REPLY_MACRO (VL_API_DHCP_PROXY_CONFIG_2_REPLY); } @@ -3261,7 +3334,9 @@ dhcp_compl_event_callback (u32 client_index, u32 pid, u8 * hostname, mp->hostname[vec_len (hostname) + 1] = '\n'; clib_memcpy (&mp->host_address[0], host_address, 16); clib_memcpy (&mp->router_address[0], router_address, 16); - clib_memcpy (&mp->host_mac[0], host_mac, 6); + + if (NULL != host_mac) + clib_memcpy (&mp->host_mac[0], host_mac, 6); mp->_vl_msg_id = ntohs (VL_API_DHCP_COMPL_EVENT); @@ -3431,7 +3506,7 @@ set_ip4_flow_hash (vl_api_set_ip_flow_hash_t * mp) vl_api_set_ip_flow_hash_reply_t *rmp; int rv; u32 table_id; - u32 flow_hash_config = 0; + flow_hash_config_t flow_hash_config = 0; table_id = ntohl (mp->vrf_id); @@ -3492,11 +3567,15 @@ static void vl_api_sw_interface_set_unnumbered_t_handler { si->flags |= VNET_SW_INTERFACE_FLAG_UNNUMBERED; si->unnumbered_sw_if_index = sw_if_index; + ip4_sw_interface_enable_disable (unnumbered_sw_if_index, 1); + ip6_sw_interface_enable_disable (unnumbered_sw_if_index, 1); } else { si->flags &= ~(VNET_SW_INTERFACE_FLAG_UNNUMBERED); si->unnumbered_sw_if_index = (u32) ~ 0; + ip4_sw_interface_enable_disable (unnumbered_sw_if_index, 0); + ip6_sw_interface_enable_disable (unnumbered_sw_if_index, 0); } done: @@ -3547,22 +3626,8 @@ vl_api_control_ping_t_handler (vl_api_control_ping_t * mp) /* *INDENT-ON* */ } -static void vl_api_noprint_control_ping_t_handler - (vl_api_noprint_control_ping_t * mp) -{ - vl_api_noprint_control_ping_reply_t *rmp; - int rv = 0; - - /* *INDENT-OFF* */ - REPLY_MACRO2(VL_API_NOPRINT_CONTROL_PING_REPLY, - ({ - rmp->vpe_pid = ntohl (getpid()); - })); - /* *INDENT-ON* */ -} - -static void -shmem_cli_output (uword arg, u8 * buffer, uword buffer_bytes) +static void +shmem_cli_output (uword arg, u8 * buffer, uword buffer_bytes) { u8 **shmem_vecp = (u8 **) arg; u8 *shmem_vec; @@ -3624,6 +3689,46 @@ vl_api_cli_request_t_handler (vl_api_cli_request_t * mp) vl_msg_api_send_shmem (q, (u8 *) & rp); } +static void +inband_cli_output (uword arg, u8 * buffer, uword buffer_bytes) +{ + u8 **mem_vecp = (u8 **) arg; + u8 *mem_vec = *mem_vecp; + u32 offset = vec_len (mem_vec); + + vec_validate (mem_vec, offset + buffer_bytes - 1); + clib_memcpy (mem_vec + offset, buffer, buffer_bytes); + *mem_vecp = mem_vec; +} + +static void +vl_api_cli_inband_t_handler (vl_api_cli_inband_t * mp) +{ + vl_api_cli_inband_reply_t *rmp; + int rv = 0; + unix_shared_memory_queue_t *q; + vlib_main_t *vm = vlib_get_main (); + unformat_input_t input; + u8 *out_vec = 0; + + q = vl_api_client_index_to_input_queue (mp->client_index); + if (!q) + return; + + unformat_init_string (&input, (char *) mp->cmd, ntohl (mp->length)); + vlib_cli_input (vm, &input, inband_cli_output, (uword) & out_vec); + + u32 len = vec_len (out_vec); + /* *INDENT-OFF* */ + REPLY_MACRO3(VL_API_CLI_INBAND_REPLY, len, + ({ + rmp->length = htonl (len); + clib_memcpy (rmp->reply, out_vec, len); + })); + /* *INDENT-ON* */ + vec_free (out_vec); +} + static void vl_api_set_arp_neighbor_limit_t_handler (vl_api_set_arp_neighbor_limit_t * mp) { @@ -3655,7 +3760,7 @@ vl_api_set_arp_neighbor_limit_t_handler (vl_api_set_arp_neighbor_limit_t * mp) static void vl_api_sr_tunnel_add_del_t_handler (vl_api_sr_tunnel_add_del_t * mp) { -#if IPV6SR == 0 +#if IP6SR == 0 clib_warning ("unimplemented"); #else ip6_sr_add_del_tunnel_args_t _a, *a = &_a; @@ -3718,7 +3823,7 @@ out: static void vl_api_sr_policy_add_del_t_handler (vl_api_sr_policy_add_del_t * mp) { -#if IPV6SR == 0 +#if IP6SR == 0 clib_warning ("unimplemented"); #else ip6_sr_add_del_policy_args_t _a, *a = &_a; @@ -3772,7 +3877,7 @@ out: static void vl_api_sr_multicast_map_add_del_t_handler (vl_api_sr_multicast_map_add_del_t * mp) { -#if IPV6SR == 0 +#if IP6SR == 0 clib_warning ("unimplemented"); #else ip6_sr_add_del_multicastmap_args_t _a, *a = &_a; @@ -3928,8 +4033,14 @@ static void vl_api_classify_set_interface_l2_tables_t_handler VALIDATE_SW_IF_INDEX (mp); - rv = vnet_l2_classify_set_tables (sw_if_index, ip4_table_index, - ip6_table_index, other_table_index); + if (mp->is_input) + rv = vnet_l2_input_classify_set_tables (sw_if_index, ip4_table_index, + ip6_table_index, + other_table_index); + else + rv = vnet_l2_output_classify_set_tables (sw_if_index, ip4_table_index, + ip6_table_index, + other_table_index); if (rv == 0) { @@ -3939,7 +4050,10 @@ static void vl_api_classify_set_interface_l2_tables_t_handler else enable = 0; - vnet_l2_classify_enable_disable (sw_if_index, enable); + if (mp->is_input) + vnet_l2_input_classify_enable_disable (sw_if_index, enable); + else + vnet_l2_output_classify_enable_disable (sw_if_index, enable); } BAD_SW_IF_INDEX_LABEL; @@ -4027,7 +4141,6 @@ vl_api_create_vhost_user_if_t_handler (vl_api_create_vhost_user_if_t * mp) { int rv = 0; vl_api_create_vhost_user_if_reply_t *rmp; -#if DPDK > 0 u32 sw_if_index = (u32) ~ 0; vnet_main_t *vnm = vnet_get_main (); @@ -4044,10 +4157,6 @@ vl_api_create_vhost_user_if_t_handler (vl_api_create_vhost_user_if_t * mp) rmp->sw_if_index = ntohl (sw_if_index); })); /* *INDENT-ON* */ -#else - rv = VNET_API_ERROR_UNIMPLEMENTED; - REPLY_MACRO (VL_API_CREATE_VHOST_USER_IF_REPLY); -#endif } static void @@ -4055,19 +4164,14 @@ vl_api_modify_vhost_user_if_t_handler (vl_api_modify_vhost_user_if_t * mp) { int rv = 0; vl_api_modify_vhost_user_if_reply_t *rmp; -#if DPDK > 0 && DPDK_VHOST_USER u32 sw_if_index = ntohl (mp->sw_if_index); vnet_main_t *vnm = vnet_get_main (); vlib_main_t *vm = vlib_get_main (); - rv = dpdk_vhost_user_modify_if (vnm, vm, (char *) mp->sock_filename, - mp->is_server, sw_if_index, (u64) ~ 0, - mp->renumber, - ntohl (mp->custom_dev_instance)); -#else - rv = VNET_API_ERROR_UNIMPLEMENTED; -#endif + rv = vhost_user_modify_if (vnm, vm, (char *) mp->sock_filename, + mp->is_server, sw_if_index, (u64) ~ 0, + mp->renumber, ntohl (mp->custom_dev_instance)); REPLY_MACRO (VL_API_MODIFY_VHOST_USER_IF_REPLY); } @@ -4076,14 +4180,13 @@ vl_api_delete_vhost_user_if_t_handler (vl_api_delete_vhost_user_if_t * mp) { int rv = 0; vl_api_delete_vhost_user_if_reply_t *rmp; -#if DPDK > 0 && DPDK_VHOST_USER vpe_api_main_t *vam = &vpe_api_main; u32 sw_if_index = ntohl (mp->sw_if_index); vnet_main_t *vnm = vnet_get_main (); vlib_main_t *vm = vlib_get_main (); - rv = dpdk_vhost_user_delete_if (vnm, vm, sw_if_index); + rv = vhost_user_delete_if (vnm, vm, sw_if_index); REPLY_MACRO (VL_API_DELETE_VHOST_USER_IF_REPLY); if (!rv) @@ -4095,10 +4198,6 @@ vl_api_delete_vhost_user_if_t_handler (vl_api_delete_vhost_user_if_t * mp) send_sw_interface_flags_deleted (vam, q, sw_if_index); } -#else - rv = VNET_API_ERROR_UNIMPLEMENTED; - REPLY_MACRO (VL_API_DELETE_VHOST_USER_IF_REPLY); -#endif } static void @@ -4108,7 +4207,6 @@ static void clib_warning ("BUG"); } -#if DPDK > 0 && DPDK_VHOST_USER static void send_sw_interface_vhost_user_details (vpe_api_main_t * am, unix_shared_memory_queue_t * q, @@ -4135,13 +4233,11 @@ send_sw_interface_vhost_user_details (vpe_api_main_t * am, vl_msg_api_send_shmem (q, (u8 *) & mp); } -#endif static void vl_api_sw_interface_vhost_user_dump_t_handler (vl_api_sw_interface_vhost_user_dump_t * mp) { -#if DPDK > 0 && DPDK_VHOST_USER int rv = 0; vpe_api_main_t *am = &vpe_api_main; vnet_main_t *vnm = vnet_get_main (); @@ -4154,7 +4250,7 @@ static void if (q == 0) return; - rv = dpdk_vhost_user_dump_ifs (vnm, vm, &ifaces); + rv = vhost_user_dump_ifs (vnm, vm, &ifaces); if (rv) return; @@ -4163,7 +4259,6 @@ static void send_sw_interface_vhost_user_details (am, q, vuid, mp->context); } vec_free (ifaces); -#endif } static void @@ -4775,7 +4870,7 @@ static void send_vxlan_tunnel_details vl_api_vxlan_tunnel_details_t *rmp; ip4_main_t *im4 = &ip4_main; ip6_main_t *im6 = &ip6_main; - u8 is_ipv6 = !(t->flags & VXLAN_TUNNEL_IS_IPV4); + u8 is_ipv6 = !ip46_address_is_ip4 (&t->dst); rmp = vl_msg_api_alloc (sizeof (*rmp)); memset (rmp, 0, sizeof (*rmp)); @@ -4784,16 +4879,17 @@ static void send_vxlan_tunnel_details { memcpy (rmp->src_address, &(t->src.ip6), 16); memcpy (rmp->dst_address, &(t->dst.ip6), 16); - rmp->encap_vrf_id = htonl (im6->fibs[t->encap_fib_index].table_id); + rmp->encap_vrf_id = htonl (im6->fibs[t->encap_fib_index].ft_table_id); } else { memcpy (rmp->src_address, &(t->src.ip4), 4); memcpy (rmp->dst_address, &(t->dst.ip4), 4); - rmp->encap_vrf_id = htonl (im4->fibs[t->encap_fib_index].table_id); + rmp->encap_vrf_id = htonl (im4->fibs[t->encap_fib_index].ft_table_id); } rmp->vni = htonl (t->vni); - rmp->decap_next_index = htonl (t->decap_next_index); + /* decap_next_index is deprecated, hard code to l2-input */ + rmp->decap_next_index = htonl (VXLAN_INPUT_NEXT_L2_INPUT); rmp->sw_if_index = htonl (t->sw_if_index); rmp->is_ipv6 = is_ipv6; rmp->context = context; @@ -4867,6 +4963,7 @@ static void vl_api_gre_add_del_tunnel_t_handler memset (a, 0, sizeof (*a)); a->is_add = mp->is_add; + a->teb = mp->teb; /* ip addresses sent in network byte order */ clib_memcpy (&(a->src), mp->src_address, 4); @@ -4895,7 +4992,8 @@ static void send_gre_tunnel_details rmp->_vl_msg_id = ntohs (VL_API_GRE_TUNNEL_DETAILS); clib_memcpy (rmp->src_address, &(t->tunnel_src), 4); clib_memcpy (rmp->dst_address, &(t->tunnel_dst), 4); - rmp->outer_fib_id = htonl (im->fibs[t->outer_fib_index].table_id); + rmp->outer_fib_id = htonl (im->fibs[t->outer_fib_index].ft_table_id); + rmp->teb = t->teb; rmp->sw_if_index = htonl (t->sw_if_index); rmp->context = context; @@ -5054,15 +5152,15 @@ static void send_vxlan_gpe_tunnel_details { memcpy (rmp->local, &(t->local.ip6), 16); memcpy (rmp->remote, &(t->remote.ip6), 16); - rmp->encap_vrf_id = htonl (im6->fibs[t->encap_fib_index].table_id); - rmp->decap_vrf_id = htonl (im6->fibs[t->decap_fib_index].table_id); + rmp->encap_vrf_id = htonl (im6->fibs[t->encap_fib_index].ft_table_id); + rmp->decap_vrf_id = htonl (im6->fibs[t->decap_fib_index].ft_table_id); } else { memcpy (rmp->local, &(t->local.ip4), 4); memcpy (rmp->remote, &(t->remote.ip4), 4); - rmp->encap_vrf_id = htonl (im4->fibs[t->encap_fib_index].table_id); - rmp->decap_vrf_id = htonl (im4->fibs[t->decap_fib_index].table_id); + rmp->encap_vrf_id = htonl (im4->fibs[t->encap_fib_index].ft_table_id); + rmp->decap_vrf_id = htonl (im4->fibs[t->decap_fib_index].ft_table_id); } rmp->vni = htonl (t->vni); rmp->protocol = t->protocol; @@ -5128,7 +5226,7 @@ vl_api_lisp_add_del_locator_set_t_handler (vl_api_lisp_add_del_locator_set_t * vnet_lisp_add_del_locator_set_args_t _a, *a = &_a; locator_t locator; ls_locator_t *ls_loc; - u32 ls_index = ~0; + u32 ls_index = ~0, locator_num; u8 *locator_name = NULL; int i; @@ -5139,9 +5237,10 @@ vl_api_lisp_add_del_locator_set_t_handler (vl_api_lisp_add_del_locator_set_t * a->name = locator_name; a->is_add = mp->is_add; a->local = 1; + locator_num = clib_net_to_host_u32 (mp->locator_num); memset (&locator, 0, sizeof (locator)); - for (i = 0; i < mp->locator_num; i++) + for (i = 0; i < locator_num; i++) { ls_loc = &((ls_locator_t *) mp->locators)[i]; VALIDATE_SW_IF_INDEX (ls_loc); @@ -5426,17 +5525,59 @@ vl_api_lisp_gpe_add_del_iface_t_handler (vl_api_lisp_gpe_add_del_iface_t * mp) { vl_api_lisp_gpe_add_del_iface_reply_t *rmp; int rv = 0; - vnet_lisp_gpe_add_del_iface_args_t _a, *a = &_a; - a->is_add = mp->is_add; - a->dp_table = mp->dp_table; - a->vni = mp->vni; - a->is_l2 = mp->is_l2; - rv = vnet_lisp_gpe_add_del_iface (a, 0); + if (mp->is_l2) + { + if (mp->is_add) + { + if (~0 == + lisp_gpe_tenant_l2_iface_add_or_lock (mp->vni, mp->dp_table)) + rv = 1; + } + else + lisp_gpe_tenant_l2_iface_unlock (mp->vni); + } + else + { + if (mp->is_add) + { + if (~0 == + lisp_gpe_tenant_l3_iface_add_or_lock (mp->vni, mp->dp_table)) + rv = 1; + } + else + lisp_gpe_tenant_l3_iface_unlock (mp->vni); + } REPLY_MACRO (VL_API_LISP_GPE_ADD_DEL_IFACE_REPLY); } +static void + vl_api_show_lisp_map_request_mode_t_handler + (vl_api_show_lisp_map_request_mode_t * mp) +{ + int rv = 0; + vl_api_show_lisp_map_request_mode_reply_t *rmp; + + /* *INDENT-OFF* */ + REPLY_MACRO2(VL_API_SHOW_LISP_MAP_REQUEST_MODE_REPLY, + ({ + rmp->mode = vnet_lisp_get_map_request_mode (); + })); + /* *INDENT-ON* */ +} + +static void +vl_api_lisp_map_request_mode_t_handler (vl_api_lisp_map_request_mode_t * mp) +{ + vl_api_lisp_map_request_mode_reply_t *rmp; + int rv = 0; + + rv = vnet_lisp_set_map_request_mode (mp->mode); + + REPLY_MACRO (VL_API_LISP_MAP_REQUEST_MODE_REPLY); +} + static void vl_api_lisp_pitr_set_locator_set_t_handler (vl_api_lisp_pitr_set_locator_set_t * mp) @@ -5481,6 +5622,7 @@ static void vl_api_lisp_add_del_remote_mapping_reply_t *rmp; int rv = 0; gid_address_t _eid, *eid = &_eid; + u32 rloc_num = clib_net_to_host_u32 (mp->rloc_num); memset (eid, 0, sizeof (eid[0])); @@ -5489,14 +5631,12 @@ static void if (rv) goto send_reply; - rlocs = unformat_lisp_locs (mp->rlocs, mp->rloc_num); - if (0 == rlocs) - goto send_reply; + rlocs = unformat_lisp_locs (mp->rlocs, rloc_num); if (!mp->is_add) { vnet_lisp_add_del_adjacency_args_t _a, *a = &_a; - gid_address_copy (&a->deid, eid); + gid_address_copy (&a->reid, eid); a->is_add = 0; rv = vnet_lisp_add_del_adjacency (a); if (rv) @@ -5528,10 +5668,10 @@ vl_api_lisp_add_del_adjacency_t_handler (vl_api_lisp_add_del_adjacency_t * mp) int rv = 0; memset (a, 0, sizeof (a[0])); - rv = unformat_lisp_eid_api (&a->seid, clib_net_to_host_u32 (mp->vni), - mp->eid_type, mp->seid, mp->seid_len); - rv |= unformat_lisp_eid_api (&a->deid, clib_net_to_host_u32 (mp->vni), - mp->eid_type, mp->deid, mp->deid_len); + rv = unformat_lisp_eid_api (&a->leid, clib_net_to_host_u32 (mp->vni), + mp->eid_type, mp->leid, mp->leid_len); + rv |= unformat_lisp_eid_api (&a->reid, clib_net_to_host_u32 (mp->vni), + mp->eid_type, mp->reid, mp->reid_len); if (rv) goto send_reply; @@ -5574,12 +5714,13 @@ send_lisp_locator_details (lisp_cp_main_t * lcm, static void vl_api_lisp_locator_dump_t_handler (vl_api_lisp_locator_dump_t * mp) { + u8 *ls_name = 0; unix_shared_memory_queue_t *q = 0; lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); locator_set_t *lsit = 0; locator_t *loc = 0; u32 ls_index = ~0, *locit = 0; - u8 filter; + uword *p = 0; q = vl_api_client_index_to_input_queue (mp->client_index); if (q == 0) @@ -5587,22 +5728,31 @@ vl_api_lisp_locator_dump_t_handler (vl_api_lisp_locator_dump_t * mp) return; } - ls_index = htonl (mp->locator_set_index); - - lsit = pool_elt_at_index (lcm->locator_set_pool, ls_index); - - filter = mp->filter; - if (filter && !((1 == filter && lsit->local) || - (2 == filter && !lsit->local))) + if (mp->is_index_set) + ls_index = htonl (mp->ls_index); + else { - return; + /* make sure we get a proper C-string */ + mp->ls_name[sizeof (mp->ls_name) - 1] = 0; + ls_name = format (0, "%s", mp->ls_name); + p = hash_get_mem (lcm->locator_set_index_by_name, ls_name); + if (!p) + goto out; + ls_index = p[0]; } + if (pool_is_free_index (lcm->locator_set_pool, ls_index)) + return; + + lsit = pool_elt_at_index (lcm->locator_set_pool, ls_index); + vec_foreach (locit, lsit->locator_indices) { loc = pool_elt_at_index (lcm->locator_pool, locit[0]); send_lisp_locator_details (lcm, loc, q, mp->context); }; +out: + vec_free (ls_name); } static void @@ -5619,19 +5769,17 @@ send_lisp_locator_set_details (lisp_cp_main_t * lcm, rmp->_vl_msg_id = ntohs (VL_API_LISP_LOCATOR_SET_DETAILS); rmp->context = context; - rmp->local = lsit->local; - rmp->locator_set_index = htonl (ls_index); + rmp->ls_index = htonl (ls_index); if (lsit->local) { ASSERT (lsit->name != NULL); - strncpy ((char *) rmp->locator_set_name, - (char *) lsit->name, ARRAY_LEN (rmp->locator_set_name) - 1); + strncpy ((char *) rmp->ls_name, (char *) lsit->name, + vec_len (lsit->name)); } else { - str = format (0, "remote-%d", ls_index); - strncpy ((char *) rmp->locator_set_name, (char *) str, - ARRAY_LEN (rmp->locator_set_name) - 1); + str = format (0, "", ls_index); + strncpy ((char *) rmp->ls_name, (char *) str, vec_len (str)); vec_free (str); } @@ -5644,7 +5792,6 @@ vl_api_lisp_locator_set_dump_t_handler (vl_api_lisp_locator_set_dump_t * mp) unix_shared_memory_queue_t *q = NULL; lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); locator_set_t *lsit = NULL; - u32 index; u8 filter; q = vl_api_client_index_to_input_queue (mp->client_index); @@ -5654,25 +5801,78 @@ vl_api_lisp_locator_set_dump_t_handler (vl_api_lisp_locator_set_dump_t * mp) } filter = mp->filter; - index = 0; /* *INDENT-OFF* */ pool_foreach (lsit, lcm->locator_set_pool, ({ if (filter && !((1 == filter && lsit->local) || - (2 == filter && !lsit->local))) { - index++; - continue; - } - send_lisp_locator_set_details(lcm, lsit, q, mp->context, index++); + (2 == filter && !lsit->local))) + { + continue; + } + send_lisp_locator_set_details (lcm, lsit, q, mp->context, + lsit - lcm->locator_set_pool); })); /* *INDENT-ON* */ } +static void +lisp_fid_put_api (u8 * dst, fid_address_t * src, u8 * prefix_length) +{ + ASSERT (prefix_length); + ip_prefix_t *ippref = &fid_addr_ippref (src); + + switch (fid_addr_type (src)) + { + case FID_ADDR_IP_PREF: + if (ip_prefix_version (ippref) == IP4) + clib_memcpy (dst, &ip_prefix_v4 (ippref), 4); + else + clib_memcpy (dst, &ip_prefix_v6 (ippref), 16); + prefix_length[0] = ip_prefix_len (ippref); + break; + + case FID_ADDR_MAC: + prefix_length[0] = 0; + clib_memcpy (dst, fid_addr_mac (src), 6); + break; + + default: + clib_warning ("Unknown FID type %d!", fid_addr_type (src)); + break; + } +} + +static u8 +fid_type_to_api_type (fid_address_t * fid) +{ + ip_prefix_t *ippref; + + switch (fid_addr_type (fid)) + { + case FID_ADDR_IP_PREF: + ippref = &fid_addr_ippref (fid); + if (ip_prefix_version (ippref) == IP4) + return 0; + else if (ip_prefix_version (ippref) == IP6) + return 1; + else + return ~0; + + case FID_ADDR_MAC: + return 2; + } + + return ~0; +} + static void send_lisp_eid_table_details (mapping_t * mapit, unix_shared_memory_queue_t * q, u32 context, u8 filter) { + fid_address_t *fid; + lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); + locator_set_t *ls = 0; vl_api_lisp_eid_table_details_t *rmp = NULL; gid_address_t *gid = NULL; u8 *mac = 0; @@ -5703,13 +5903,29 @@ send_lisp_eid_table_details (mapping_t * mapit, rmp = vl_msg_api_alloc (sizeof (*rmp)); memset (rmp, 0, sizeof (*rmp)); rmp->_vl_msg_id = ntohs (VL_API_LISP_EID_TABLE_DETAILS); - rmp->locator_set_index = mapit->locator_set_index; + + ls = pool_elt_at_index (lcm->locator_set_pool, mapit->locator_set_index); + if (vec_len (ls->locator_indices) == 0) + rmp->locator_set_index = ~0; + else + rmp->locator_set_index = clib_host_to_net_u32 (mapit->locator_set_index); + rmp->is_local = mapit->local; - rmp->ttl = mapit->ttl; + rmp->ttl = clib_host_to_net_u32 (mapit->ttl); + rmp->action = mapit->action; rmp->authoritative = mapit->authoritative; switch (gid_address_type (gid)) { + case GID_ADDR_SRC_DST: + rmp->is_src_dst = 1; + fid = &gid_address_sd_src (gid); + rmp->eid_type = fid_type_to_api_type (fid); + lisp_fid_put_api (rmp->seid, &gid_address_sd_src (gid), + &rmp->seid_prefix_len); + lisp_fid_put_api (rmp->eid, &gid_address_sd_dst (gid), + &rmp->eid_prefix_len); + break; case GID_ADDR_IP_PREFIX: rmp->eid_prefix_len = ip_prefix_len (ip_prefix); if (ip_prefix_version (ip_prefix) == IP4) @@ -5780,8 +5996,8 @@ vl_api_lisp_eid_table_dump_t_handler (vl_api_lisp_eid_table_dump_t * mp) } static void -send_lisp_gpe_tunnel_details (lisp_gpe_tunnel_t * tunnel, - unix_shared_memory_queue_t * q, u32 context) +send_lisp_gpe_fwd_entry_details (lisp_gpe_fwd_entry_t * lfe, + unix_shared_memory_queue_t * q, u32 context) { vl_api_lisp_gpe_tunnel_details_t *rmp; lisp_gpe_main_t *lgm = &lisp_gpe_main; @@ -5790,21 +6006,17 @@ send_lisp_gpe_tunnel_details (lisp_gpe_tunnel_t * tunnel, memset (rmp, 0, sizeof (*rmp)); rmp->_vl_msg_id = ntohs (VL_API_LISP_GPE_TUNNEL_DETAILS); - rmp->tunnels = tunnel - lgm->tunnels; - - rmp->is_ipv6 = ip_addr_version (&tunnel->src) == IP6 ? 1 : 0; - ip_address_copy_addr (rmp->source_ip, &tunnel->src); - ip_address_copy_addr (rmp->destination_ip, &tunnel->dst); - - rmp->encap_fib_id = htonl (tunnel->encap_fib_index); - rmp->decap_fib_id = htonl (tunnel->decap_fib_index); - rmp->dcap_next = htonl (tunnel->decap_next_index); - rmp->lisp_ver = tunnel->ver_res; - rmp->next_protocol = tunnel->next_protocol; - rmp->flags = tunnel->flags; - rmp->ver_res = tunnel->ver_res; - rmp->res = tunnel->res; - rmp->iid = htonl (tunnel->vni); + rmp->tunnels = lfe - lgm->lisp_fwd_entry_pool; + + rmp->is_ipv6 = ip_prefix_version (&(lfe->key->rmt.ippref)) == IP6 ? 1 : 0; + ip_address_copy_addr (rmp->source_ip, + &ip_prefix_addr (&(lfe->key->rmt.ippref))); + ip_address_copy_addr (rmp->destination_ip, + &ip_prefix_addr (&(lfe->key->rmt.ippref))); + + rmp->encap_fib_id = htonl (0); + rmp->decap_fib_id = htonl (lfe->eid_fib_index); + rmp->iid = htonl (lfe->key->vni); rmp->context = context; vl_msg_api_send_shmem (q, (u8 *) & rmp); @@ -5815,9 +6027,9 @@ vl_api_lisp_gpe_tunnel_dump_t_handler (vl_api_lisp_gpe_tunnel_dump_t * mp) { unix_shared_memory_queue_t *q = NULL; lisp_gpe_main_t *lgm = &lisp_gpe_main; - lisp_gpe_tunnel_t *tunnel = NULL; + lisp_gpe_fwd_entry_t *lfe = NULL; - if (pool_elts (lgm->tunnels) == 0) + if (pool_elts (lgm->lisp_fwd_entry_pool) == 0) { return; } @@ -5829,9 +6041,9 @@ vl_api_lisp_gpe_tunnel_dump_t_handler (vl_api_lisp_gpe_tunnel_dump_t * mp) } /* *INDENT-OFF* */ - pool_foreach(tunnel, lgm->tunnels, + pool_foreach(lfe, lgm->lisp_fwd_entry_pool, ({ - send_lisp_gpe_tunnel_details(tunnel, q, mp->context); + send_lisp_gpe_fwd_entry_details(lfe, q, mp->context); })); /* *INDENT-ON* */ } @@ -5898,7 +6110,7 @@ send_eid_table_map_pair (hash_pair_t * p, rmp->_vl_msg_id = ntohs (VL_API_LISP_EID_TABLE_MAP_DETAILS); rmp->vni = clib_host_to_net_u32 (p->key); - rmp->vrf = clib_host_to_net_u32 (p->value[0]); + rmp->dp_table = clib_host_to_net_u32 (p->value[0]); rmp->context = context; vl_msg_api_send_shmem (q, (u8 *) & rmp); } @@ -5910,20 +6122,145 @@ vl_api_lisp_eid_table_map_dump_t_handler (vl_api_lisp_eid_table_map_dump_t * unix_shared_memory_queue_t *q = NULL; lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); hash_pair_t *p; + uword *vni_table = 0; q = vl_api_client_index_to_input_queue (mp->client_index); if (q == 0) { return; } + + if (mp->is_l2) + { + vni_table = lcm->bd_id_by_vni; + } + else + { + vni_table = lcm->table_id_by_vni; + } + /* *INDENT-OFF* */ - hash_foreach_pair (p, lcm->table_id_by_vni, + hash_foreach_pair (p, vni_table, ({ send_eid_table_map_pair (p, q, mp->context); })); /* *INDENT-ON* */ } +static void +send_eid_table_vni (u32 vni, unix_shared_memory_queue_t * q, u32 context) +{ + vl_api_lisp_eid_table_vni_details_t *rmp = 0; + + rmp = vl_msg_api_alloc (sizeof (*rmp)); + memset (rmp, 0, sizeof (*rmp)); + rmp->_vl_msg_id = ntohs (VL_API_LISP_EID_TABLE_VNI_DETAILS); + rmp->context = context; + rmp->vni = clib_host_to_net_u32 (vni); + vl_msg_api_send_shmem (q, (u8 *) & rmp); +} + +static void +lisp_adjacency_copy (vl_api_lisp_adjacency_t * dst, lisp_adjacency_t * adjs) +{ + lisp_adjacency_t *adj; + vl_api_lisp_adjacency_t a; + u32 i, n = vec_len (adjs); + + for (i = 0; i < n; i++) + { + adj = vec_elt_at_index (adjs, i); + memset (&a, 0, sizeof (a)); + + switch (gid_address_type (&adj->reid)) + { + case GID_ADDR_IP_PREFIX: + a.reid_prefix_len = gid_address_ippref_len (&adj->reid); + a.leid_prefix_len = gid_address_ippref_len (&adj->leid); + if (gid_address_ip_version (&adj->reid) == IP4) + { + a.eid_type = 0; /* ipv4 type */ + clib_memcpy (a.reid, &gid_address_ip (&adj->reid), 4); + clib_memcpy (a.leid, &gid_address_ip (&adj->leid), 4); + } + else + { + a.eid_type = 1; /* ipv6 type */ + clib_memcpy (a.reid, &gid_address_ip (&adj->reid), 16); + clib_memcpy (a.leid, &gid_address_ip (&adj->leid), 16); + } + break; + case GID_ADDR_MAC: + a.eid_type = 2; /* l2 mac type */ + mac_copy (a.reid, gid_address_mac (&adj->reid)); + mac_copy (a.leid, gid_address_mac (&adj->leid)); + break; + default: + ASSERT (0); + } + dst[i] = a; + } +} + +static void +vl_api_lisp_adjacencies_get_t_handler (vl_api_lisp_adjacencies_get_t * mp) +{ + vl_api_lisp_adjacencies_get_reply_t *rmp = 0; + lisp_adjacency_t *adjs = 0; + int rv = 0; + vl_api_lisp_adjacency_t a; + u32 size = ~0; + u32 vni = clib_net_to_host_u32 (mp->vni); + + adjs = vnet_lisp_adjacencies_get_by_vni (vni); + size = vec_len (adjs) * sizeof (a); + + /* *INDENT-OFF* */ + REPLY_MACRO4 (VL_API_LISP_ADJACENCIES_GET_REPLY, size, + { + rmp->count = clib_host_to_net_u32 (vec_len (adjs)); + lisp_adjacency_copy (rmp->adjacencies, adjs); + }); + /* *INDENT-ON* */ + + vec_free (adjs); +} + +static void +vl_api_lisp_eid_table_vni_dump_t_handler (vl_api_lisp_eid_table_vni_dump_t * + mp) +{ + hash_pair_t *p; + u32 *vnis = 0; + unix_shared_memory_queue_t *q = 0; + lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); + + q = vl_api_client_index_to_input_queue (mp->client_index); + if (q == 0) + { + return; + } + + /* *INDENT-OFF* */ + hash_foreach_pair (p, lcm->table_id_by_vni, + ({ + hash_set (vnis, p->key, 0); + })); + + hash_foreach_pair (p, lcm->bd_id_by_vni, + ({ + hash_set (vnis, p->key, 0); + })); + + hash_foreach_pair (p, vnis, + ({ + send_eid_table_vni (p->key, q, mp->context); + })); + /* *INDENT-ON* */ + + hash_free (vnis); +} + static void vl_api_show_lisp_status_t_handler (vl_api_show_lisp_status_t * mp) { @@ -6063,29 +6400,68 @@ arp_change_data_callback (u32 pool_index, u8 * new_mac, return 1; event = pool_elt_at_index (am->arp_events, pool_index); + /* *INDENT-OFF* */ if (memcmp (&event->new_mac, new_mac, sizeof (event->new_mac))) { clib_memcpy (event->new_mac, new_mac, sizeof (event->new_mac)); } else { /* same mac */ - if ((sw_if_index == event->sw_if_index) && ((address == 0) || - /* for BD case, also check IP address with 10 sec timeout */ - ((address == event->address) - && - ((now - - arp_event_last_time) < - 10.0)))) + if (sw_if_index == event->sw_if_index && + (!event->mac_ip || + /* for BD case, also check IP address with 10 sec timeout */ + (address == event->address && + (now - arp_event_last_time) < 10.0))) return 1; } + /* *INDENT-ON* */ arp_event_last_time = now; event->sw_if_index = sw_if_index; - if (address) + if (event->mac_ip) event->address = address; return 0; } +static int +nd_change_data_callback (u32 pool_index, u8 * new_mac, + u32 sw_if_index, ip6_address_t * address) +{ + vpe_api_main_t *am = &vpe_api_main; + vlib_main_t *vm = am->vlib_main; + vl_api_ip6_nd_event_t *event; + static f64 nd_event_last_time; + f64 now = vlib_time_now (vm); + + if (pool_is_free_index (am->nd_events, pool_index)) + return 1; + + event = pool_elt_at_index (am->nd_events, pool_index); + + /* *INDENT-OFF* */ + if (memcmp (&event->new_mac, new_mac, sizeof (event->new_mac))) + { + clib_memcpy (event->new_mac, new_mac, sizeof (event->new_mac)); + } + else + { /* same mac */ + if (sw_if_index == event->sw_if_index && + (!event->mac_ip || + /* for BD case, also check IP address with 10 sec timeout */ + (ip6_address_is_equal (address, + (ip6_address_t *) event->address) && + (now - nd_event_last_time) < 10.0))) + return 1; + } + /* *INDENT-ON* */ + + nd_event_last_time = now; + event->sw_if_index = sw_if_index; + if (event->mac_ip) + clib_memcpy (event->address, address, sizeof (event->address)); + return 0; +} + static int arp_change_delete_callback (u32 pool_index, u8 * notused) { @@ -6098,6 +6474,18 @@ arp_change_delete_callback (u32 pool_index, u8 * notused) return 0; } +static int +nd_change_delete_callback (u32 pool_index, u8 * notused) +{ + vpe_api_main_t *am = &vpe_api_main; + + if (pool_is_free_index (am->nd_events, pool_index)) + return 1; + + pool_put_index (am->nd_events, pool_index); + return 0; +} + static void vl_api_want_ip4_arp_events_t_handler (vl_api_want_ip4_arp_events_t * mp) { @@ -6117,6 +6505,8 @@ vl_api_want_ip4_arp_events_t_handler (vl_api_want_ip4_arp_events_t * mp) event->context = mp->context; event->address = mp->address; event->pid = mp->pid; + if (mp->address == 0) + event->mac_ip = 1; rv = vnet_add_del_ip4_arp_change_event (vnm, arp_change_data_callback, @@ -6135,13 +6525,52 @@ vl_api_want_ip4_arp_events_t_handler (vl_api_want_ip4_arp_events_t * mp) REPLY_MACRO (VL_API_WANT_IP4_ARP_EVENTS_REPLY); } -static void vl_api_input_acl_set_interface_t_handler - (vl_api_input_acl_set_interface_t * mp) +static void +vl_api_want_ip6_nd_events_t_handler (vl_api_want_ip6_nd_events_t * mp) { - vlib_main_t *vm = vlib_get_main (); - vl_api_input_acl_set_interface_reply_t *rmp; + vpe_api_main_t *am = &vpe_api_main; + vnet_main_t *vnm = vnet_get_main (); + vl_api_want_ip6_nd_events_reply_t *rmp; + vl_api_ip6_nd_event_t *event; int rv; - u32 sw_if_index, ip4_table_index, ip6_table_index, l2_table_index; + + if (mp->enable_disable) + { + pool_get (am->nd_events, event); + memset (event, 0, sizeof (*event)); + + event->_vl_msg_id = ntohs (VL_API_IP6_ND_EVENT); + event->client_index = mp->client_index; + event->context = mp->context; + clib_memcpy (event->address, mp->address, 16); + event->pid = mp->pid; + if (ip6_address_is_zero ((ip6_address_t *) mp->address)) + event->mac_ip = 1; + + rv = vnet_add_del_ip6_nd_change_event + (vnm, nd_change_data_callback, + mp->pid, mp->address /* addr, in net byte order */ , + vpe_resolver_process_node.index, + IP6_ND_EVENT, event - am->nd_events, 1 /* is_add */ ); + } + else + { + rv = vnet_add_del_ip6_nd_change_event + (vnm, nd_change_delete_callback, + mp->pid, mp->address /* addr, in net byte order */ , + vpe_resolver_process_node.index, + IP6_ND_EVENT, ~0 /* pool index */ , 0 /* is_add */ ); + } + REPLY_MACRO (VL_API_WANT_IP6_ND_EVENTS_REPLY); +} + +static void vl_api_input_acl_set_interface_t_handler + (vl_api_input_acl_set_interface_t * mp) +{ + vlib_main_t *vm = vlib_get_main (); + vl_api_input_acl_set_interface_reply_t *rmp; + int rv; + u32 sw_if_index, ip4_table_index, ip6_table_index, l2_table_index; ip4_table_index = ntohl (mp->ip4_table_index); ip6_table_index = ntohl (mp->ip6_table_index); @@ -6742,56 +7171,31 @@ vl_api_get_node_graph_t_handler (vl_api_get_node_graph_t * mp) /* *INDENT-ON* */ } -static void vl_api_trace_profile_add_t_handler - (vl_api_trace_profile_add_t * mp) +static void +vl_api_ioam_enable_t_handler (vl_api_ioam_enable_t * mp) { int rv = 0; - vl_api_trace_profile_add_reply_t *rmp; + vl_api_ioam_enable_reply_t *rmp; clib_error_t *error; /* Ignoring the profile id as currently a single profile * is supported */ - error = ip6_ioam_trace_profile_set (mp->trace_num_elt, mp->trace_type, - ntohl (mp->node_id), - ntohl (mp->trace_app_data), - mp->pow_enable, mp->trace_tsp, - mp->trace_ppc); + error = ip6_ioam_enable (mp->trace_enable, mp->pot_enable, + mp->seqno, mp->analyse); if (error) { clib_error_report (error); rv = clib_error_get_code (error); } - REPLY_MACRO (VL_API_TRACE_PROFILE_ADD_REPLY); -} - -static void vl_api_trace_profile_apply_t_handler - (vl_api_trace_profile_apply_t * mp) -{ - int rv = 0; - vl_api_trace_profile_apply_reply_t *rmp; - - if (mp->enable != 0) - { - rv = ip6_ioam_set_destination ((ip6_address_t *) (&mp->dest_ipv6), - ntohl (mp->prefix_length), - ntohl (mp->vrf_id), - mp->trace_op == IOAM_HBYH_ADD, - mp->trace_op == IOAM_HBYH_POP, - mp->trace_op == IOAM_HBYH_MOD); - } - else - { - //ip6_ioam_clear_destination(&ip6, mp->prefix_length, mp->vrf_id); - } - REPLY_MACRO (VL_API_TRACE_PROFILE_APPLY_REPLY); + REPLY_MACRO (VL_API_IOAM_ENABLE_REPLY); } -static void vl_api_trace_profile_del_t_handler - (vl_api_trace_profile_del_t * mp) +static void +vl_api_ioam_disable_t_handler (vl_api_ioam_disable_t * mp) { int rv = 0; - vl_api_trace_profile_del_reply_t *rmp; + vl_api_ioam_disable_reply_t *rmp; clib_error_t *error; error = clear_ioam_rewrite_fn (); @@ -6801,7 +7205,7 @@ static void vl_api_trace_profile_del_t_handler rv = clib_error_get_code (error); } - REPLY_MACRO (VL_API_TRACE_PROFILE_DEL_REPLY); + REPLY_MACRO (VL_API_IOAM_DISABLE_REPLY); } static void @@ -7089,88 +7493,6 @@ vl_api_netmap_delete_t_handler (vl_api_netmap_delete_t * mp) REPLY_MACRO (VL_API_NETMAP_DELETE_REPLY); } -static void -vl_api_mpls_gre_tunnel_details_t_handler (vl_api_mpls_gre_tunnel_details_t * - mp) -{ - clib_warning ("BUG"); -} - -static void -send_mpls_gre_tunnel_entry (vpe_api_main_t * am, - unix_shared_memory_queue_t * q, - mpls_gre_tunnel_t * gt, u32 index, u32 context) -{ - vl_api_mpls_gre_tunnel_details_t *mp; - mpls_main_t *mm = &mpls_main; - mpls_encap_t *e; - int i; - u32 nlabels; - - e = pool_elt_at_index (mm->encaps, gt->encap_index); - nlabels = vec_len (e->labels); - - mp = vl_msg_api_alloc (sizeof (*mp) + nlabels * sizeof (u32)); - memset (mp, 0, sizeof (*mp)); - mp->_vl_msg_id = ntohs (VL_API_MPLS_GRE_TUNNEL_DETAILS); - mp->context = context; - - mp->tunnel_index = htonl (index); - mp->tunnel_src = gt->tunnel_src.as_u32; - mp->tunnel_dst = gt->tunnel_dst.as_u32; - mp->intfc_address = gt->intfc_address.as_u32; - mp->mask_width = htonl (gt->mask_width); - mp->inner_fib_index = htonl (gt->inner_fib_index); - mp->outer_fib_index = htonl (gt->outer_fib_index); - mp->encap_index = htonl (gt->encap_index); - mp->hw_if_index = htonl (gt->hw_if_index); - mp->l2_only = htonl (gt->l2_only); - mp->nlabels = htonl (nlabels); - - for (i = 0; i < nlabels; i++) - { - mp->labels[i] = - htonl (vnet_mpls_uc_get_label - (clib_host_to_net_u32 (e->labels[i].label_exp_s_ttl))); - } - - vl_msg_api_send_shmem (q, (u8 *) & mp); -} - -static void -vl_api_mpls_gre_tunnel_dump_t_handler (vl_api_mpls_gre_tunnel_dump_t * mp) -{ - vpe_api_main_t *am = &vpe_api_main; - unix_shared_memory_queue_t *q; - mpls_main_t *mm = &mpls_main; - mpls_gre_tunnel_t *gt; - u32 index = ntohl (mp->tunnel_index); - - q = vl_api_client_index_to_input_queue (mp->client_index); - if (q == 0) - return; - - if (index != ~0) - { - if (!pool_is_free_index (mm->gre_tunnels, index)) - { - gt = pool_elt_at_index (mm->gre_tunnels, index); - send_mpls_gre_tunnel_entry (am, q, gt, gt - mm->gre_tunnels, - mp->context); - } - } - else - { - /* *INDENT-OFF* */ - pool_foreach (gt, mm->gre_tunnels, - ({ - send_mpls_gre_tunnel_entry (am, q, gt, gt - mm->gre_tunnels, - mp->context); - })); - /* *INDENT-ON* */ - } -} - static void vl_api_mpls_eth_tunnel_details_t_handler (vl_api_mpls_eth_tunnel_details_t * mp) @@ -7253,243 +7575,564 @@ vl_api_mpls_eth_tunnel_dump_t_handler (vl_api_mpls_eth_tunnel_dump_t * mp) } static void -vl_api_mpls_fib_encap_details_t_handler (vl_api_mpls_fib_encap_details_t * mp) +vl_api_mpls_fib_details_t_handler (vl_api_mpls_fib_details_t * mp) { clib_warning ("BUG"); } static void -send_mpls_fib_encap_details (vpe_api_main_t * am, - unix_shared_memory_queue_t * q, - show_mpls_fib_t * s, u32 context) +vl_api_mpls_fib_details_t_endian (vl_api_mpls_fib_details_t * mp) { - vl_api_mpls_fib_encap_details_t *mp; - mpls_main_t *mm = &mpls_main; - mpls_encap_t *e; - int i; - u32 nlabels; + clib_warning ("BUG"); +} - e = pool_elt_at_index (mm->encaps, s->entry_index); - nlabels = vec_len (e->labels); +static void +vl_api_mpls_fib_details_t_print (vl_api_mpls_fib_details_t * mp) +{ + clib_warning ("BUG"); +} - mp = vl_msg_api_alloc (sizeof (*mp) + nlabels * sizeof (u32)); +static void +send_mpls_fib_details (vpe_api_main_t * am, + unix_shared_memory_queue_t * q, + u32 table_id, u32 label, u32 eos, + fib_route_path_encode_t * api_rpaths, u32 context) +{ + vl_api_mpls_fib_details_t *mp; + fib_route_path_encode_t *api_rpath; + vl_api_fib_path_t *fp; + int is_ip4, path_count; + + 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_MPLS_FIB_ENCAP_DETAILS); + mp->_vl_msg_id = ntohs (VL_API_MPLS_FIB_DETAILS); mp->context = context; - mp->fib_index = htonl (s->fib_index); - mp->entry_index = htonl (s->entry_index); - mp->dest = s->dest; - mp->s_bit = htonl (s->s_bit); + mp->table_id = htonl (table_id); + mp->eos_bit = eos; + mp->label = htonl (label); - mp->nlabels = htonl (nlabels); - - for (i = 0; i < nlabels; i++) - { - mp->labels[i] = - htonl (vnet_mpls_uc_get_label - (clib_host_to_net_u32 (e->labels[i].label_exp_s_ttl))); - } + mp->count = htonl (path_count); + fp = mp->path; + vec_foreach (api_rpath, api_rpaths) + { + memset (fp, 0, sizeof (*fp)); + fp->weight = htonl (api_rpath->rpath.frp_weight); + fp->sw_if_index = htonl (api_rpath->rpath.frp_sw_if_index); + memcpy (fp->next_hop, &api_rpath->rpath.frp_addr, sizeof (fp->next_hop)); + if (api_rpath->rpath.frp_proto == FIB_PROTOCOL_IP4) + fp->afi = IP46_TYPE_IP4; + else if (api_rpath->rpath.frp_proto == FIB_PROTOCOL_IP6) + fp->afi = IP46_TYPE_IP6; + else + { + 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; + } + fp++; + } vl_msg_api_send_shmem (q, (u8 *) & mp); } static void -vl_api_mpls_fib_encap_dump_t_handler (vl_api_mpls_fib_encap_dump_t * mp) +vl_api_mpls_fib_dump_t_handler (vl_api_mpls_fib_dump_t * mp) { vpe_api_main_t *am = &vpe_api_main; unix_shared_memory_queue_t *q; - vlib_main_t *vm = &vlib_global_main; - u64 key; - u32 value; - show_mpls_fib_t *records = 0; - show_mpls_fib_t *s; mpls_main_t *mm = &mpls_main; - ip4_main_t *im = &ip4_main; - ip4_fib_t *rx_fib; + fib_table_t *fib_table; + fib_node_index_t lfei, *lfeip, *lfeis = NULL; + mpls_label_t key; + fib_prefix_t pfx; + u32 fib_index; + fib_route_path_encode_t *api_rpaths; q = vl_api_client_index_to_input_queue (mp->client_index); if (q == 0) return; /* *INDENT-OFF* */ - hash_foreach (key, value, mm->mpls_encap_by_fib_and_dest, + pool_foreach (fib_table, mm->fibs, ({ - vec_add2 (records, s, 1); - s->fib_index = (u32)(key>>32); - s->dest = (u32)(key & 0xFFFFFFFF); - s->entry_index = (u32) value; + hash_foreach(key, lfei, fib_table->mpls.mf_entries, + ({ + vec_add1(lfeis, lfei); + })); })); - /* *INDENT-ON* */ - - if (0 == vec_len (records)) - { - vlib_cli_output (vm, "MPLS encap table empty"); - goto out; - } + vec_sort_with_function(lfeis, fib_entry_cmp_for_sort); - /* sort output by dst address within fib */ - vec_sort_with_function (records, mpls_dest_cmp); - vec_sort_with_function (records, mpls_fib_index_cmp); - vlib_cli_output (vm, "MPLS encap table"); - vlib_cli_output (vm, "%=6s%=16s%=16s", "Table", "Dest address", "Labels"); - vec_foreach (s, records) + vec_foreach(lfeip, lfeis) { - rx_fib = vec_elt_at_index (im->fibs, s->fib_index); - vlib_cli_output (vm, "%=6d%=16U%=16U", rx_fib->table_id, - format_ip4_address, &s->dest, format_mpls_encap_index, - mm, s->entry_index); - send_mpls_fib_encap_details (am, q, s, mp->context); + 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_mpls_fib_details (am, q, + fib_table->ft_table_id, + pfx.fp_label, + pfx.fp_eos, + api_rpaths, + mp->context); + vec_free(api_rpaths); } -out: - vec_free (records); + vec_free (lfeis); } static void -vl_api_mpls_fib_decap_details_t_handler (vl_api_mpls_fib_decap_details_t * mp) +vl_api_ip_fib_details_t_handler (vl_api_ip_fib_details_t * mp) { clib_warning ("BUG"); } static void -send_mpls_fib_decap_details (vpe_api_main_t * am, - unix_shared_memory_queue_t * q, - show_mpls_fib_t * s, - u32 rx_table_id, - u32 tx_table_id, char *swif_tag, u32 context) +vl_api_ip_fib_details_t_endian (vl_api_ip_fib_details_t * mp) { - vl_api_mpls_fib_decap_details_t *mp; - - mp = vl_msg_api_alloc (sizeof (*mp)); - memset (mp, 0, sizeof (*mp)); - mp->_vl_msg_id = ntohs (VL_API_MPLS_FIB_DECAP_DETAILS); - mp->context = context; - - mp->fib_index = htonl (s->fib_index); - mp->entry_index = htonl (s->entry_index); - mp->dest = s->dest; - mp->s_bit = htonl (s->s_bit); - mp->label = htonl (s->label); - mp->rx_table_id = htonl (rx_table_id); - mp->tx_table_id = htonl (tx_table_id); - strncpy ((char *) mp->swif_tag, - (char *) swif_tag, ARRAY_LEN (mp->swif_tag) - 1); + clib_warning ("BUG"); +} - vl_msg_api_send_shmem (q, (u8 *) & mp); +static void +vl_api_ip_fib_details_t_print (vl_api_ip_fib_details_t * mp) +{ + clib_warning ("BUG"); } static void -vl_api_mpls_fib_decap_dump_t_handler (vl_api_mpls_fib_decap_dump_t * mp) +send_ip_fib_details (vpe_api_main_t * am, + unix_shared_memory_queue_t * q, + u32 table_id, fib_prefix_t *pfx, + fib_route_path_encode_t *api_rpaths, u32 context) { - vpe_api_main_t *am = &vpe_api_main; - unix_shared_memory_queue_t *q; - vlib_main_t *vm = &vlib_global_main; - u64 key; - u32 value; - show_mpls_fib_t *records = 0; - show_mpls_fib_t *s; - mpls_main_t *mm = &mpls_main; - ip4_main_t *im = &ip4_main; - ip4_fib_t *rx_fib; - ip4_fib_t *tx_fib; - u32 tx_table_id; - char *swif_tag; + vl_api_ip_fib_details_t *mp; + fib_route_path_encode_t *api_rpath; + vl_api_fib_path_t *fp; + int is_ip4, path_count; - q = vl_api_client_index_to_input_queue (mp->client_index); - if (q == 0) + 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->context = context; - /* *INDENT-OFF* */ - hash_foreach (key, value, mm->mpls_decap_by_rx_fib_and_label, - ({ - vec_add2 (records, s, 1); - s->fib_index = (u32)(key>>32); - s->entry_index = (u32) value; - s->label = ((u32) key)>>12; - s->s_bit = (key & (1<<8)) != 0; - })); - /* *INDENT-ON* */ - - if (!vec_len (records)) - { - vlib_cli_output (vm, "MPLS decap table empty"); - goto out; - } + mp->table_id = htonl (table_id); + mp->address_length = pfx->fp_len; + memcpy(mp->address, &pfx->fp_addr.ip4, sizeof(pfx->fp_addr.ip4)); - vec_sort_with_function (records, mpls_label_cmp); - vlib_cli_output (vm, "MPLS decap table"); - vlib_cli_output (vm, "%=10s%=15s%=6s%=6s", "RX Table", "TX Table/Intfc", - "Label", "S-bit"); - vec_foreach (s, records) + mp->count = htonl (path_count); + fp = mp->path; + vec_foreach(api_rpath, api_rpaths) { - mpls_decap_t *d; - d = pool_elt_at_index (mm->decaps, s->entry_index); - if (d->next_index == MPLS_INPUT_NEXT_IP4_INPUT) + memset (fp, 0, sizeof (*fp)); + switch (api_rpath->dpo.dpoi_type) { - tx_fib = vec_elt_at_index (im->fibs, d->tx_fib_index); - tx_table_id = tx_fib->table_id; - swif_tag = " "; + case DPO_RECEIVE: + fp->is_local = true; + break; + case DPO_DROP: + fp->is_drop = true; + break; + case DPO_IP_NULL: + switch (api_rpath->dpo.dpoi_index) + { + case IP_NULL_ACTION_NONE: + fp->is_drop = true; + break; + case IP_NULL_ACTION_SEND_ICMP_UNREACH: + fp->is_unreach = true; + break; + case IP_NULL_ACTION_SEND_ICMP_PROHIBIT: + fp->is_prohibit = true; + break; + default: + break; + } + break; + default: + break; } + fp->weight = htonl(api_rpath->rpath.frp_weight); + fp->sw_if_index = htonl(api_rpath->rpath.frp_sw_if_index); + memcpy(fp->next_hop, &api_rpath->rpath.frp_addr, sizeof(fp->next_hop)); + if (api_rpath->rpath.frp_proto == FIB_PROTOCOL_IP4) + fp->afi = IP46_TYPE_IP4; + else if (api_rpath->rpath.frp_proto == FIB_PROTOCOL_IP6) + fp->afi = IP46_TYPE_IP6; else { - tx_table_id = d->tx_fib_index; - swif_tag = "(i) "; + 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; } - rx_fib = vec_elt_at_index (im->fibs, s->fib_index); - - vlib_cli_output (vm, "%=10d%=10d%=5s%=6d%=6d", rx_fib->table_id, - tx_table_id, swif_tag, s->label, s->s_bit); - - send_mpls_fib_decap_details (am, q, s, rx_fib->table_id, - tx_table_id, swif_tag, mp->context); + fp++; } -out: - vec_free (records); + vl_msg_api_send_shmem (q, (u8 *) & mp); } static void -vl_api_classify_table_ids_t_handler (vl_api_classify_table_ids_t * mp) +vl_api_ip_fib_dump_t_handler (vl_api_ip_fib_dump_t * mp) { + vpe_api_main_t *am = &vpe_api_main; 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_prefix_t pfx; + u32 fib_index; + fib_route_path_encode_t *api_rpaths; + int i; q = vl_api_client_index_to_input_queue (mp->client_index); if (q == 0) return; - vnet_classify_main_t *cm = &vnet_classify_main; - vnet_classify_table_t *t; - u32 *table_ids = 0; - u32 count; - /* *INDENT-OFF* */ - pool_foreach (t, cm->tables, + pool_foreach (fib_table, im->fibs, ({ - vec_add1 (table_ids, ntohl(t - cm->tables)); + 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); + })); + } })); - /* *INDENT-ON* */ - count = vec_len (table_ids); - vl_api_classify_table_ids_reply_t *rmp; - rmp = vl_msg_api_alloc_as_if_client (sizeof (*rmp) + count * sizeof (u32)); - rmp->_vl_msg_id = ntohs (VL_API_CLASSIFY_TABLE_IDS_REPLY); - rmp->context = mp->context; - rmp->count = ntohl (count); - clib_memcpy (rmp->ids, table_ids, count * sizeof (u32)); - rmp->retval = 0; + vec_sort_with_function(lfeis, fib_entry_cmp_for_sort); - vl_msg_api_send_shmem (q, (u8 *) & rmp); + vec_foreach(lfeip, lfeis) + { + 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); + vec_free(api_rpaths); + } - vec_free (table_ids); + vec_free (lfeis); } static void - vl_api_classify_table_by_interface_t_handler - (vl_api_classify_table_by_interface_t * mp) +vl_api_ip6_fib_details_t_handler (vl_api_ip6_fib_details_t * mp) { - vl_api_classify_table_by_interface_reply_t *rmp; - int rv = 0; + clib_warning ("BUG"); +} + +static void +vl_api_ip6_fib_details_t_endian (vl_api_ip6_fib_details_t * mp) +{ + clib_warning ("BUG"); +} + +static void +vl_api_ip6_fib_details_t_print (vl_api_ip6_fib_details_t * mp) +{ + clib_warning ("BUG"); +} + +static void +send_ip6_fib_details (vpe_api_main_t * am, + unix_shared_memory_queue_t * q, + u32 table_id, fib_prefix_t *pfx, + fib_route_path_encode_t *api_rpaths, u32 context) +{ + vl_api_ip6_fib_details_t *mp; + fib_route_path_encode_t *api_rpath; + vl_api_fib_path_t *fp; + int is_ip4, path_count; + + 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_IP6_FIB_DETAILS); + mp->context = context; + + mp->table_id = htonl (table_id); + mp->address_length = pfx->fp_len; + memcpy(mp->address, &pfx->fp_addr.ip6, sizeof(pfx->fp_addr.ip6)); + + mp->count = htonl (path_count); + fp = mp->path; + vec_foreach(api_rpath, api_rpaths) + { + memset (fp, 0, sizeof (*fp)); + switch (api_rpath->dpo.dpoi_type) + { + case DPO_RECEIVE: + fp->is_local = true; + break; + case DPO_DROP: + fp->is_drop = true; + break; + case DPO_IP_NULL: + switch (api_rpath->dpo.dpoi_index) + { + case IP_NULL_DPO_ACTION_NUM+IP_NULL_ACTION_NONE: + fp->is_drop = true; + break; + case IP_NULL_DPO_ACTION_NUM+IP_NULL_ACTION_SEND_ICMP_UNREACH: + fp->is_unreach = true; + break; + case IP_NULL_DPO_ACTION_NUM+IP_NULL_ACTION_SEND_ICMP_PROHIBIT: + fp->is_prohibit = true; + break; + default: + break; + } + break; + default: + break; + } + fp->weight = htonl(api_rpath->rpath.frp_weight); + fp->sw_if_index = htonl(api_rpath->rpath.frp_sw_if_index); + memcpy(fp->next_hop, &api_rpath->rpath.frp_addr, sizeof(fp->next_hop)); + if (api_rpath->rpath.frp_proto == FIB_PROTOCOL_IP4) + fp->afi = IP46_TYPE_IP4; + else if (api_rpath->rpath.frp_proto == FIB_PROTOCOL_IP6) + fp->afi = IP46_TYPE_IP6; + else + { + 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; + } + fp++; + } + + vl_msg_api_send_shmem (q, (u8 *) & mp); +} + +typedef struct apt_ip6_fib_show_ctx_t_ { + u32 fib_index; + fib_node_index_t *entries; +} api_ip6_fib_show_ctx_t; + +static void +api_ip6_fib_table_put_entries (clib_bihash_kv_24_8_t * kvp, + void *arg) +{ + api_ip6_fib_show_ctx_t *ctx = arg; + + if ((kvp->key[2] >> 32) == ctx->fib_index) + { + vec_add1(ctx->entries, kvp->value); + } +} + +static void +api_ip6_fib_table_get_all (unix_shared_memory_queue_t *q, + vl_api_ip6_fib_dump_t *mp, + fib_table_t *fib_table) +{ + 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_route_path_encode_t *api_rpaths; + fib_prefix_t pfx; + + BV(clib_bihash_foreach_key_value_pair) + ((BVT(clib_bihash) *) &im6->ip6_table[IP6_FIB_TABLE_NON_FWDING].ip6_hash, + api_ip6_fib_table_put_entries, + &ctx); + + vec_sort_with_function(ctx.entries, fib_entry_cmp_for_sort); + + vec_foreach(fib_entry_index, ctx.entries) + { + fib_entry_get_prefix(*fib_entry_index, &pfx); + api_rpaths = NULL; + fib_entry_encode(*fib_entry_index, &api_rpaths); + send_ip6_fib_details (am, q, + fib_table->ft_table_id, + &pfx, + api_rpaths, + mp->context); + vec_free(api_rpaths); + } + + vec_free(ctx.entries); +} + +static void +vl_api_ip6_fib_dump_t_handler (vl_api_ip6_fib_dump_t * mp) +{ + unix_shared_memory_queue_t *q; + ip6_main_t *im6 = &ip6_main; + fib_table_t *fib_table; + + q = vl_api_client_index_to_input_queue (mp->client_index); + if (q == 0) + return; + + /* *INDENT-OFF* */ + pool_foreach (fib_table, im6->fibs, + ({ + api_ip6_fib_table_get_all(q, mp, fib_table); + })); +} + +static void +vl_api_mpls_fib_encap_details_t_handler (vl_api_mpls_fib_encap_details_t * mp) +{ + clib_warning ("BUG"); +} + +static void +send_mpls_fib_encap_details (vpe_api_main_t * am, + unix_shared_memory_queue_t * q, + show_mpls_fib_t * s, u32 context) +{ + vl_api_mpls_fib_encap_details_t *mp; + mpls_main_t *mm = &mpls_main; + mpls_encap_t *e; + int i; + u32 nlabels; + + e = pool_elt_at_index (mm->encaps, s->entry_index); + nlabels = vec_len (e->labels); + + mp = vl_msg_api_alloc (sizeof (*mp) + nlabels * sizeof (u32)); + memset (mp, 0, sizeof (*mp)); + mp->_vl_msg_id = ntohs (VL_API_MPLS_FIB_ENCAP_DETAILS); + mp->context = context; + + mp->fib_index = htonl (s->fib_index); + mp->entry_index = htonl (s->entry_index); + mp->dest = s->dest; + mp->s_bit = htonl (s->s_bit); + + mp->nlabels = htonl (nlabels); + + for (i = 0; i < nlabels; i++) + { + mp->labels[i] = + htonl (vnet_mpls_uc_get_label + (clib_host_to_net_u32 (e->labels[i].label_exp_s_ttl))); + } + + vl_msg_api_send_shmem (q, (u8 *) & mp); +} + +static void +vl_api_mpls_fib_encap_dump_t_handler (vl_api_mpls_fib_encap_dump_t * mp) +{ + vpe_api_main_t *am = &vpe_api_main; + unix_shared_memory_queue_t *q; + vlib_main_t *vm = &vlib_global_main; + u64 key; + u32 value; + show_mpls_fib_t *records = 0; + show_mpls_fib_t *s; + mpls_main_t *mm = &mpls_main; + ip4_fib_t *rx_fib; + + q = vl_api_client_index_to_input_queue (mp->client_index); + if (q == 0) + return; + + /* *INDENT-OFF* */ + hash_foreach (key, value, mm->mpls_encap_by_fib_and_dest, + ({ + vec_add2 (records, s, 1); + s->fib_index = (u32)(key>>32); + s->dest = (u32)(key & 0xFFFFFFFF); + s->entry_index = (u32) value; + })); + /* *INDENT-ON* */ + + if (0 == vec_len (records)) + { + vlib_cli_output (vm, "MPLS encap table empty"); + goto out; + } + + /* sort output by dst address within fib */ + vec_sort_with_function (records, mpls_dest_cmp); + vec_sort_with_function (records, mpls_fib_index_cmp); + vlib_cli_output (vm, "MPLS encap table"); + vlib_cli_output (vm, "%=6s%=16s%=16s", "Table", "Dest address", "Labels"); + vec_foreach (s, records) + { + rx_fib = ip4_fib_get (s->fib_index); + vlib_cli_output (vm, "%=6d%=16U%=16U", rx_fib->table_id, + format_ip4_address, &s->dest, format_mpls_encap_index, + mm, s->entry_index); + send_mpls_fib_encap_details (am, q, s, mp->context); + } + +out: + vec_free (records); +} + +static void +vl_api_classify_table_ids_t_handler (vl_api_classify_table_ids_t * mp) +{ + unix_shared_memory_queue_t *q; + + q = vl_api_client_index_to_input_queue (mp->client_index); + if (q == 0) + return; + + vnet_classify_main_t *cm = &vnet_classify_main; + vnet_classify_table_t *t; + u32 *table_ids = 0; + u32 count; + + /* *INDENT-OFF* */ + pool_foreach (t, cm->tables, + ({ + vec_add1 (table_ids, ntohl(t - cm->tables)); + })); + /* *INDENT-ON* */ + count = vec_len (table_ids); + + vl_api_classify_table_ids_reply_t *rmp; + rmp = vl_msg_api_alloc_as_if_client (sizeof (*rmp) + count * sizeof (u32)); + rmp->_vl_msg_id = ntohs (VL_API_CLASSIFY_TABLE_IDS_REPLY); + rmp->context = mp->context; + rmp->count = ntohl (count); + clib_memcpy (rmp->ids, table_ids, count * sizeof (u32)); + rmp->retval = 0; + + vl_msg_api_send_shmem (q, (u8 *) & rmp); + + vec_free (table_ids); +} + +static void + vl_api_classify_table_by_interface_t_handler + (vl_api_classify_table_by_interface_t * mp) +{ + vl_api_classify_table_by_interface_reply_t *rmp; + int rv = 0; u32 sw_if_index = ntohl (mp->sw_if_index); u32 *acl = 0; @@ -7623,6 +8266,8 @@ vl_api_classify_session_dump_t_handler (vl_api_classify_session_dump_t * mp) vnet_classify_table_t *t; q = vl_api_client_index_to_input_queue (mp->client_index); + if (!q) + return; /* *INDENT-OFF* */ pool_foreach (t, cm->tables, @@ -7662,15 +8307,16 @@ vl_api_classify_session_dump_t_handler (vl_api_classify_session_dump_t * mp) } static void -vl_api_ipfix_enable_t_handler (vl_api_ipfix_enable_t * mp) +vl_api_set_ipfix_exporter_t_handler (vl_api_set_ipfix_exporter_t * mp) { vlib_main_t *vm = vlib_get_main (); flow_report_main_t *frm = &flow_report_main; - vl_api_ipfix_enable_reply_t *rmp; + vl_api_set_ipfix_exporter_reply_t *rmp; ip4_address_t collector, src; u16 collector_port = UDP_DST_PORT_ipfix; u32 path_mtu; u32 template_interval; + u8 udp_checksum; u32 fib_id; u32 fib_index = ~0; int rv = 0; @@ -7683,13 +8329,20 @@ vl_api_ipfix_enable_t_handler (vl_api_ipfix_enable_t * mp) fib_id = ntohl (mp->vrf_id); ip4_main_t *im = &ip4_main; - uword *p = hash_get (im->fib_index_by_table_id, fib_id); - if (!p) + if (fib_id == ~0) { - rv = VNET_API_ERROR_NO_SUCH_FIB; - goto out; + fib_index = ~0; + } + else + { + uword *p = hash_get (im->fib_index_by_table_id, fib_id); + if (!p) + { + rv = VNET_API_ERROR_NO_SUCH_FIB; + goto out; + } + fib_index = p[0]; } - fib_index = p[0]; path_mtu = ntohl (mp->path_mtu); if (path_mtu == ~0) @@ -7697,6 +8350,7 @@ vl_api_ipfix_enable_t_handler (vl_api_ipfix_enable_t * mp) template_interval = ntohl (mp->template_interval); if (template_interval == ~0) template_interval = 20; + udp_checksum = mp->udp_checksum; if (collector.as_u32 == 0) { @@ -7734,20 +8388,23 @@ vl_api_ipfix_enable_t_handler (vl_api_ipfix_enable_t * mp) frm->fib_index = fib_index; frm->path_mtu = path_mtu; frm->template_interval = template_interval; + frm->udp_checksum = udp_checksum; /* Turn on the flow reporting process */ vlib_process_signal_event (vm, flow_report_process_node.index, 1, 0); out: - REPLY_MACRO (VL_API_IPFIX_ENABLE_REPLY); + REPLY_MACRO (VL_API_SET_IPFIX_EXPORTER_REPLY); } static void -vl_api_ipfix_dump_t_handler (vl_api_ipfix_dump_t * mp) +vl_api_ipfix_exporter_dump_t_handler (vl_api_ipfix_exporter_dump_t * mp) { flow_report_main_t *frm = &flow_report_main; unix_shared_memory_queue_t *q; - vl_api_ipfix_details_t *rmp; + vl_api_ipfix_exporter_details_t *rmp; + ip4_main_t *im = &ip4_main; + u32 vrf_id; q = vl_api_client_index_to_input_queue (mp->client_index); if (!q) @@ -7755,20 +8412,234 @@ vl_api_ipfix_dump_t_handler (vl_api_ipfix_dump_t * mp) rmp = vl_msg_api_alloc (sizeof (*rmp)); memset (rmp, 0, sizeof (*rmp)); - rmp->_vl_msg_id = ntohs (VL_API_IPFIX_DETAILS); + rmp->_vl_msg_id = ntohs (VL_API_IPFIX_EXPORTER_DETAILS); rmp->context = mp->context; memcpy (rmp->collector_address, frm->ipfix_collector.data, sizeof (frm->ipfix_collector.data)); rmp->collector_port = htons (frm->collector_port); memcpy (rmp->src_address, frm->src_address.data, sizeof (frm->src_address.data)); - rmp->fib_index = htonl (frm->fib_index); + if (frm->fib_index == ~0) + vrf_id = ~0; + else + vrf_id = im->fibs[frm->fib_index].ft_table_id; + rmp->vrf_id = htonl (vrf_id); rmp->path_mtu = htonl (frm->path_mtu); rmp->template_interval = htonl (frm->template_interval); + rmp->udp_checksum = (frm->udp_checksum != 0); vl_msg_api_send_shmem (q, (u8 *) & rmp); } +static void + vl_api_set_ipfix_classify_stream_t_handler + (vl_api_set_ipfix_classify_stream_t * mp) +{ + vl_api_set_ipfix_classify_stream_reply_t *rmp; + flow_report_classify_main_t *fcm = &flow_report_classify_main; + flow_report_main_t *frm = &flow_report_main; + u32 domain_id = 0; + u32 src_port = UDP_DST_PORT_ipfix; + int rv = 0; + + domain_id = ntohl (mp->domain_id); + src_port = ntohs (mp->src_port); + + if (fcm->src_port != 0 && + (fcm->domain_id != domain_id || fcm->src_port != (u16) src_port)) + { + int rv = vnet_stream_change (frm, fcm->domain_id, fcm->src_port, + domain_id, (u16) src_port); + ASSERT (rv == 0); + } + + fcm->domain_id = domain_id; + fcm->src_port = (u16) src_port; + + REPLY_MACRO (VL_API_SET_IPFIX_CLASSIFY_STREAM_REPLY); +} + +static void + vl_api_ipfix_classify_stream_dump_t_handler + (vl_api_ipfix_classify_stream_dump_t * mp) +{ + flow_report_classify_main_t *fcm = &flow_report_classify_main; + unix_shared_memory_queue_t *q; + vl_api_ipfix_classify_stream_details_t *rmp; + + q = vl_api_client_index_to_input_queue (mp->client_index); + if (!q) + return; + + rmp = vl_msg_api_alloc (sizeof (*rmp)); + memset (rmp, 0, sizeof (*rmp)); + rmp->_vl_msg_id = ntohs (VL_API_IPFIX_CLASSIFY_STREAM_DETAILS); + rmp->context = mp->context; + rmp->domain_id = htonl (fcm->domain_id); + rmp->src_port = htons (fcm->src_port); + + vl_msg_api_send_shmem (q, (u8 *) & rmp); +} + +static void + vl_api_ipfix_classify_table_add_del_t_handler + (vl_api_ipfix_classify_table_add_del_t * mp) +{ + vl_api_ipfix_classify_table_add_del_reply_t *rmp; + flow_report_classify_main_t *fcm = &flow_report_classify_main; + flow_report_main_t *frm = &flow_report_main; + vnet_flow_report_add_del_args_t args; + ipfix_classify_table_t *table; + int is_add; + u32 classify_table_index; + u8 ip_version; + u8 transport_protocol; + int rv = 0; + + classify_table_index = ntohl (mp->table_id); + ip_version = mp->ip_version; + transport_protocol = mp->transport_protocol; + is_add = mp->is_add; + + if (fcm->src_port == 0) + { + /* call set_ipfix_classify_stream first */ + rv = VNET_API_ERROR_UNSPECIFIED; + goto out; + } + + memset (&args, 0, sizeof (args)); + + table = 0; + int i; + for (i = 0; i < vec_len (fcm->tables); i++) + if (ipfix_classify_table_index_valid (i)) + if (fcm->tables[i].classify_table_index == classify_table_index) + { + table = &fcm->tables[i]; + break; + } + + if (is_add) + { + if (table) + { + rv = VNET_API_ERROR_VALUE_EXIST; + goto out; + } + table = ipfix_classify_add_table (); + table->classify_table_index = classify_table_index; + } + else + { + if (!table) + { + rv = VNET_API_ERROR_NO_SUCH_ENTRY; + goto out; + } + } + + table->ip_version = ip_version; + table->transport_protocol = transport_protocol; + + args.opaque.as_uword = table - fcm->tables; + args.rewrite_callback = ipfix_classify_template_rewrite; + args.flow_data_callback = ipfix_classify_send_flows; + args.is_add = is_add; + args.domain_id = fcm->domain_id; + args.src_port = fcm->src_port; + + rv = vnet_flow_report_add_del (frm, &args); + + /* If deleting, or add failed */ + if (is_add == 0 || (rv && is_add)) + ipfix_classify_delete_table (table - fcm->tables); + +out: + REPLY_MACRO (VL_API_SET_IPFIX_CLASSIFY_STREAM_REPLY); +} + +static void +send_ipfix_classify_table_details (u32 table_index, + unix_shared_memory_queue_t * q, + u32 context) +{ + flow_report_classify_main_t *fcm = &flow_report_classify_main; + vl_api_ipfix_classify_table_details_t *mp; + + ipfix_classify_table_t *table = &fcm->tables[table_index]; + + mp = vl_msg_api_alloc (sizeof (*mp)); + memset (mp, 0, sizeof (*mp)); + mp->_vl_msg_id = ntohs (VL_API_IPFIX_CLASSIFY_TABLE_DETAILS); + mp->context = context; + mp->table_id = htonl (table->classify_table_index); + mp->ip_version = table->ip_version; + mp->transport_protocol = table->transport_protocol; + + vl_msg_api_send_shmem (q, (u8 *) & mp); +} + +static void + vl_api_ipfix_classify_table_dump_t_handler + (vl_api_ipfix_classify_table_dump_t * mp) +{ + flow_report_classify_main_t *fcm = &flow_report_classify_main; + unix_shared_memory_queue_t *q; + u32 i; + + q = vl_api_client_index_to_input_queue (mp->client_index); + if (!q) + return; + + for (i = 0; i < vec_len (fcm->tables); i++) + if (ipfix_classify_table_index_valid (i)) + send_ipfix_classify_table_details (i, q, mp->context); +} + +static void + vl_api_sw_interface_span_enable_disable_t_handler + (vl_api_sw_interface_span_enable_disable_t * mp) +{ + vl_api_sw_interface_span_enable_disable_reply_t *rmp; + int rv; + + vlib_main_t *vm = vlib_get_main (); + + rv = span_add_delete_entry (vm, ntohl (mp->sw_if_index_from), + ntohl (mp->sw_if_index_to), mp->enable); + + REPLY_MACRO (VL_API_SW_INTERFACE_SPAN_ENABLE_DISABLE_REPLY); +} + +static void +vl_api_sw_interface_span_dump_t_handler (vl_api_sw_interface_span_dump_t * mp) +{ + + unix_shared_memory_queue_t *q; + vl_api_sw_interface_span_details_t *rmp; + span_main_t *sm = &span_main; + u32 src_sw_if_index = 0, *dst_sw_if_index; + + q = vl_api_client_index_to_input_queue (mp->client_index); + vec_foreach (dst_sw_if_index, sm->dst_by_src_sw_if_index) + { + if (*dst_sw_if_index > 0) + { + rmp = vl_msg_api_alloc (sizeof (*rmp)); + memset (rmp, 0, sizeof (*rmp)); + rmp->_vl_msg_id = ntohs (VL_API_SW_INTERFACE_SPAN_DETAILS); + rmp->context = mp->context; + + rmp->sw_if_index_from = htonl (src_sw_if_index); + rmp->sw_if_index_to = htonl (*dst_sw_if_index); + + vl_msg_api_send_shmem (q, (u8 *) & rmp); + } + src_sw_if_index++; + } +} + static void vl_api_pg_create_interface_t_handler (vl_api_pg_create_interface_t * mp) { @@ -7776,12 +8647,13 @@ vl_api_pg_create_interface_t_handler (vl_api_pg_create_interface_t * mp) int rv = 0; pg_main_t *pg = &pg_main; - u32 sw_if_index = pg_interface_add_or_get (pg, ntohl (mp->interface_id)); + u32 pg_if_id = pg_interface_add_or_get (pg, ntohl (mp->interface_id)); + pg_interface_t *pi = pool_elt_at_index (pg->interfaces, pg_if_id); /* *INDENT-OFF* */ REPLY_MACRO2(VL_API_PG_CREATE_INTERFACE_REPLY, ({ - rmp->sw_if_index = ntohl(sw_if_index); + rmp->sw_if_index = ntohl(pi->sw_if_index); })); /* *INDENT-ON* */ } @@ -8089,6 +8961,215 @@ static void vl_api_ipsec_gre_tunnel_dump_t_handler } } +static void +vl_api_delete_subif_t_handler (vl_api_delete_subif_t * mp) +{ + vl_api_delete_subif_reply_t *rmp; + int rv; + + rv = vnet_delete_sub_interface (ntohl (mp->sw_if_index)); + + REPLY_MACRO (VL_API_DELETE_SUBIF_REPLY); +} + +static void + vl_api_l2_interface_pbb_tag_rewrite_t_handler + (vl_api_l2_interface_pbb_tag_rewrite_t * mp) +{ + vl_api_l2_interface_pbb_tag_rewrite_reply_t *rmp; + vnet_main_t *vnm = vnet_get_main (); + vlib_main_t *vm = vlib_get_main (); + u32 vtr_op; + int rv = 0; + + VALIDATE_SW_IF_INDEX (mp); + + vtr_op = ntohl (mp->vtr_op); + + switch (vtr_op) + { + case L2_VTR_DISABLED: + case L2_VTR_PUSH_2: + case L2_VTR_POP_2: + case L2_VTR_TRANSLATE_2_1: + break; + + default: + rv = VNET_API_ERROR_INVALID_VALUE; + goto bad_sw_if_index; + } + + rv = l2pbb_configure (vm, vnm, ntohl (mp->sw_if_index), vtr_op, + mp->b_dmac, mp->b_smac, ntohs (mp->b_vlanid), + ntohl (mp->i_sid), ntohs (mp->outer_tag)); + + BAD_SW_IF_INDEX_LABEL; + + REPLY_MACRO (VL_API_L2_INTERFACE_PBB_TAG_REWRITE_REPLY); +} + +static void +vl_api_punt_t_handler (vl_api_punt_t * mp) +{ + vl_api_punt_reply_t *rmp; + vlib_main_t *vm = vlib_get_main (); + int rv = 0; + clib_error_t *error; + + error = vnet_punt_add_del (vm, mp->ipv, mp->l4_protocol, + ntohs (mp->l4_port), mp->is_add); + if (error) + { + rv = -1; + clib_error_report (error); + } + + REPLY_MACRO (VL_API_PUNT_REPLY); +} + +static void + vl_api_flow_classify_set_interface_t_handler + (vl_api_flow_classify_set_interface_t * mp) +{ + vlib_main_t *vm = vlib_get_main (); + vl_api_flow_classify_set_interface_reply_t *rmp; + int rv; + u32 sw_if_index, ip4_table_index, ip6_table_index; + + ip4_table_index = ntohl (mp->ip4_table_index); + ip6_table_index = ntohl (mp->ip6_table_index); + sw_if_index = ntohl (mp->sw_if_index); + + VALIDATE_SW_IF_INDEX (mp); + + rv = vnet_set_flow_classify_intfc (vm, sw_if_index, ip4_table_index, + ip6_table_index, mp->is_add); + + BAD_SW_IF_INDEX_LABEL; + + REPLY_MACRO (VL_API_FLOW_CLASSIFY_SET_INTERFACE_REPLY); +} + +static void +send_flow_classify_details (u32 sw_if_index, + u32 table_index, + unix_shared_memory_queue_t * q, u32 context) +{ + vl_api_flow_classify_details_t *mp; + + mp = vl_msg_api_alloc (sizeof (*mp)); + memset (mp, 0, sizeof (*mp)); + mp->_vl_msg_id = ntohs (VL_API_FLOW_CLASSIFY_DETAILS); + mp->context = context; + mp->sw_if_index = htonl (sw_if_index); + mp->table_index = htonl (table_index); + + vl_msg_api_send_shmem (q, (u8 *) & mp); +} + +static void +vl_api_flow_classify_dump_t_handler (vl_api_flow_classify_dump_t * mp) +{ + unix_shared_memory_queue_t *q; + flow_classify_main_t *pcm = &flow_classify_main; + u32 *vec_tbl; + int i; + + q = vl_api_client_index_to_input_queue (mp->client_index); + if (q == 0) + return; + + vec_tbl = pcm->classify_table_index_by_sw_if_index[mp->type]; + + if (vec_len (vec_tbl)) + { + for (i = 0; i < vec_len (vec_tbl); i++) + { + if (vec_elt (vec_tbl, i) == ~0) + continue; + + send_flow_classify_details (i, vec_elt (vec_tbl, i), q, + mp->context); + } + } +} + +static void +send_ipsec_spd_details (ipsec_policy_t * p, unix_shared_memory_queue_t * q, + u32 context) +{ + vl_api_ipsec_spd_details_t *mp; + + mp = vl_msg_api_alloc (sizeof (*mp)); + memset (mp, 0, sizeof (*mp)); + mp->_vl_msg_id = ntohs (VL_API_IPSEC_SPD_DETAILS); + mp->context = context; + + mp->spd_id = htonl (p->id); + mp->priority = htonl (p->priority); + mp->is_outbound = p->is_outbound; + mp->is_ipv6 = p->is_ipv6; + if (p->is_ipv6) + { + memcpy (mp->local_start_addr, &p->laddr.start.ip6, 16); + memcpy (mp->local_stop_addr, &p->laddr.stop.ip6, 16); + memcpy (mp->remote_start_addr, &p->raddr.start.ip6, 16); + memcpy (mp->remote_stop_addr, &p->raddr.stop.ip6, 16); + } + else + { + memcpy (mp->local_start_addr, &p->laddr.start.ip4, 4); + memcpy (mp->local_stop_addr, &p->laddr.stop.ip4, 4); + memcpy (mp->remote_start_addr, &p->raddr.start.ip4, 4); + memcpy (mp->remote_stop_addr, &p->raddr.stop.ip4, 4); + } + mp->local_start_port = htons (p->lport.start); + mp->local_stop_port = htons (p->lport.stop); + mp->remote_start_port = htons (p->rport.start); + mp->remote_stop_port = htons (p->rport.stop); + mp->protocol = p->protocol; + mp->policy = p->policy; + mp->sa_id = htonl (p->sa_id); + mp->bytes = clib_host_to_net_u64 (p->counter.bytes); + mp->packets = clib_host_to_net_u64 (p->counter.packets); + + vl_msg_api_send_shmem (q, (u8 *) & mp); +} + +static void +vl_api_ipsec_spd_dump_t_handler (vl_api_ipsec_spd_dump_t * mp) +{ + unix_shared_memory_queue_t *q; + ipsec_main_t *im = &ipsec_main; + ipsec_policy_t *policy; + ipsec_spd_t *spd; + uword *p; + u32 spd_index; +#if IPSEC > 0 + q = vl_api_client_index_to_input_queue (mp->client_index); + if (q == 0) + return; + + p = hash_get (im->spd_index_by_spd_id, ntohl (mp->spd_id)); + if (!p) + return; + + spd_index = p[0]; + spd = pool_elt_at_index (im->spds, spd_index); + + pool_foreach (policy, spd->policies, ( + { + if (mp->sa_id == ~(0) + || ntohl (mp->sa_id) == + policy->sa_id) + send_ipsec_spd_details (policy, q, + mp->context);} + )); +#else + clib_warning ("unimplemented"); +#endif +} + #define BOUNCE_HANDLER(nn) \ static void vl_api_##nn##_t_handler ( \ vl_api_##nn##_t *mp) \ @@ -8356,28 +9437,50 @@ format_arp_event (u8 * s, va_list * args) { vl_api_ip4_arp_event_t *event = va_arg (*args, vl_api_ip4_arp_event_t *); - s = format (s, "pid %d: %U", event->pid, - format_ip4_address, &event->address); + s = format (s, "pid %d: ", event->pid); + if (event->mac_ip) + s = format (s, "bd mac/ip4 binding events"); + else + s = format (s, "resolution for %U", format_ip4_address, &event->address); + return s; +} + +static u8 * +format_nd_event (u8 * s, va_list * args) +{ + vl_api_ip6_nd_event_t *event = va_arg (*args, vl_api_ip6_nd_event_t *); + + s = format (s, "pid %d: ", event->pid); + if (event->mac_ip) + s = format (s, "bd mac/ip6 binding events"); + else + s = format (s, "resolution for %U", format_ip6_address, event->address); return s; } static clib_error_t * -show_ip4_arp_events_fn (vlib_main_t * vm, - unformat_input_t * input, vlib_cli_command_t * cmd) +show_ip_arp_nd_events_fn (vlib_main_t * vm, + unformat_input_t * input, vlib_cli_command_t * cmd) { vpe_api_main_t *am = &vpe_api_main; - vl_api_ip4_arp_event_t *event; + vl_api_ip4_arp_event_t *arp_event; + vl_api_ip6_nd_event_t *nd_event; - if (pool_elts (am->arp_events) == 0) + if ((pool_elts (am->arp_events) == 0) && (pool_elts (am->nd_events) == 0)) { - vlib_cli_output (vm, "No active arp event registrations"); + vlib_cli_output (vm, "No active arp or nd event registrations"); return 0; } /* *INDENT-OFF* */ - pool_foreach (event, am->arp_events, + pool_foreach (arp_event, am->arp_events, + ({ + vlib_cli_output (vm, "%U", format_arp_event, arp_event); + })); + + pool_foreach (nd_event, am->nd_events, ({ - vlib_cli_output (vm, "%U", format_arp_event, event); + vlib_cli_output (vm, "%U", format_nd_event, nd_event); })); /* *INDENT-ON* */ @@ -8385,10 +9488,10 @@ show_ip4_arp_events_fn (vlib_main_t * vm, } /* *INDENT-OFF* */ -VLIB_CLI_COMMAND (show_ip4_arp_events, static) = { - .path = "show arp event registrations", - .function = show_ip4_arp_events_fn, - .short_help = "Show arp event registrations", +VLIB_CLI_COMMAND (show_ip_arp_nd_events, static) = { + .path = "show arp-nd-event registrations", + .function = show_ip_arp_nd_events_fn, + .short_help = "Show ip4 arp and ip6 nd event registrations", }; /* *INDENT-ON* */