/* * Copyright (c) 2017-2019 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include #include #include #include #define __plugin_msg_base hicn_test_main.msg_id_base #include #include #include "error.h" // uword unformat_sw_if_index(unformat_input_t * input, va_list * args); /* Declare message IDs */ #include "hicn_msg_enum.h" /* define message structures */ #define vl_typedefs #include #include #undef vl_typedefs /* Get CRC codes of the messages defined outside of this plugin */ #define vl_msg_name_crc_list #include #undef vl_msg_name_crc_list /* declare message handlers for each api */ #define vl_endianfun /* define message structures */ #include "hicn_all_api_h.h" #undef vl_endianfun /* instantiate all the print functions we know about */ #define vl_print(handle, ...) #define vl_printfun #include "hicn_all_api_h.h" #undef vl_printfun /* Get the API version number. */ #define vl_api_version(n, v) static u32 api_version=(v); #include "hicn_all_api_h.h" #undef vl_api_version /* SUPPORTING FUNCTIONS NOT LOADED BY VPP_API_TEST */ uword unformat_ip46_address (unformat_input_t * input, va_list * args) { ip46_address_t *ip46 = va_arg (*args, ip46_address_t *); ip46_type_t type = va_arg (*args, ip46_type_t); if ((type != IP46_TYPE_IP6) && unformat (input, "%U", unformat_ip4_address, &ip46->ip4)) { ip46_address_mask_ip4 (ip46); return 1; } else if ((type != IP46_TYPE_IP4) && unformat (input, "%U", unformat_ip6_address, &ip46->ip6)) { return 1; } return 0; } static ip46_type_t ip_address_union_decode (const vl_api_address_union_t * in, vl_api_address_family_t af, ip46_address_t * out) { ip46_type_t type; switch (clib_net_to_host_u32 (af)) { case ADDRESS_IP4: clib_memset (out, 0, sizeof (*out)); clib_memcpy (&out->ip4, &in->ip4, sizeof (out->ip4)); type = IP46_TYPE_IP4; break; case ADDRESS_IP6: clib_memcpy (&out->ip6, &in->ip6, sizeof (out->ip6)); type = IP46_TYPE_IP6; break; default: ASSERT (!"Unkown address family in API address type"); type = IP46_TYPE_ANY; break; } return type; } void ip6_address_encode (const ip6_address_t * in, vl_api_ip6_address_t out) { clib_memcpy (out, in, sizeof (*in)); } void ip6_address_decode (const vl_api_ip6_address_t in, ip6_address_t * out) { clib_memcpy (out, in, sizeof (*out)); } void ip4_address_encode (const ip4_address_t * in, vl_api_ip4_address_t out) { clib_memcpy (out, in, sizeof (*in)); } void ip4_address_decode (const vl_api_ip4_address_t in, ip4_address_t * out) { clib_memcpy (out, in, sizeof (*out)); } static void ip_address_union_encode (const ip46_address_t * in, vl_api_address_family_t af, vl_api_address_union_t * out) { if (ADDRESS_IP6 == clib_net_to_host_u32 (af)) ip6_address_encode (&in->ip6, out->ip6); else ip4_address_encode (&in->ip4, out->ip4); } ip46_type_t ip_address_decode (const vl_api_address_t * in, ip46_address_t * out) { return (ip_address_union_decode (&in->un, in->af, out)); } void ip_address_encode (const ip46_address_t * in, ip46_type_t type, vl_api_address_t * out) { switch (type) { case IP46_TYPE_IP4: out->af = clib_net_to_host_u32 (ADDRESS_IP4); break; case IP46_TYPE_IP6: out->af = clib_net_to_host_u32 (ADDRESS_IP6); break; case IP46_TYPE_ANY: if (ip46_address_is_ip4 (in)) out->af = clib_net_to_host_u32 (ADDRESS_IP4); else out->af = clib_net_to_host_u32 (ADDRESS_IP6); break; } ip_address_union_encode (in, out->af, &out->un); } fib_protocol_t fib_proto_from_ip46 (ip46_type_t iproto) { switch (iproto) { case IP46_TYPE_IP4: return FIB_PROTOCOL_IP4; case IP46_TYPE_IP6: return FIB_PROTOCOL_IP6; case IP46_TYPE_ANY: ASSERT (0); return FIB_PROTOCOL_IP4; } ASSERT (0); return FIB_PROTOCOL_IP4; } ip46_type_t fib_proto_to_ip46 (fib_protocol_t fproto) { switch (fproto) { case FIB_PROTOCOL_IP4: return (IP46_TYPE_IP4); case FIB_PROTOCOL_IP6: return (IP46_TYPE_IP6); case FIB_PROTOCOL_MPLS: return (IP46_TYPE_ANY); } ASSERT (0); return (IP46_TYPE_ANY); } void ip_prefix_decode (const vl_api_prefix_t * in, fib_prefix_t * out) { switch (clib_net_to_host_u32 (in->address.af)) { case ADDRESS_IP4: out->fp_proto = FIB_PROTOCOL_IP4; break; case ADDRESS_IP6: out->fp_proto = FIB_PROTOCOL_IP6; break; } out->fp_len = in->len; out->___fp___pad = 0; ip_address_decode (&in->address, &out->fp_addr); } void ip_prefix_encode (const fib_prefix_t * in, vl_api_prefix_t * out) { out->len = in->fp_len; ip_address_encode (&in->fp_addr, fib_proto_to_ip46 (in->fp_proto), &out->address); } ///////////////////////////////////////////////////// #define HICN_FACE_NULL ~0 typedef struct { /* API message ID base */ u16 msg_id_base; vat_main_t *vat_main; u32 ping_id; } hicn_test_main_t; hicn_test_main_t hicn_test_main; #define foreach_standard_reply_retval_handler \ _(hicn_api_node_params_set_reply) \ _(hicn_api_face_ip_del_reply) \ _(hicn_api_face_del_reply) \ _(hicn_api_route_nhops_add_reply) \ _(hicn_api_route_del_reply) \ _(hicn_api_route_nhop_del_reply) \ _(hicn_api_punting_add_reply) \ _(hicn_api_face_cons_del_reply) \ _(hicn_api_face_prod_del_reply) #define _(n) \ static void vl_api_##n##_t_handler \ (vl_api_##n##_t * mp) \ { \ vat_main_t * vam = hicn_test_main.vat_main; \ i32 retval = ntohl(mp->retval); \ if (vam->async_mode) { \ vam->async_errors += (retval < 0); \ } else { \ fformat (vam->ofp,"%s\n", get_error_string(retval));\ vam->retval = retval; \ vam->result_ready = 1; \ } \ } foreach_standard_reply_retval_handler; #undef _ /* * Table of message reply handlers, must include boilerplate handlers we just * generated */ #define foreach_vpe_api_reply_msg \ _(HICN_API_NODE_PARAMS_SET_REPLY, hicn_api_node_params_set_reply) \ _(HICN_API_NODE_PARAMS_GET_REPLY, hicn_api_node_params_get_reply) \ _(HICN_API_NODE_STATS_GET_REPLY, hicn_api_node_stats_get_reply) \ _(HICN_API_FACE_IP_DEL_REPLY, hicn_api_face_ip_del_reply) \ _(HICN_API_FACE_IP_ADD_REPLY, hicn_api_face_ip_add_reply) \ _(HICN_API_FACE_ADD_REPLY, hicn_api_face_add_reply) \ _(HICN_API_FACE_DEL_REPLY, hicn_api_face_del_reply) \ _(HICN_API_FACE_GET_REPLY, hicn_api_face_get_reply) \ _(HICN_API_FACES_DETAILS, hicn_api_faces_details) \ _(HICN_API_FACE_STATS_DETAILS, hicn_api_face_stats_details) \ _(HICN_API_ROUTE_NHOPS_ADD_REPLY, hicn_api_route_nhops_add_reply) \ _(HICN_API_FACE_IP_PARAMS_GET_REPLY, hicn_api_face_ip_params_get_reply) \ _(HICN_API_ROUTE_GET_REPLY, hicn_api_route_get_reply) \ _(HICN_API_ROUTES_DETAILS, hicn_api_routes_details) \ _(HICN_API_ROUTE_DEL_REPLY, hicn_api_route_del_reply) \ _(HICN_API_ROUTE_NHOP_DEL_REPLY, hicn_api_route_nhop_del_reply) \ _(HICN_API_STRATEGIES_GET_REPLY, hicn_api_strategies_get_reply) \ _(HICN_API_STRATEGY_GET_REPLY, hicn_api_strategy_get_reply) \ _(HICN_API_PUNTING_ADD_REPLY, hicn_api_punting_add_reply) \ _(HICN_API_REGISTER_PROD_APP_REPLY, hicn_api_register_prod_app_reply) \ _(HICN_API_FACE_PROD_DEL_REPLY, hicn_api_face_prod_del_reply) \ _(HICN_API_REGISTER_CONS_APP_REPLY, hicn_api_register_cons_app_reply) \ _(HICN_API_FACE_CONS_DEL_REPLY, hicn_api_face_cons_del_reply) static int api_hicn_api_node_params_set (vat_main_t * vam) { unformat_input_t *input = vam->input; int enable_disable = 1; int pit_size = -1, cs_size = -1; f64 pit_max_lifetime_sec = -1.0f; int ret; vl_api_hicn_api_node_params_set_t *mp; /* Parse args required to build the message */ while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { if (unformat (input, "disable")) { enable_disable = 0; } else if (unformat (input, "PIT size %d", &pit_size)) {; } else if (unformat (input, "CS size %d", &cs_size)) {; } else if (unformat (input, "PIT maxlife %f", &pit_max_lifetime_sec)) {; } else { break; } } /* Construct the API message */ M (HICN_API_NODE_PARAMS_SET, mp); mp->enable_disable = enable_disable; mp->pit_max_size = clib_host_to_net_i32 (pit_size); mp->cs_max_size = clib_host_to_net_i32 (cs_size); mp->pit_max_lifetime_sec = pit_max_lifetime_sec; /* send it... */ S (mp); /* Wait for a reply... */ W (ret); return ret; } static int api_hicn_api_node_params_get (vat_main_t * vam) { vl_api_hicn_api_node_params_get_t *mp; int ret; //Construct the API message M (HICN_API_NODE_PARAMS_GET, mp); /* send it... */ S (mp); /* Wait for a reply... */ W (ret); return ret; } static void vl_api_hicn_api_node_params_get_reply_t_handler (vl_api_hicn_api_node_params_get_reply_t * mp) { vat_main_t *vam = hicn_test_main.vat_main; i32 retval = ntohl (mp->retval); if (vam->async_mode) { vam->async_errors += (retval < 0); return; } vam->retval = retval; vam->result_ready = 1; if (vam->retval < 0) { //vpp_api_test infra will also print out string form of error fformat (vam->ofp, " (API call error: %d)\n", vam->retval); return; } fformat (vam->ofp, "Enabled %d\n" " Features: cs:%d\n" " PIT size %d\n" " PIT lifetime dflt %.3f, min %.3f, max %.3f\n" " CS size %d\n", mp->is_enabled, mp->feature_cs, clib_net_to_host_u32 (mp->pit_max_size), mp->pit_max_lifetime_sec, clib_net_to_host_u32 (mp->cs_max_size)); } static int api_hicn_api_node_stats_get (vat_main_t * vam) { vl_api_hicn_api_node_stats_get_t *mp; int ret; /* Construct the API message */ M (HICN_API_NODE_STATS_GET, mp); /* send it... */ S (mp); /* Wait for a reply... */ W (ret); return ret; } static void vl_api_hicn_api_node_stats_get_reply_t_handler (vl_api_hicn_api_node_stats_get_reply_t * rmp) { vat_main_t *vam = hicn_test_main.vat_main; i32 retval = ntohl (rmp->retval); if (vam->async_mode) { vam->async_errors += (retval < 0); return; } vam->retval = retval; vam->result_ready = 1; if (vam->retval < 0) { //vpp_api_test infra will also print out string form of error fformat (vam->ofp, " (API call error: %d)\n", vam->retval); return; } else { fformat (vam->ofp, //compare hicn_cli_show_command_fn block:should match " PIT entries (now): %d\n" " CS entries (now): %d\n" " Forwarding statistics:" " pkts_processed: %d\n" " pkts_interest_count: %d\n" " pkts_data_count: %d\n" " pkts_nak_count: %d\n" " pkts_from_cache_count: %d\n" " pkts_nacked_interests_count: %d\n" " pkts_nak_hoplimit_count: %d\n" " pkts_nak_no_route_count: %d\n" " pkts_no_pit_count: %d\n" " pit_expired_count: %d\n" " cs_expired_count: %d\n" " cs_lru_count: %d\n" " pkts_drop_no_buf: %d\n" " interests_aggregated: %d\n" " interests_retransmitted: %d\n", clib_net_to_host_u64 (rmp->pit_entries_count), clib_net_to_host_u64 (rmp->cs_entries_count), clib_net_to_host_u64 (rmp->pkts_processed), clib_net_to_host_u64 (rmp->pkts_interest_count), clib_net_to_host_u64 (rmp->pkts_data_count), clib_net_to_host_u64 (rmp->pkts_from_cache_count), clib_net_to_host_u64 (rmp->pkts_no_pit_count), clib_net_to_host_u64 (rmp->pit_expired_count), clib_net_to_host_u64 (rmp->cs_expired_count), clib_net_to_host_u64 (rmp->cs_lru_count), clib_net_to_host_u64 (rmp->pkts_drop_no_buf), clib_net_to_host_u64 (rmp->interests_aggregated), clib_net_to_host_u64 (rmp->interests_retx)); } } static int api_hicn_api_face_ip_add (vat_main_t * vam) { unformat_input_t *input = vam->input; ip46_address_t local_addr = { 0 }; ip46_address_t remote_addr = { 0 }; int ret = HICN_ERROR_NONE; int sw_if = 0; vl_api_hicn_api_face_add_t *mp; /* Parse args required to build the message */ while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { if (unformat (input, "local %U", unformat_ip46_address, &local_addr, IP46_TYPE_ANY)); else if (unformat (input, "remote %U", unformat_ip46_address, &remote_addr, IP46_TYPE_ANY)); else if (unformat (input, "intfc %d", &sw_if)); else { break; } } /* Check for presence of both addresses */ if (ip46_address_is_zero (&remote_addr)) { clib_warning ("Incomplete IP face. Please specify remote address"); return (1); } /* Construct the API message */ M (HICN_API_FACE_ADD, mp); mp->type = clib_host_to_net_u32(IP_FACE); ip_address_encode (&local_addr, IP46_TYPE_ANY, &mp->face.ip.local_addr); ip_address_encode (&remote_addr, IP46_TYPE_ANY, &mp->face.ip.remote_addr); mp->face.ip.swif = clib_host_to_net_u32 (sw_if); /* send it... */ S (mp); /* Wait for a reply... */ W (ret); return ret; } static void vl_api_hicn_api_face_ip_add_reply_t_handler (vl_api_hicn_api_face_ip_add_reply_t * rmp) { vat_main_t *vam = hicn_test_main.vat_main; i32 retval = ntohl (rmp->retval); if (vam->async_mode) { vam->async_errors += (retval < 0); return; } vam->retval = retval; vam->result_ready = 1; if (vam->retval < 0) { //vpp_api_test infra will also print out string form of error fformat (vam->ofp, " (API call error: %d)\n", vam->retval); return; } fformat (vam->ofp, "New Face ID: %d\n", ntohl (rmp->faceid)); } static int api_hicn_api_face_udp_add (vat_main_t * vam) { unformat_input_t *input = vam->input; ip46_address_t local_addr = ip46_address_initializer; ip46_address_t remote_addr = ip46_address_initializer; u32 sport = 0; u32 dport = 0; int ret = HICN_ERROR_NONE; int sw_if = ~0; vl_api_hicn_api_face_add_t *mp; /* Parse args required to build the message */ while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { if (unformat (input, "local %U port %u", unformat_ip46_address, &local_addr, IP46_TYPE_ANY, &sport)); else if (unformat (input, "remote %U port %u", unformat_ip46_address, &remote_addr, IP46_TYPE_ANY, &dport)); else if (unformat (input, "intfc %d", &sw_if)); else { break; } } /* Check for presence of both addresses */ if (ip46_address_is_zero (&remote_addr) || ip46_address_is_zero (&local_addr) || sport == 0 || dport == 0) { clib_warning ("Incomplete UDP face. Please specify local and remote address and port"); return (1); } /* Construct the API message */ M (HICN_API_FACE_ADD, mp); mp->type = clib_host_to_net_u32(UDP_FACE); ip_address_encode (&local_addr, IP46_TYPE_ANY, &mp->face.udp.local_addr); ip_address_encode (&remote_addr, IP46_TYPE_ANY, &mp->face.udp.remote_addr); mp->face.udp.lport = clib_host_to_net_u16 (sport); mp->face.udp.rport = clib_host_to_net_u16 (dport); mp->face.udp.swif = clib_host_to_net_u32 (sw_if); /* send it... */ S (mp); /* Wait for a reply... */ W (ret); return ret; } static void vl_api_hicn_api_face_add_reply_t_handler (vl_api_hicn_api_face_add_reply_t * rmp) { vat_main_t *vam = hicn_test_main.vat_main; i32 retval = ntohl (rmp->retval); if (vam->async_mode) { vam->async_errors += (retval < 0); return; } vam->retval = retval; vam->result_ready = 1; if (vam->retval < 0) { //vpp_api_test infra will also print out string form of error fformat (vam->ofp, " (API call error: %d)\n", vam->retval); return; } fformat (vam->ofp, "New Face ID: %d\n", ntohl (rmp->faceid)); } static int api_hicn_api_face_ip_del (vat_main_t * vam) { unformat_input_t *input = vam->input; vl_api_hicn_api_face_ip_del_t *mp; u32 faceid = 0, ret; while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { if (unformat (input, "face %d", &faceid)) {; } else { break; } } //Check for presence of face ID if (faceid == ~0) { clib_warning ("Please specify face ID"); return 1; } //Construct the API message M (HICN_API_FACE_IP_DEL, mp); mp->faceid = clib_host_to_net_u32 (faceid); //send it... S (mp); //Wait for a reply... W (ret); return ret; } static int api_hicn_api_face_del (vat_main_t * vam) { unformat_input_t *input = vam->input; vl_api_hicn_api_face_del_t *mp; u32 faceid = 0, ret; while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { if (unformat (input, "face %d", &faceid)) {; } else { break; } } //Check for presence of face ID if (faceid == ~0) { clib_warning ("Please specify face ID"); return 1; } //Construct the API message M (HICN_API_FACE_DEL, mp); mp->faceid = clib_host_to_net_u32 (faceid); //send it... S (mp); //Wait for a reply... W (ret); return ret; } static int api_hicn_api_face_ip_params_get (vat_main_t * vam) { unformat_input_t *input = vam->input; vl_api_hicn_api_face_ip_params_get_t *mp; u32 faceid = HICN_FACE_NULL, ret; while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { if (unformat (input, "face %d", &faceid)) {; } else { break; } } //Check for presence of face ID if (faceid == HICN_FACE_NULL) { clib_warning ("Please specify face ID"); return 1; } //Construct the API message M (HICN_API_FACE_IP_PARAMS_GET, mp); mp->faceid = clib_host_to_net_u32 (faceid); //send it... S (mp); //Wait for a reply... W (ret); return ret; } static void vl_api_hicn_api_face_ip_params_get_reply_t_handler (vl_api_hicn_api_face_ip_params_get_reply_t * rmp) { vat_main_t *vam = hicn_test_main.vat_main; i32 retval = ntohl (rmp->retval); u8 *sbuf = 0; ip46_address_t remote_addr; ip46_address_t local_addr; if (vam->async_mode) { vam->async_errors += (retval < 0); return; } vam->retval = retval; vam->result_ready = 1; if (vam->retval < 0) { //vpp_api_test infra will also print out string form of error fformat (vam->ofp, " (API call error: %d)\n", vam->retval); return; } vec_reset_length (sbuf); ip_address_decode (&rmp->local_addr, &local_addr); ip_address_decode (&rmp->remote_addr, &remote_addr); sbuf = format (0, "local_addr %U remote_addr %U", format_ip46_address, &local_addr, 0 /*IP46_ANY_TYPE */ , format_ip46_address, &remote_addr, 0 /*IP46_ANY_TYPE */ ); fformat (vam->ofp, "%s swif %d flags %d\n", sbuf, clib_net_to_host_u32 (rmp->swif), clib_net_to_host_i32 (rmp->flags)); } static void format_ip_face (vl_api_hicn_face_ip_t * rmp) { vat_main_t *vam = hicn_test_main.vat_main; u8 *sbuf = 0; ip46_address_t remote_addr; ip46_address_t local_addr; vec_reset_length (sbuf); ip_address_decode (&rmp->local_addr, &local_addr); ip_address_decode (&rmp->remote_addr, &remote_addr); sbuf = format (0, "local_addr %U remote_addr %U", format_ip46_address, &local_addr, 0 /*IP46_ANY_TYPE */ , format_ip46_address, &remote_addr, 0 /*IP46_ANY_TYPE */ ); fformat (vam->ofp, "%s swif %d flags %d name %s\n", sbuf, clib_net_to_host_u32 (rmp->swif), clib_net_to_host_i32 (rmp->flags), rmp->if_name); } static void format_udp_face (vl_api_hicn_face_udp_t * rmp) { vat_main_t *vam = hicn_test_main.vat_main; u8 *sbuf = 0; ip46_address_t remote_addr; ip46_address_t local_addr; vec_reset_length (sbuf); ip_address_decode (&rmp->local_addr, &local_addr); ip_address_decode (&rmp->remote_addr, &remote_addr); u16 lport = clib_net_to_host_u16 (rmp->lport); u16 rport = clib_net_to_host_u16 (rmp->rport);; sbuf = format (0, "local_addr %U port %u remote_addr %U port %u", format_ip46_address, &local_addr, 0 /*IP46_ANY_TYPE */ , lport, format_ip46_address, &remote_addr, 0 /*IP46_ANY_TYPE */ , rport); fformat (vam->ofp, "%s swif %d flags %d name %s\n", sbuf, clib_net_to_host_u16 (rmp->swif), clib_net_to_host_i32 (rmp->flags), rmp->if_name); } static int api_hicn_api_faces_dump (vat_main_t * vam) { hicn_test_main_t *hm = &hicn_test_main; vl_api_hicn_api_faces_dump_t *mp; vl_api_control_ping_t *mp_ping; int ret; if (vam->json_output) { clib_warning ("JSON output not supported for faces_dump"); return -99; } M (HICN_API_FACES_DUMP, mp); S (mp); /* Use a control ping for synchronization */ mp_ping = vl_msg_api_alloc_as_if_client (sizeof (*mp_ping)); mp_ping->_vl_msg_id = htons (hm->ping_id); mp_ping->client_index = vam->my_client_index; fformat (vam->ofp, "Sending ping id=%d\n", hm->ping_id); vam->result_ready = 0; S (mp_ping); W (ret); return ret; } static void vl_api_hicn_api_faces_details_t_handler (vl_api_hicn_api_faces_details_t * mp) { if (mp->type == IP_FACE) { format_ip_face (&(mp->face.ip)); } else { format_udp_face (&(mp->face.udp)); } } static int api_hicn_api_face_get (vat_main_t * vam) { unformat_input_t *input = vam->input; vl_api_hicn_api_face_get_t *mp; u32 faceid = HICN_FACE_NULL, ret; while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { if (unformat (input, "face %d", &faceid)) {; } else { break; } } //Check for presence of face ID if (faceid == HICN_FACE_NULL) { clib_warning ("Please specify face ID"); return 1; } //Construct the API message M (HICN_API_FACE_GET, mp); mp->faceid = clib_host_to_net_u32 (faceid); //send it... S (mp); //Wait for a reply... W (ret); return ret; } static void vl_api_hicn_api_face_get_reply_t_handler (vl_api_hicn_api_face_get_reply_t * rmp) { vat_main_t *vam = hicn_test_main.vat_main; i32 retval = ntohl (rmp->retval); if (vam->async_mode) { vam->async_errors += (retval < 0); return; } vam->retval = retval; vam->result_ready = 1; if (vam->retval < 0) { //vpp_api_test infra will also print out string form of error fformat (vam->ofp, " (API call error: %d)\n", vam->retval); return; } if (rmp->type == IP_FACE) { format_ip_face (&(rmp->face.ip)); } else { format_udp_face (&(rmp->face.udp)); } } static int api_hicn_api_face_stats_dump (vat_main_t * vam) { hicn_test_main_t *hm = &hicn_test_main; vl_api_hicn_api_face_stats_dump_t *mp; vl_api_control_ping_t *mp_ping; int ret; if (vam->json_output) { clib_warning ("JSON output not supported for memif_dump"); return -99; } M (HICN_API_FACE_STATS_DUMP, mp); S (mp); /* Use a control ping for synchronization */ mp_ping = vl_msg_api_alloc_as_if_client (sizeof (*mp_ping)); mp_ping->_vl_msg_id = htons (hm->ping_id); mp_ping->client_index = vam->my_client_index; fformat (vam->ofp, "Sending ping id=%d\n", hm->ping_id); vam->result_ready = 0; S (mp_ping); W (ret); return ret; } /* face_stats-details message handler */ static void vl_api_hicn_api_face_stats_details_t_handler (vl_api_hicn_api_face_stats_details_t * mp) { vat_main_t *vam = hicn_test_main.vat_main; fformat (vam->ofp, "face id %d\n" " interest rx packets %16Ld\n" " bytes %16Ld\n" " interest tx packets %16Ld\n" " bytes %16Ld\n" " data rx packets %16Ld\n" " bytes %16Ld\n" " data tx packets %16Ld\n" " bytes %16Ld\n", clib_host_to_net_u32 (mp->faceid), clib_host_to_net_u64 (mp->irx_packets), clib_host_to_net_u64 (mp->irx_bytes), clib_host_to_net_u64 (mp->itx_packets), clib_host_to_net_u64 (mp->itx_bytes), clib_host_to_net_u64 (mp->drx_packets), clib_host_to_net_u64 (mp->drx_bytes), clib_host_to_net_u64 (mp->dtx_packets), clib_host_to_net_u64 (mp->dtx_bytes)); } static int api_hicn_api_route_get (vat_main_t * vam) { unformat_input_t *input = vam->input; vl_api_hicn_api_route_get_t *mp; fib_prefix_t prefix; int ret; while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { if (unformat (input, "prefix %U/%d", unformat_ip46_address, &prefix.fp_addr, IP46_TYPE_ANY, &prefix.fp_len)) {; } else { break; } } /* Check parse */ if (((prefix.fp_addr.as_u64[0] == 0) && (prefix.fp_addr.as_u64[1] == 0)) || (prefix.fp_len == 0)) { clib_warning ("Please specify a valid prefix..."); return 1; } //Construct the API message M (HICN_API_ROUTE_GET, mp); if (!ip46_address_is_ip4 (&(prefix.fp_addr))) prefix.fp_proto = fib_proto_from_ip46 (IP46_TYPE_IP6); ip_prefix_encode (&prefix, &mp->prefix); //send it... S (mp); //Wait for a reply... W (ret); return ret; } static int api_hicn_api_routes_dump (vat_main_t * vam) { hicn_test_main_t *hm = &hicn_test_main; vl_api_hicn_api_route_get_t *mp; vl_api_control_ping_t *mp_ping; int ret; if (vam->json_output) { clib_warning ("JSON output not supported for routes_dump"); return -99; } M (HICN_API_ROUTES_DUMP, mp); S (mp); /* Use a control ping for synchronization */ mp_ping = vl_msg_api_alloc_as_if_client (sizeof (*mp_ping)); mp_ping->_vl_msg_id = htons (hm->ping_id); mp_ping->client_index = vam->my_client_index; fformat (vam->ofp, "Sending ping id=%d\n", hm->ping_id); vam->result_ready = 0; S (mp_ping); W (ret); return ret; } static void vl_api_hicn_api_route_get_reply_t_handler (vl_api_hicn_api_route_get_reply_t * rmp) { vat_main_t *vam = hicn_test_main.vat_main; i32 retval = ntohl (rmp->retval); u8 *sbuf = 0; if (vam->async_mode) { vam->async_errors += (retval < 0); return; } vam->retval = retval; vam->result_ready = 1; if (vam->retval < 0) { //vpp_api_test infra will also print out string form of error fformat (vam->ofp, " (API call error: %d)\n", vam->retval); return; } int i = 0; u8 null_face = 0; u32 faceid; vec_reset_length (sbuf); sbuf = format (sbuf, "Faces: \n"); while (i < 1000 && !null_face) { faceid = clib_net_to_host_u32 (rmp->faceids[i]); if (faceid != HICN_FACE_NULL) { sbuf = format (sbuf, "faceid %d", clib_net_to_host_u32 (rmp->faceids[i])); i++; } else { null_face = 1; } } fformat (vam->ofp, "%s\n Strategy: %d\n", sbuf, clib_net_to_host_u32 (rmp->strategy_id)); } /* face_stats-details message handler */ static void vl_api_hicn_api_routes_details_t_handler (vl_api_hicn_api_routes_details_t * mp) { vat_main_t *vam = hicn_test_main.vat_main; fib_prefix_t prefix; u32 faceid; u8 *sbuf = 0; vec_reset_length (sbuf); ip_prefix_decode (&mp->prefix, &prefix); sbuf = format (sbuf, "Prefix: %U/%u\n", format_ip46_address, &prefix.fp_addr, 0, prefix.fp_len); sbuf = format (sbuf, "Faces: \n"); for (int i = 0; i < mp->nfaces; i++) { faceid = clib_net_to_host_u32 (mp->faceids[i]); sbuf = format (sbuf, " faceid %d\n", faceid); } fformat (vam->ofp, "%sStrategy: %d\n", sbuf, clib_net_to_host_u32 (mp->strategy_id)); } static int api_hicn_api_route_nhops_add (vat_main_t * vam) { unformat_input_t *input = vam->input; vl_api_hicn_api_route_nhops_add_t *mp; fib_prefix_t prefix; u32 faceid = 0; int ret; while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { if (unformat (input, "add prefix %U/%d", unformat_ip46_address, &prefix.fp_addr, IP46_TYPE_ANY, &prefix.fp_len)) {; } else if (unformat (input, "face %d", &faceid)) {; } else { break; } } /* Check parse */ if (((prefix.fp_addr.as_u64[0] == 0) && (prefix.fp_addr.as_u64[1] == 0)) || (prefix.fp_len == 0) || (faceid == 0)) { clib_warning ("Please specify prefix and faceid..."); return 1; } /* Construct the API message */ M (HICN_API_ROUTE_NHOPS_ADD, mp); ip_prefix_encode (&prefix, &mp->prefix); if (!ip46_address_is_ip4 (&(prefix.fp_addr))) prefix.fp_proto = fib_proto_from_ip46 (IP46_TYPE_IP6); mp->face_ids[0] = clib_host_to_net_u32 (faceid); mp->n_faces = 1; /* send it... */ S (mp); /* Wait for a reply... */ W (ret); return ret; } static int api_hicn_api_route_del (vat_main_t * vam) { unformat_input_t *input = vam->input; vl_api_hicn_api_route_del_t *mp; fib_prefix_t prefix; int ret; while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { if (unformat (input, "prefix %U/%d", unformat_ip46_address, &prefix.fp_addr, IP46_TYPE_ANY, &prefix.fp_len)) {; } else { break; } } /* Check parse */ if (((prefix.fp_addr.as_u64[0] == 0) && (prefix.fp_addr.as_u64[1] == 0)) || (prefix.fp_len == 0)) { clib_warning ("Please specify prefix..."); return 1; } /* Construct the API message */ M (HICN_API_ROUTE_DEL, mp); ip_prefix_encode (&prefix, &mp->prefix); if (!ip46_address_is_ip4 (&(prefix.fp_addr))) prefix.fp_proto = fib_proto_from_ip46 (IP46_TYPE_IP6); /* send it... */ S (mp); /* Wait for a reply... */ W (ret); return ret; } static int api_hicn_api_route_nhop_del (vat_main_t * vam) { unformat_input_t *input = vam->input; vl_api_hicn_api_route_nhop_del_t *mp; fib_prefix_t prefix; int faceid = 0, ret; while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { if (unformat (input, "del prefix %U/%d", unformat_ip46_address, &prefix.fp_addr, IP46_TYPE_ANY, &prefix.fp_len)) {; } else if (unformat (input, "face %d", &faceid)) {; } else { break; } } /* Check parse */ if (((prefix.fp_addr.as_u64[0] == 0) && (prefix.fp_addr.as_u64[1] == 0)) || (prefix.fp_len == 0) || (faceid == HICN_FACE_NULL)) { clib_warning ("Please specify prefix and faceid..."); return 1; } /* Construct the API message */ M (HICN_API_ROUTE_NHOP_DEL, mp); ip_prefix_encode (&prefix, &mp->prefix); if (!ip46_address_is_ip4 (&(prefix.fp_addr))) prefix.fp_proto = fib_proto_from_ip46 (IP46_TYPE_IP6); mp->faceid = clib_host_to_net_u32 (faceid); /* send it... */ S (mp); /* Wait for a reply... */ W (ret); return ret; } static int api_hicn_api_strategies_get (vat_main_t * vam) { vl_api_hicn_api_strategies_get_t *mp; int ret; //TODO /* Construct the API message */ M (HICN_API_STRATEGIES_GET, mp); /* send it... */ S (mp); /* Wait for a reply... */ W (ret); return ret; } static void vl_api_hicn_api_strategies_get_reply_t_handler (vl_api_hicn_api_strategies_get_reply_t * mp) { vat_main_t *vam = hicn_test_main.vat_main; i32 retval = ntohl (mp->retval); u8 *sbuf = 0; if (vam->async_mode) { vam->async_errors += (retval < 0); return; } vam->retval = retval; vam->result_ready = 1; if (vam->retval < 0) { //vpp_api_test infra will also print out string form of error fformat (vam->ofp, " (API call error: %d)\n", vam->retval); return; } int n_strategies = clib_net_to_host_i32 (mp->n_strategies); vec_reset_length (sbuf); sbuf = format (sbuf, "Available strategies:\n"); int i; for (i = 0; i < n_strategies; i++) { u32 strategy_id = clib_net_to_host_u32 (mp->strategy_id[i]); sbuf = format (sbuf, "%d ", strategy_id); } fformat (vam->ofp, "%s", sbuf); } static int api_hicn_api_strategy_get (vat_main_t * vam) { unformat_input_t *input = vam->input; vl_api_hicn_api_strategy_get_t *mp; int ret; u32 strategy_id = HICN_STRATEGY_NULL; while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { if (unformat (input, "strategy %d", strategy_id)) {; } else { break; } } if (strategy_id == HICN_STRATEGY_NULL) { clib_warning ("Please specify strategy id..."); return 1; } /* Construct the API message */ M (HICN_API_STRATEGY_GET, mp); mp->strategy_id = clib_host_to_net_u32 (strategy_id); /* send it... */ S (mp); /* Wait for a reply... */ W (ret); return ret; } static void vl_api_hicn_api_strategy_get_reply_t_handler (vl_api_hicn_api_strategy_get_reply_t * mp) { vat_main_t *vam = hicn_test_main.vat_main; i32 retval = ntohl (mp->retval); if (vam->async_mode) { vam->async_errors += (retval < 0); return; } vam->retval = retval; vam->result_ready = 1; if (vam->retval < 0) { //vpp_api_test infra will also print out string form of error fformat (vam->ofp, " (API call error: %d)\n", vam->retval); return; } fformat (vam->ofp, "%s", mp->description); } static int api_hicn_api_ip_punting_add (vat_main_t * vam) { unformat_input_t *input = vam->input; vl_api_hicn_api_punting_add_t *mp; fib_prefix_t prefix; u32 swif = ~0; int ret; while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { if (unformat (input, "prefix %U/%d", unformat_ip46_address, &prefix.fp_addr, IP46_TYPE_ANY, &prefix.fp_len)) {; } else if (unformat (input, "intfc %d", &swif)) {; } else { break; } } /* Check parse */ if (((prefix.fp_addr.as_u64[0] == 0) && (prefix.fp_addr.as_u64[1] == 0)) || (prefix.fp_len == 0)) { clib_warning ("Please specify prefix..."); return 1; } if (swif == ~0) { clib_warning ("Please specify interface..."); return 1; } /* Construct the API message */ M (HICN_API_PUNTING_ADD, mp); mp->type = IP_PUNT; if (!ip46_address_is_ip4 (&(prefix.fp_addr))) { prefix.fp_proto = fib_proto_from_ip46 (IP46_TYPE_IP6); } ip_prefix_encode (&prefix, &mp->rule.ip.prefix); mp->rule.ip.swif = clib_host_to_net_u32 (swif); /* send it... */ S (mp); /* Wait for a reply... */ W (ret); return ret; } static int api_hicn_api_udp_punting_add (vat_main_t * vam) { unformat_input_t *input = vam->input; vl_api_hicn_api_punting_add_t *mp; fib_prefix_t prefix; u32 swif = ~0; u16 sport = 0; u16 dport = 0; vl_api_address_family_t ip_version = ~0; int ret; while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { if (unformat (input, "prefix %U/%d", unformat_ip46_address, &prefix.fp_addr, IP46_TYPE_ANY, &prefix.fp_len)) {; } else if (unformat (input, "sport %u", &sport)); else if (unformat (input, "dport %u", &dport)); else if (unformat (input, "ip4")) { ip_version = ADDRESS_IP4; } else if (unformat (input, "ip6")) { ip_version = ADDRESS_IP6; } else if (unformat (input, "intfc %d", &swif)) {; } else { break; } } /* Check parse */ if (((prefix.fp_addr.as_u64[0] == 0) && (prefix.fp_addr.as_u64[1] == 0)) || (prefix.fp_len == 0)) { clib_warning ("Please specify prefix..."); return 1; } if (swif == ~0) { clib_warning ("Please specify interface..."); return 1; } if (ip_version == ~0) { clib_warning ("Please specify ip version of the udp tunnel..."); return 1; } /* Construct the API message */ M (HICN_API_PUNTING_ADD, mp); mp->type = UDP_PUNT; if (!ip46_address_is_ip4 (&(prefix.fp_addr))) { prefix.fp_proto = fib_proto_from_ip46 (IP46_TYPE_IP6); } ip_prefix_encode (&prefix, &mp->rule.ip.prefix); mp->rule.udp.ip_version = ip_version; mp->rule.udp.swif = clib_host_to_net_u32 (swif); mp->rule.udp.sport = clib_host_to_net_u16 (sport); mp->rule.udp.sport = clib_host_to_net_u16 (dport); /* send it... */ S (mp); /* Wait for a reply... */ W (ret); return ret; } static int api_hicn_api_register_prod_app (vat_main_t * vam) { unformat_input_t *input = vam->input; vl_api_hicn_api_register_prod_app_t *mp; fib_prefix_t prefix; u32 swif = ~0; int ret; while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { if (unformat (input, "prefix %U/%d", unformat_ip46_address, &prefix.fp_addr, IP46_TYPE_ANY, &prefix.fp_len)) {; } else if (unformat (input, "id %d", &swif)) {; } else { break; } } /* Check parse */ if (((prefix.fp_addr.as_u64[0] == 0) && (prefix.fp_addr.as_u64[1] == 0)) || (prefix.fp_len == 0)) { clib_warning ("Please specify prefix..."); return 1; } prefix.fp_proto = ip46_address_is_ip4 (&(prefix.fp_addr)) ? FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6; /* Construct the API message */ M (HICN_API_REGISTER_PROD_APP, mp); ip_prefix_encode (&prefix, &mp->prefix); mp->swif = clib_host_to_net_u32 (swif); /* send it... */ S (mp); /* Wait for a reply... */ W (ret); return ret; } static void vl_api_hicn_api_register_prod_app_reply_t_handler (vl_api_hicn_api_register_prod_app_reply_t * mp) { vat_main_t *vam = hicn_test_main.vat_main; i32 retval = ntohl (mp->retval); if (vam->async_mode) { vam->async_errors += (retval < 0); return; } vam->retval = retval; vam->result_ready = 1; if (vam->retval < 0) { //vpp_api_test infra will also print out string form of error fformat (vam->ofp, " (API call error: %d)\n", vam->retval); return; } } static int api_hicn_api_face_prod_del (vat_main_t * vam) { unformat_input_t *input = vam->input; vl_api_hicn_api_face_prod_del_t *mp; u32 faceid = 0, ret; while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { if (unformat (input, "face %d", &faceid)) {; } else { break; } } //Check for presence of face ID if (faceid == ~0) { clib_warning ("Please specify face ID"); return 1; } //Construct the API message M (HICN_API_FACE_PROD_DEL, mp); mp->faceid = clib_host_to_net_u32 (faceid); //send it... S (mp); //Wait for a reply... W (ret); return ret; } static int api_hicn_api_register_cons_app (vat_main_t * vam) { vl_api_hicn_api_register_cons_app_t *mp; int ret; /* Construct the API message */ M (HICN_API_REGISTER_CONS_APP, mp); /* send it... */ S (mp); /* Wait for a reply... */ W (ret); return ret; } static int api_hicn_api_face_cons_del (vat_main_t * vam) { unformat_input_t *input = vam->input; vl_api_hicn_api_face_cons_del_t *mp; u32 faceid = 0, ret; while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { if (unformat (input, "face %d", &faceid)) {; } else { break; } } //Check for presence of face ID if (faceid == ~0) { clib_warning ("Please specify face ID"); return 1; } //Construct the API message M (HICN_API_FACE_CONS_DEL, mp); mp->faceid = clib_host_to_net_u32 (faceid); //send it... S (mp); //Wait for a reply... W (ret); return ret; } static void vl_api_hicn_api_register_cons_app_reply_t_handler (vl_api_hicn_api_register_cons_app_reply_t * mp) { vat_main_t *vam = hicn_test_main.vat_main; i32 retval = ntohl (mp->retval); if (vam->async_mode) { vam->async_errors += (retval < 0); return; } vam->retval = retval; vam->result_ready = 1; if (vam->retval < 0) { //vpp_api_test infra will also print out string form of error fformat (vam->ofp, " (API call error: %d)\n", vam->retval); return; } ip46_address_t src_addr4 = ip46_address_initializer; ip46_address_t src_addr6 = ip46_address_initializer; ip_address_decode (&mp->src_addr4, &src_addr4); ip_address_decode (&mp->src_addr6, &src_addr6); fformat (vam->ofp, "ip4 address %U\n" "ip6 address :%U\n" "appif id :%d\n", format_ip46_address, IP46_TYPE_ANY, &src_addr4, format_ip46_address, IP46_TYPE_ANY, &src_addr6); } /* * List of messages that the api test plugin sends, and that the data plane * plugin processes */ #define foreach_vpe_api_msg \ _(hicn_api_node_params_set, "PIT size CS size " \ "PIT minlimit PIT maxlimit [disable] ") \ _(hicn_api_node_params_get, "") \ _(hicn_api_node_stats_get, "") \ _(hicn_api_face_ip_del, "face ") \ _(hicn_api_face_ip_add, "local
remote
intfc ")\ _(hicn_api_face_udp_add, "local
port remote
port intfc ") \ _(hicn_api_face_del, "face ") \ _(hicn_api_faces_dump, "") \ _(hicn_api_face_get, "face ") \ _(hicn_api_face_stats_dump, "") \ _(hicn_api_route_nhops_add, "add prefix / face weight ") \ _(hicn_api_face_ip_params_get, "face ") \ _(hicn_api_route_get, "prefix /") \ _(hicn_api_routes_dump, "") \ _(hicn_api_route_del, "prefix /") \ _(hicn_api_route_nhop_del, "del prefix / face ") \ _(hicn_api_strategies_get, "") \ _(hicn_api_strategy_get, "strategy ") \ _(hicn_api_ip_punting_add, "prefix / intfc ") \ _(hicn_api_udp_punting_add, "prefix / intfc sport dport ip4/ip6") \ _(hicn_api_register_prod_app, "prefix / id ") \ _(hicn_api_face_prod_del, "face ") \ _(hicn_api_register_cons_app, "") \ _(hicn_api_face_cons_del, "face ") void hicn_vat_api_hookup (vat_main_t * vam) { hicn_test_main_t *sm = &hicn_test_main; /* Hook up handlers for replies from the data plane plug-in */ #define _(N, n) \ vl_msg_api_set_handlers((VL_API_##N + sm->msg_id_base), \ #n, \ vl_api_##n##_t_handler, \ vl_noop_handler, \ vl_api_##n##_t_endian, \ vl_api_##n##_t_print, \ sizeof(vl_api_##n##_t), 1); foreach_vpe_api_reply_msg; #undef _ /* API messages we can send */ #define _(n, h) hash_set_mem (vam->function_by_name, #n, api_##n); foreach_vpe_api_msg; #undef _ /* Help strings */ #define _(n, h) hash_set_mem (vam->help_by_name, #n, h); foreach_vpe_api_msg; #undef _ } clib_error_t * vat_plugin_register (vat_main_t * vam) { hicn_test_main_t *sm = &hicn_test_main; u8 *name; sm->vat_main = vam; /* Ask the vpp engine for the first assigned message-id */ name = format (0, "hicn_%08x%c", api_version, 0); sm->msg_id_base = vl_client_get_first_plugin_msg_id ((char *) name); /* Get the control ping ID */ #define _(id,n,crc) \ const char *id ## _CRC __attribute__ ((unused)) = #n "_" #crc; foreach_vl_msg_name_crc_vpe; #undef _ sm->ping_id = vl_msg_api_get_msg_index ((u8 *) (VL_API_CONTROL_PING_CRC)); if (sm->msg_id_base != (u16) ~ 0) hicn_vat_api_hookup (vam); vec_free (name); return 0; } /* * fd.io coding-style-patch-verification: ON * * Local Variables: eval: (c-set-style "gnu") End: */