+ fformat(vam->ofp, "%=20d%=30U%=16U%=16d%=16d%=16U"
+ "%=16d%=16d%=16sd=16d%=16s%=16s\n",
+ mp->tunnels,
+ mp->is_ipv6 ? format_ip6_address : format_ip4_address,
+ mp->source_ip,
+ mp->is_ipv6 ? format_ip6_address : format_ip4_address,
+ mp->destination_ip,
+ ntohl(mp->encap_fib_id),
+ ntohl(mp->decap_fib_id),
+ format_decap_next, ntohl(mp->dcap_next),
+ mp->ver_res >> 6,
+ flag_str,
+ mp->next_protocol,
+ mp->ver_res,
+ mp->res,
+ iid_str);
+
+ vec_free(iid_str);
+}
+
+static void
+vl_api_lisp_gpe_tunnel_details_t_handler_json (
+ vl_api_lisp_gpe_tunnel_details_t *mp)
+{
+ vat_main_t *vam = &vat_main;
+ vat_json_node_t *node = NULL;
+ struct in6_addr ip6;
+ struct in_addr ip4;
+ u8 *next_decap_str;
+
+ next_decap_str = format(0, "%U", format_decap_next, htonl(mp->dcap_next));
+
+ if (VAT_JSON_ARRAY != vam->json_tree.type) {
+ ASSERT(VAT_JSON_NONE == vam->json_tree.type);
+ vat_json_init_array(&vam->json_tree);
+ }
+ node = vat_json_array_add(&vam->json_tree);
+
+ vat_json_init_object(node);
+ vat_json_object_add_uint(node, "tunel", mp->tunnels);
+ if (mp->is_ipv6) {
+ clib_memcpy(&ip6, mp->source_ip, sizeof(ip6));
+ vat_json_object_add_ip6(node, "source address", ip6);
+ clib_memcpy(&ip6, mp->destination_ip, sizeof(ip6));
+ vat_json_object_add_ip6(node, "destination address", ip6);
+ } else {
+ clib_memcpy(&ip4, mp->source_ip, sizeof(ip4));
+ vat_json_object_add_ip4(node, "source address", ip4);
+ clib_memcpy(&ip4, mp->destination_ip, sizeof(ip4));
+ vat_json_object_add_ip4(node, "destination address", ip4);
+ }
+ vat_json_object_add_uint(node, "fib encap", ntohl(mp->encap_fib_id));
+ vat_json_object_add_uint(node, "fib decap", ntohl(mp->decap_fib_id));
+ vat_json_object_add_string_copy(node, "decap next", next_decap_str);
+ vat_json_object_add_uint(node, "lisp version", mp->ver_res >> 6);
+ vat_json_object_add_uint(node, "flags", mp->flags);
+ vat_json_object_add_uint(node, "next protocol", mp->next_protocol);
+ vat_json_object_add_uint(node, "ver_res", mp->ver_res);
+ vat_json_object_add_uint(node, "res", mp->res);
+ vat_json_object_add_uint(node, "iid", ntohl(mp->iid));
+
+ vec_free(next_decap_str);
+}
+
+static void
+vl_api_lisp_map_resolver_details_t_handler (
+ vl_api_lisp_map_resolver_details_t *mp)
+{
+ vat_main_t *vam = &vat_main;
+
+ fformat(vam->ofp, "%=20U\n",
+ mp->is_ipv6 ? format_ip6_address : format_ip4_address,
+ mp->ip_address);
+}
+
+static void
+vl_api_lisp_map_resolver_details_t_handler_json (
+ vl_api_lisp_map_resolver_details_t *mp)
+{
+ vat_main_t *vam = &vat_main;
+ vat_json_node_t *node = NULL;
+ struct in6_addr ip6;
+ struct in_addr ip4;
+
+ if (VAT_JSON_ARRAY != vam->json_tree.type) {
+ ASSERT(VAT_JSON_NONE == vam->json_tree.type);
+ vat_json_init_array(&vam->json_tree);
+ }
+ node = vat_json_array_add(&vam->json_tree);
+
+ vat_json_init_object(node);
+ if (mp->is_ipv6) {
+ clib_memcpy(&ip6, mp->ip_address, sizeof(ip6));
+ vat_json_object_add_ip6(node, "map resolver", ip6);
+ } else {
+ clib_memcpy(&ip4, mp->ip_address, sizeof(ip4));
+ vat_json_object_add_ip4(node, "map resolver", ip4);
+ }
+}
+
+static void
+vl_api_lisp_enable_disable_status_details_t_handler
+(vl_api_lisp_enable_disable_status_details_t *mp)
+{
+ vat_main_t *vam = &vat_main;
+
+ fformat(vam->ofp, "feature: %s\ngpe: %s\n",
+ mp->feature_status ? "enabled" : "disabled",
+ mp->gpe_status ? "enabled" : "disabled");
+}
+
+static void
+vl_api_lisp_enable_disable_status_details_t_handler_json
+(vl_api_lisp_enable_disable_status_details_t *mp)
+{
+ vat_main_t *vam = &vat_main;
+ vat_json_node_t *node = NULL;
+ u8 * gpe_status = NULL;
+ u8 * feature_status = NULL;
+
+ gpe_status = format (0, "%s", mp->gpe_status ? "enabled" : "disabled");
+ feature_status = format (0, "%s",
+ mp->feature_status ? "enabled" : "disabled");
+ vec_add1 (gpe_status, 0);
+ vec_add1 (feature_status, 0);
+
+ if (VAT_JSON_ARRAY != vam->json_tree.type) {
+ ASSERT(VAT_JSON_NONE == vam->json_tree.type);
+ vat_json_init_array(&vam->json_tree);
+ }
+ node = vat_json_array_add(&vam->json_tree);
+
+ vat_json_init_object(node);
+ vat_json_object_add_string_copy(node, "gpe_status", gpe_status);
+ vat_json_object_add_string_copy(node, "feature_status", feature_status);
+
+ vec_free (gpe_status);
+ vec_free (feature_status);
+}
+
+static void
+vl_api_lisp_get_map_request_itr_rlocs_reply_t_handler (
+ vl_api_lisp_get_map_request_itr_rlocs_reply_t * mp)
+{
+ vat_main_t * vam = &vat_main;
+ i32 retval = ntohl(mp->retval);
+
+ if (retval >= 0) {
+ fformat(vam->ofp, "%=20s\n",
+ mp->locator_set_name);
+ }
+
+ vam->retval = retval;
+ vam->result_ready = 1;
+}
+
+static void
+vl_api_lisp_get_map_request_itr_rlocs_reply_t_handler_json (
+ vl_api_lisp_get_map_request_itr_rlocs_reply_t * mp)
+{
+ vat_main_t * vam = &vat_main;
+ vat_json_node_t * node = NULL;
+
+ if (VAT_JSON_ARRAY != vam->json_tree.type) {
+ ASSERT(VAT_JSON_NONE == vam->json_tree.type);
+ vat_json_init_array(&vam->json_tree);
+ }
+ node = vat_json_array_add(&vam->json_tree);
+
+ vat_json_init_object(node);
+ vat_json_object_add_string_copy(node, "itr-rlocs", mp->locator_set_name);
+
+ vat_json_print(vam->ofp, node);
+ vat_json_free(node);
+
+ vam->retval = ntohl(mp->retval);
+ vam->result_ready = 1;
+}
+
+static void
+vl_api_show_lisp_pitr_reply_t_handler (vl_api_show_lisp_pitr_reply_t * mp)
+{
+ vat_main_t *vam = &vat_main;
+ i32 retval = ntohl(mp->retval);
+
+ if (0 <= retval) {
+ fformat(vam->ofp, "%-20s%-16s\n",
+ mp->status ? "enabled" : "disabled",
+ mp->status ? (char *) mp->locator_set_name : "");
+ }
+
+ vam->retval = retval;
+ vam->result_ready = 1;
+}
+
+static void
+vl_api_show_lisp_pitr_reply_t_handler_json (vl_api_show_lisp_pitr_reply_t * mp)
+{
+ vat_main_t *vam = &vat_main;
+ vat_json_node_t node;
+ u8 * status = 0;
+
+ status = format (0, "%s", mp->status ? "enabled" : "disabled");
+ vec_add1 (status, 0);
+
+ vat_json_init_object(&node);
+ vat_json_object_add_string_copy(&node, "status", status);
+ if (mp->status) {
+ vat_json_object_add_string_copy(&node, "locator_set", mp->locator_set_name);
+ }
+
+ vec_free (status);
+
+ vat_json_print(vam->ofp, &node);
+ vat_json_free(&node);
+
+ vam->retval = ntohl(mp->retval);
+ vam->result_ready = 1;
+}
+
+static u8 * format_policer_type (u8 * s, va_list * va)
+{
+ u32 i = va_arg (*va, u32);
+
+ if (i == SSE2_QOS_POLICER_TYPE_1R2C)
+ s = format (s, "1r2c");
+ else if (i == SSE2_QOS_POLICER_TYPE_1R3C_RFC_2697)
+ s = format (s, "1r3c");
+ else if (i == SSE2_QOS_POLICER_TYPE_2R3C_RFC_2698)
+ s = format (s, "2r3c-2698");
+ else if (i == SSE2_QOS_POLICER_TYPE_2R3C_RFC_4115)
+ s = format (s, "2r3c-4115");
+ else if (i == SSE2_QOS_POLICER_TYPE_2R3C_RFC_MEF5CF1)
+ s = format (s, "2r3c-mef5cf1");
+ else
+ s = format (s, "ILLEGAL");
+ return s;
+}
+
+static u8 * format_policer_rate_type (u8 * s, va_list * va)
+{
+ u32 i = va_arg (*va, u32);
+
+ if (i == SSE2_QOS_RATE_KBPS)
+ s = format (s, "kbps");
+ else if (i == SSE2_QOS_RATE_PPS)
+ s = format(s, "pps");
+ else
+ s = format (s, "ILLEGAL");
+ return s;
+}
+
+static u8 * format_policer_round_type (u8 * s, va_list * va)
+{
+ u32 i = va_arg (*va, u32);
+
+ if (i == SSE2_QOS_ROUND_TO_CLOSEST)
+ s = format(s, "closest");
+ else if (i == SSE2_QOS_ROUND_TO_UP)
+ s = format (s, "up");
+ else if (i == SSE2_QOS_ROUND_TO_DOWN)
+ s = format (s, "down");
+ else
+ s = format (s, "ILLEGAL");
+ return s;
+}
+
+static u8 * format_policer_action_type (u8 * s, va_list * va)
+{
+ u32 i = va_arg (*va, u32);
+
+ if (i == SSE2_QOS_ACTION_DROP)
+ s = format (s, "drop");
+ else if (i == SSE2_QOS_ACTION_TRANSMIT)
+ s = format (s, "transmit");
+ else if (i == SSE2_QOS_ACTION_MARK_AND_TRANSMIT)
+ s = format (s, "mark-and-transmit");
+ else
+ s = format (s, "ILLEGAL");
+ return s;
+}
+
+static u8 * format_dscp (u8 * s, va_list * va)
+{
+ u32 i = va_arg (*va, u32);
+ char * t = 0;
+
+ switch (i) {
+ #define _(v,f,str) case VNET_DSCP_##f: t = str; break;
+ foreach_vnet_dscp
+ #undef _
+ default:
+ return format (s, "ILLEGAL");
+ }
+ s = format (s, "%s", t);
+ return s;
+}
+
+static void vl_api_policer_details_t_handler
+(vl_api_policer_details_t * mp)
+{
+ vat_main_t * vam = &vat_main;
+ u8 *conform_dscp_str, *exceed_dscp_str, *violate_dscp_str;
+
+ if (mp->conform_action_type == SSE2_QOS_ACTION_MARK_AND_TRANSMIT)
+ conform_dscp_str = format(0, "%U", format_dscp, mp->conform_dscp);
+ else
+ conform_dscp_str = format(0, "");
+
+ if (mp->exceed_action_type == SSE2_QOS_ACTION_MARK_AND_TRANSMIT)
+ exceed_dscp_str = format(0, "%U", format_dscp, mp->exceed_dscp);
+ else
+ exceed_dscp_str = format(0, "");
+
+ if (mp->violate_action_type == SSE2_QOS_ACTION_MARK_AND_TRANSMIT)
+ violate_dscp_str = format(0, "%U", format_dscp, mp->violate_dscp);
+ else
+ violate_dscp_str = format(0, "");
+
+ fformat (vam->ofp, "Name \"%s\", type %U, cir %u, eir %u, cb %u, eb %u, "
+ "rate type %U, round type %U, %s rate, %s color-aware, "
+ "cir %u tok/period, pir %u tok/period, scale %u, cur lim %u, "
+ "cur bkt %u, ext lim %u, ext bkt %u, last update %llu"
+ "conform action %U%s, exceed action %U%s, violate action %U%s\n",
+ mp->name,
+ format_policer_type, mp->type,
+ ntohl(mp->cir),
+ ntohl(mp->eir),
+ ntohl(mp->cb),
+ ntohl(mp->eb),
+ format_policer_rate_type, mp->rate_type,
+ format_policer_round_type, mp->round_type,
+ mp->single_rate ? "single" : "dual",
+ mp->color_aware ? "is" : "not",
+ ntohl(mp->cir_tokens_per_period),
+ ntohl(mp->pir_tokens_per_period),
+ ntohl(mp->scale),
+ ntohl(mp->current_limit),
+ ntohl(mp->current_bucket),
+ ntohl(mp->extended_limit),
+ ntohl(mp->extended_bucket),
+ clib_net_to_host_u64(mp->last_update_time),
+ format_policer_action_type, mp->conform_action_type,
+ conform_dscp_str,
+ format_policer_action_type, mp->exceed_action_type,
+ exceed_dscp_str,
+ format_policer_action_type, mp->violate_action_type,
+ violate_dscp_str);
+
+ vec_free(conform_dscp_str);
+ vec_free(exceed_dscp_str);
+ vec_free(violate_dscp_str);
+}
+
+static void vl_api_policer_details_t_handler_json
+(vl_api_policer_details_t * mp)
+{
+ vat_main_t * vam = &vat_main;
+ vat_json_node_t *node;
+ u8 *rate_type_str, *round_type_str, *type_str;
+ u8 *conform_action_str, *exceed_action_str, *violate_action_str;
+
+ rate_type_str = format(0, "%U", format_policer_rate_type, mp->rate_type);
+ round_type_str = format(0, "%U", format_policer_round_type, mp->round_type);
+ type_str = format(0, "%U", format_policer_type, mp->type);
+ conform_action_str = format(0, "%U", format_policer_action_type,
+ mp->conform_action_type);
+ exceed_action_str = format(0, "%U", format_policer_action_type,
+ mp->exceed_action_type);
+ violate_action_str = format(0, "%U", format_policer_action_type,
+ mp->violate_action_type);
+
+ if (VAT_JSON_ARRAY != vam->json_tree.type) {
+ ASSERT(VAT_JSON_NONE == vam->json_tree.type);
+ vat_json_init_array(&vam->json_tree);
+ }
+ node = vat_json_array_add(&vam->json_tree);
+
+ vat_json_init_object(node);
+ vat_json_object_add_string_copy(node, "name", mp->name);
+ vat_json_object_add_uint(node, "cir", ntohl(mp->cir));
+ vat_json_object_add_uint(node, "eir", ntohl(mp->eir));
+ vat_json_object_add_uint(node, "cb", ntohl(mp->cb));
+ vat_json_object_add_uint(node, "eb", ntohl(mp->eb));
+ vat_json_object_add_string_copy(node, "rate_type", rate_type_str);
+ vat_json_object_add_string_copy(node, "round_type", round_type_str);
+ vat_json_object_add_string_copy(node, "type", type_str);
+ vat_json_object_add_uint(node, "single_rate", mp->single_rate);
+ vat_json_object_add_uint(node, "color_aware", mp->color_aware);
+ vat_json_object_add_uint(node, "scale", ntohl(mp->scale));
+ vat_json_object_add_uint(node, "cir_tokens_per_period",
+ ntohl(mp->cir_tokens_per_period));
+ vat_json_object_add_uint(node, "eir_tokens_per_period",
+ ntohl(mp->pir_tokens_per_period));
+ vat_json_object_add_uint(node, "current_limit", ntohl(mp->current_limit));
+ vat_json_object_add_uint(node, "current_bucket", ntohl(mp->current_bucket));
+ vat_json_object_add_uint(node, "extended_limit", ntohl(mp->extended_limit));
+ vat_json_object_add_uint(node, "extended_bucket",
+ ntohl(mp->extended_bucket));
+ vat_json_object_add_uint(node, "last_update_time",
+ ntohl(mp->last_update_time));
+ vat_json_object_add_string_copy(node, "conform_action", conform_action_str);
+ if (mp->conform_action_type == SSE2_QOS_ACTION_MARK_AND_TRANSMIT) {
+ u8 *dscp_str = format(0, "%U", format_dscp, mp->conform_dscp);
+ vat_json_object_add_string_copy(node, "conform_dscp", dscp_str);
+ vec_free(dscp_str);
+ }
+ vat_json_object_add_string_copy(node, "exceed_action", exceed_action_str);
+ if (mp->exceed_action_type == SSE2_QOS_ACTION_MARK_AND_TRANSMIT) {
+ u8 *dscp_str = format(0, "%U", format_dscp, mp->exceed_dscp);
+ vat_json_object_add_string_copy(node, "exceed_dscp", dscp_str);
+ vec_free(dscp_str);
+ }
+ vat_json_object_add_string_copy(node, "violate_action", violate_action_str);
+ if (mp->violate_action_type == SSE2_QOS_ACTION_MARK_AND_TRANSMIT) {
+ u8 *dscp_str = format(0, "%U", format_dscp, mp->violate_dscp);
+ vat_json_object_add_string_copy(node, "violate_dscp", dscp_str);
+ vec_free(dscp_str);
+ }
+
+ vec_free(rate_type_str);
+ vec_free(round_type_str);
+ vec_free(type_str);
+ vec_free(conform_action_str);
+ vec_free(exceed_action_str);
+ vec_free(violate_action_str);
+}
+
+static void vl_api_classify_table_ids_reply_t_handler (vl_api_classify_table_ids_reply_t * mp)
+{
+ vat_main_t * vam = &vat_main;
+ int i, count = ntohl(mp->count);
+
+ if (count>0)
+ fformat (vam->ofp, "classify table ids (%d) : ", count);
+ for (i = 0; i < count; i++)
+ {
+ fformat (vam->ofp, "%d", ntohl(mp->ids[i]));
+ fformat (vam->ofp, (i<count-1)?",":"\n");
+ }
+ vam->retval = ntohl(mp->retval);
+ vam->result_ready = 1;
+}
+
+static void vl_api_classify_table_ids_reply_t_handler_json (vl_api_classify_table_ids_reply_t * mp)
+{
+ vat_main_t * vam = &vat_main;
+ int i, count = ntohl(mp->count);
+
+ if (count>0) {
+ vat_json_node_t node;
+
+ vat_json_init_object(&node);
+ for (i = 0; i < count; i++)
+ {
+ vat_json_object_add_uint(&node, "table_id", ntohl(mp->ids[i]));
+ }
+ vat_json_print(vam->ofp, &node);
+ vat_json_free(&node);
+ }
+ vam->retval = ntohl(mp->retval);
+ vam->result_ready = 1;
+}
+
+static void vl_api_classify_table_by_interface_reply_t_handler (vl_api_classify_table_by_interface_reply_t * mp)
+{
+ vat_main_t * vam = &vat_main;
+ u32 table_id;
+
+ table_id = ntohl(mp->l2_table_id);
+ if (table_id != ~0)
+ fformat (vam->ofp, "l2 table id : %d\n", table_id);
+ else
+ fformat (vam->ofp, "l2 table id : No input ACL tables configured\n");
+ table_id = ntohl(mp->ip4_table_id);
+ if (table_id != ~0)
+ fformat (vam->ofp, "ip4 table id : %d\n", table_id);
+ else
+ fformat (vam->ofp, "ip4 table id : No input ACL tables configured\n");
+ table_id = ntohl(mp->ip6_table_id);
+ if (table_id != ~0)
+ fformat (vam->ofp, "ip6 table id : %d\n", table_id);
+ else
+ fformat (vam->ofp, "ip6 table id : No input ACL tables configured\n");
+ vam->retval = ntohl(mp->retval);
+ vam->result_ready = 1;
+}
+
+static void vl_api_classify_table_by_interface_reply_t_handler_json (vl_api_classify_table_by_interface_reply_t * mp)
+{
+ vat_main_t * vam = &vat_main;
+ vat_json_node_t node;
+
+ vat_json_init_object(&node);
+
+ vat_json_object_add_int(&node, "l2_table_id", ntohl(mp->l2_table_id));
+ vat_json_object_add_int(&node, "ip4_table_id", ntohl(mp->ip4_table_id));
+ vat_json_object_add_int(&node, "ip6_table_id", ntohl(mp->ip6_table_id));
+
+ vat_json_print(vam->ofp, &node);
+ vat_json_free(&node);
+
+ vam->retval = ntohl(mp->retval);
+ vam->result_ready = 1;
+}
+
+/* Format hex dump. */
+u8 * format_hex_bytes (u8 * s, va_list * va)
+{
+ u8 * bytes = va_arg (*va, u8 *);
+ int n_bytes = va_arg (*va, int);
+ uword i;
+
+ /* Print short or long form depending on byte count. */
+ uword short_form = n_bytes <= 32;
+ uword indent = format_get_indent (s);
+
+ if (n_bytes == 0)
+ return s;
+
+ for (i = 0; i < n_bytes; i++)
+ {
+ if (! short_form && (i % 32) == 0)
+ s = format (s, "%08x: ", i);
+ s = format (s, "%02x", bytes[i]);
+ if (! short_form && ((i + 1) % 32) == 0 && (i + 1) < n_bytes)
+ s = format (s, "\n%U", format_white_space, indent);
+ }
+
+ return s;
+}
+
+static void vl_api_classify_table_info_reply_t_handler (vl_api_classify_table_info_reply_t * mp)
+{
+ vat_main_t * vam = &vat_main;
+ i32 retval = ntohl(mp->retval);
+ if (retval == 0) {
+ fformat (vam->ofp, "classify table info :\n");
+ fformat (vam->ofp, "sessions: %d nexttbl: %d nextnode: %d\n", ntohl(mp->active_sessions), ntohl(mp->next_table_index), ntohl(mp->miss_next_index));
+ fformat (vam->ofp, "nbuckets: %d skip: %d match: %d\n", ntohl(mp->nbuckets), ntohl(mp->skip_n_vectors), ntohl(mp->match_n_vectors));
+ fformat (vam->ofp, "mask: %U\n", format_hex_bytes, mp->mask, ntohl(mp->mask_length));
+ }
+ vam->retval = retval;
+ vam->result_ready = 1;
+}
+
+static void vl_api_classify_table_info_reply_t_handler_json (vl_api_classify_table_info_reply_t * mp)
+{
+ vat_main_t * vam = &vat_main;
+ vat_json_node_t node;
+
+ i32 retval = ntohl(mp->retval);
+ if (retval == 0) {
+ vat_json_init_object(&node);
+
+ vat_json_object_add_int(&node, "sessions", ntohl(mp->active_sessions));
+ vat_json_object_add_int(&node, "nexttbl", ntohl(mp->next_table_index));
+ vat_json_object_add_int(&node, "nextnode", ntohl(mp->miss_next_index));
+ vat_json_object_add_int(&node, "nbuckets", ntohl(mp->nbuckets));
+ vat_json_object_add_int(&node, "skip", ntohl(mp->skip_n_vectors));
+ vat_json_object_add_int(&node, "match", ntohl(mp->match_n_vectors));
+ u8 * s = format (0, "%U%c",format_hex_bytes, mp->mask, ntohl(mp->mask_length), 0);
+ vat_json_object_add_string_copy(&node, "mask", s);
+
+ vat_json_print(vam->ofp, &node);
+ vat_json_free(&node);
+ }
+ vam->retval = ntohl(mp->retval);
+ vam->result_ready = 1;
+}
+
+static void vl_api_classify_session_details_t_handler (vl_api_classify_session_details_t * mp)
+{
+ vat_main_t * vam = &vat_main;
+
+ fformat (vam->ofp, "next_index: %d advance: %d opaque: %d ", ntohl(mp->hit_next_index), ntohl(mp->advance), ntohl(mp->opaque_index));
+ fformat (vam->ofp, "mask: %U\n", format_hex_bytes, mp->match, ntohl(mp->match_length));
+}
+
+static void vl_api_classify_session_details_t_handler_json (vl_api_classify_session_details_t * mp)
+{
+ vat_main_t * vam = &vat_main;
+ vat_json_node_t *node = NULL;
+
+ if (VAT_JSON_ARRAY != vam->json_tree.type) {
+ ASSERT(VAT_JSON_NONE == vam->json_tree.type);
+ vat_json_init_array(&vam->json_tree);
+ }
+ node = vat_json_array_add(&vam->json_tree);
+
+ vat_json_init_object(node);
+ vat_json_object_add_int(node, "next_index", ntohl(mp->hit_next_index));
+ vat_json_object_add_int(node, "advance", ntohl(mp->advance));
+ vat_json_object_add_int(node, "opaque", ntohl(mp->opaque_index));
+ u8 * s = format (0, "%U%c",format_hex_bytes, mp->match, ntohl(mp->match_length), 0);
+ vat_json_object_add_string_copy(node, "match", s);
+}
+
+static void vl_api_pg_create_interface_reply_t_handler
+(vl_api_pg_create_interface_reply_t * mp)
+{
+ vat_main_t * vam = &vat_main;
+
+ vam->retval = ntohl(mp->retval);
+ vam->result_ready = 1;
+}
+
+static void vl_api_pg_create_interface_reply_t_handler_json
+(vl_api_pg_create_interface_reply_t * mp)
+{
+ vat_main_t * vam = &vat_main;
+ vat_json_node_t node;
+
+ i32 retval = ntohl(mp->retval);
+ if (retval == 0) {
+ vat_json_init_object(&node);
+
+ vat_json_object_add_int(&node, "sw_if_index", ntohl(mp->sw_if_index));
+
+ vat_json_print(vam->ofp, &node);
+ vat_json_free(&node);
+ }
+ vam->retval = ntohl(mp->retval);
+ vam->result_ready = 1;
+}
+
+#define vl_api_vnet_ip4_fib_counters_t_endian vl_noop_handler
+#define vl_api_vnet_ip4_fib_counters_t_print vl_noop_handler
+#define vl_api_vnet_ip6_fib_counters_t_endian vl_noop_handler
+#define vl_api_vnet_ip6_fib_counters_t_print vl_noop_handler
+
+/*
+ * Generate boilerplate reply handlers, which
+ * dig the return value out of the xxx_reply_t API message,
+ * stick it into vam->retval, and set vam->result_ready
+ *
+ * Could also do this by pointing N message decode slots at
+ * a single function, but that could break in subtle ways.
+ */
+
+#define foreach_standard_reply_retval_handler \
+_(sw_interface_set_flags_reply) \
+_(sw_interface_add_del_address_reply) \
+_(sw_interface_set_table_reply) \
+_(sw_interface_set_vpath_reply) \
+_(sw_interface_set_l2_bridge_reply) \
+_(bridge_domain_add_del_reply) \
+_(sw_interface_set_l2_xconnect_reply) \
+_(l2fib_add_del_reply) \
+_(ip_add_del_route_reply) \
+_(proxy_arp_add_del_reply) \
+_(proxy_arp_intfc_enable_disable_reply) \
+_(mpls_add_del_encap_reply) \
+_(mpls_add_del_decap_reply) \
+_(mpls_ethernet_add_del_tunnel_2_reply) \
+_(sw_interface_set_unnumbered_reply) \
+_(ip_neighbor_add_del_reply) \
+_(reset_vrf_reply) \
+_(oam_add_del_reply) \
+_(reset_fib_reply) \
+_(dhcp_proxy_config_reply) \
+_(dhcp_proxy_config_2_reply) \
+_(dhcp_proxy_set_vss_reply) \
+_(dhcp_client_config_reply) \
+_(set_ip_flow_hash_reply) \
+_(sw_interface_ip6_enable_disable_reply) \
+_(sw_interface_ip6_set_link_local_address_reply) \
+_(sw_interface_ip6nd_ra_prefix_reply) \
+_(sw_interface_ip6nd_ra_config_reply) \
+_(set_arp_neighbor_limit_reply) \
+_(l2_patch_add_del_reply) \
+_(sr_tunnel_add_del_reply) \
+_(sr_policy_add_del_reply) \
+_(sr_multicast_map_add_del_reply) \
+_(classify_add_del_session_reply) \
+_(classify_set_interface_ip_table_reply) \
+_(classify_set_interface_l2_tables_reply) \
+_(l2tpv3_set_tunnel_cookies_reply) \
+_(l2tpv3_interface_enable_disable_reply) \
+_(l2tpv3_set_lookup_key_reply) \
+_(l2_fib_clear_table_reply) \
+_(l2_interface_efp_filter_reply) \
+_(l2_interface_vlan_tag_rewrite_reply) \
+_(modify_vhost_user_if_reply) \
+_(delete_vhost_user_if_reply) \
+_(want_ip4_arp_events_reply) \
+_(input_acl_set_interface_reply) \
+_(ipsec_spd_add_del_reply) \
+_(ipsec_interface_add_del_spd_reply) \
+_(ipsec_spd_add_del_entry_reply) \
+_(ipsec_sad_add_del_entry_reply) \
+_(ipsec_sa_set_key_reply) \
+_(ikev2_profile_add_del_reply) \
+_(ikev2_profile_set_auth_reply) \
+_(ikev2_profile_set_id_reply) \
+_(ikev2_profile_set_ts_reply) \
+_(ikev2_set_local_key_reply) \
+_(delete_loopback_reply) \
+_(bd_ip_mac_add_del_reply) \
+_(map_del_domain_reply) \
+_(map_add_del_rule_reply) \
+_(want_interface_events_reply) \
+_(want_stats_reply) \
+_(cop_interface_enable_disable_reply) \
+_(cop_whitelist_enable_disable_reply) \
+_(sw_interface_clear_stats_reply) \
+_(trace_profile_add_reply) \
+_(trace_profile_apply_reply) \
+_(trace_profile_del_reply) \
+_(lisp_add_del_locator_set_reply) \
+_(lisp_add_del_locator_reply) \
+_(lisp_add_del_local_eid_reply) \
+_(lisp_add_del_remote_mapping_reply) \
+_(lisp_add_del_adjacency_reply) \
+_(lisp_gpe_add_del_fwd_entry_reply) \
+_(lisp_add_del_map_resolver_reply) \
+_(lisp_gpe_enable_disable_reply) \
+_(lisp_gpe_add_del_iface_reply) \
+_(lisp_enable_disable_reply) \
+_(lisp_pitr_set_locator_set_reply) \
+_(lisp_add_del_map_request_itr_rlocs_reply) \
+_(lisp_eid_table_add_del_map_reply) \
+_(vxlan_gpe_add_del_tunnel_reply) \
+_(af_packet_delete_reply) \
+_(policer_add_del_reply) \
+_(netmap_create_reply) \
+_(netmap_delete_reply) \
+_(ipfix_enable_reply) \
+_(pg_capture_reply) \
+_(pg_enable_disable_reply)
+
+#define _(n) \
+ static void vl_api_##n##_t_handler \
+ (vl_api_##n##_t * mp) \
+ { \
+ vat_main_t * vam = &vat_main; \
+ i32 retval = ntohl(mp->retval); \
+ if (vam->async_mode) { \
+ vam->async_errors += (retval < 0); \
+ } else { \
+ vam->retval = retval; \
+ vam->result_ready = 1; \
+ } \
+ }
+foreach_standard_reply_retval_handler;
+#undef _
+
+#define _(n) \
+ static void vl_api_##n##_t_handler_json \
+ (vl_api_##n##_t * mp) \
+ { \
+ vat_main_t * vam = &vat_main; \
+ vat_json_node_t node; \
+ vat_json_init_object(&node); \
+ vat_json_object_add_int(&node, "retval", ntohl(mp->retval)); \
+ vat_json_print(vam->ofp, &node); \
+ vam->retval = ntohl(mp->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 \
+_(CREATE_LOOPBACK_REPLY, create_loopback_reply) \
+_(SW_INTERFACE_DETAILS, sw_interface_details) \
+_(SW_INTERFACE_SET_FLAGS, sw_interface_set_flags) \
+_(SW_INTERFACE_SET_FLAGS_REPLY, sw_interface_set_flags_reply) \
+_(CONTROL_PING_REPLY, control_ping_reply) \
+_(CLI_REPLY, cli_reply) \
+_(SW_INTERFACE_ADD_DEL_ADDRESS_REPLY, \
+ sw_interface_add_del_address_reply) \
+_(SW_INTERFACE_SET_TABLE_REPLY, sw_interface_set_table_reply) \
+_(SW_INTERFACE_SET_VPATH_REPLY, sw_interface_set_vpath_reply) \
+_(SW_INTERFACE_SET_L2_XCONNECT_REPLY, \
+ sw_interface_set_l2_xconnect_reply) \
+_(SW_INTERFACE_SET_L2_BRIDGE_REPLY, \
+ sw_interface_set_l2_bridge_reply) \
+_(BRIDGE_DOMAIN_ADD_DEL_REPLY, bridge_domain_add_del_reply) \
+_(BRIDGE_DOMAIN_DETAILS, bridge_domain_details) \
+_(BRIDGE_DOMAIN_SW_IF_DETAILS, bridge_domain_sw_if_details) \
+_(L2FIB_ADD_DEL_REPLY, l2fib_add_del_reply) \
+_(L2_FLAGS_REPLY, l2_flags_reply) \
+_(BRIDGE_FLAGS_REPLY, bridge_flags_reply) \
+_(TAP_CONNECT_REPLY, tap_connect_reply) \
+_(TAP_MODIFY_REPLY, tap_modify_reply) \
+_(TAP_DELETE_REPLY, tap_delete_reply) \
+_(SW_INTERFACE_TAP_DETAILS, sw_interface_tap_details) \
+_(IP_ADD_DEL_ROUTE_REPLY, ip_add_del_route_reply) \
+_(PROXY_ARP_ADD_DEL_REPLY, proxy_arp_add_del_reply) \
+_(PROXY_ARP_INTFC_ENABLE_DISABLE_REPLY, \
+ proxy_arp_intfc_enable_disable_reply) \
+_(MPLS_ADD_DEL_ENCAP_REPLY, mpls_add_del_encap_reply) \
+_(MPLS_ADD_DEL_DECAP_REPLY, mpls_add_del_decap_reply) \
+_(MPLS_GRE_ADD_DEL_TUNNEL_REPLY, mpls_gre_add_del_tunnel_reply) \
+_(MPLS_ETHERNET_ADD_DEL_TUNNEL_REPLY, \
+ mpls_ethernet_add_del_tunnel_reply) \
+_(MPLS_ETHERNET_ADD_DEL_TUNNEL_2_REPLY, \
+ mpls_ethernet_add_del_tunnel_2_reply) \
+_(SW_INTERFACE_SET_UNNUMBERED_REPLY, \
+ sw_interface_set_unnumbered_reply) \
+_(IP_NEIGHBOR_ADD_DEL_REPLY, ip_neighbor_add_del_reply) \
+_(RESET_VRF_REPLY, reset_vrf_reply) \
+_(CREATE_VLAN_SUBIF_REPLY, create_vlan_subif_reply) \
+_(CREATE_SUBIF_REPLY, create_subif_reply) \
+_(OAM_ADD_DEL_REPLY, oam_add_del_reply) \
+_(RESET_FIB_REPLY, reset_fib_reply) \
+_(DHCP_PROXY_CONFIG_REPLY, dhcp_proxy_config_reply) \
+_(DHCP_PROXY_CONFIG_2_REPLY, dhcp_proxy_config_2_reply) \
+_(DHCP_PROXY_SET_VSS_REPLY, dhcp_proxy_set_vss_reply) \
+_(DHCP_CLIENT_CONFIG_REPLY, dhcp_client_config_reply) \
+_(SET_IP_FLOW_HASH_REPLY, set_ip_flow_hash_reply) \
+_(SW_INTERFACE_IP6_ENABLE_DISABLE_REPLY, \
+ sw_interface_ip6_enable_disable_reply) \
+_(SW_INTERFACE_IP6_SET_LINK_LOCAL_ADDRESS_REPLY, \
+ sw_interface_ip6_set_link_local_address_reply) \
+_(SW_INTERFACE_IP6ND_RA_PREFIX_REPLY, \
+ sw_interface_ip6nd_ra_prefix_reply) \
+_(SW_INTERFACE_IP6ND_RA_CONFIG_REPLY, \
+ sw_interface_ip6nd_ra_config_reply) \
+_(SET_ARP_NEIGHBOR_LIMIT_REPLY, set_arp_neighbor_limit_reply) \
+_(L2_PATCH_ADD_DEL_REPLY, l2_patch_add_del_reply) \
+_(SR_TUNNEL_ADD_DEL_REPLY, sr_tunnel_add_del_reply) \
+_(SR_POLICY_ADD_DEL_REPLY, sr_policy_add_del_reply) \
+_(SR_MULTICAST_MAP_ADD_DEL_REPLY, sr_multicast_map_add_del_reply) \
+_(CLASSIFY_ADD_DEL_TABLE_REPLY, classify_add_del_table_reply) \
+_(CLASSIFY_ADD_DEL_SESSION_REPLY, classify_add_del_session_reply) \
+_(CLASSIFY_SET_INTERFACE_IP_TABLE_REPLY, \
+classify_set_interface_ip_table_reply) \
+_(CLASSIFY_SET_INTERFACE_L2_TABLES_REPLY, \
+ classify_set_interface_l2_tables_reply) \
+_(GET_NODE_INDEX_REPLY, get_node_index_reply) \
+_(ADD_NODE_NEXT_REPLY, add_node_next_reply) \
+_(L2TPV3_CREATE_TUNNEL_REPLY, l2tpv3_create_tunnel_reply) \
+_(L2TPV3_SET_TUNNEL_COOKIES_REPLY, l2tpv3_set_tunnel_cookies_reply) \
+_(L2TPV3_INTERFACE_ENABLE_DISABLE_REPLY, \
+ l2tpv3_interface_enable_disable_reply) \
+_(L2TPV3_SET_LOOKUP_KEY_REPLY, l2tpv3_set_lookup_key_reply) \
+_(SW_IF_L2TPV3_TUNNEL_DETAILS, sw_if_l2tpv3_tunnel_details) \
+_(VXLAN_ADD_DEL_TUNNEL_REPLY, vxlan_add_del_tunnel_reply) \
+_(VXLAN_TUNNEL_DETAILS, vxlan_tunnel_details) \
+_(GRE_ADD_DEL_TUNNEL_REPLY, gre_add_del_tunnel_reply) \
+_(GRE_TUNNEL_DETAILS, gre_tunnel_details) \
+_(L2_FIB_CLEAR_TABLE_REPLY, l2_fib_clear_table_reply) \
+_(L2_INTERFACE_EFP_FILTER_REPLY, l2_interface_efp_filter_reply) \
+_(L2_INTERFACE_VLAN_TAG_REWRITE_REPLY, l2_interface_vlan_tag_rewrite_reply) \
+_(SW_INTERFACE_VHOST_USER_DETAILS, sw_interface_vhost_user_details) \
+_(CREATE_VHOST_USER_IF_REPLY, create_vhost_user_if_reply) \
+_(MODIFY_VHOST_USER_IF_REPLY, modify_vhost_user_if_reply) \
+_(DELETE_VHOST_USER_IF_REPLY, delete_vhost_user_if_reply) \
+_(SHOW_VERSION_REPLY, show_version_reply) \
+_(L2_FIB_TABLE_ENTRY, l2_fib_table_entry) \
+_(VXLAN_GPE_ADD_DEL_TUNNEL_REPLY, vxlan_gpe_add_del_tunnel_reply) \
+_(VXLAN_GPE_TUNNEL_DETAILS, vxlan_gpe_tunnel_details) \
+_(INTERFACE_NAME_RENUMBER_REPLY, interface_name_renumber_reply) \
+_(WANT_IP4_ARP_EVENTS_REPLY, want_ip4_arp_events_reply) \
+_(IP4_ARP_EVENT, ip4_arp_event) \
+_(INPUT_ACL_SET_INTERFACE_REPLY, input_acl_set_interface_reply) \
+_(IP_ADDRESS_DETAILS, ip_address_details) \
+_(IP_DETAILS, ip_details) \
+_(IPSEC_SPD_ADD_DEL_REPLY, ipsec_spd_add_del_reply) \
+_(IPSEC_INTERFACE_ADD_DEL_SPD_REPLY, ipsec_interface_add_del_spd_reply) \
+_(IPSEC_SPD_ADD_DEL_ENTRY_REPLY, ipsec_spd_add_del_entry_reply) \
+_(IPSEC_SAD_ADD_DEL_ENTRY_REPLY, ipsec_sad_add_del_entry_reply) \
+_(IPSEC_SA_SET_KEY_REPLY, ipsec_sa_set_key_reply) \
+_(IKEV2_PROFILE_ADD_DEL_REPLY, ikev2_profile_add_del_reply) \
+_(IKEV2_PROFILE_SET_AUTH_REPLY, ikev2_profile_set_auth_reply) \
+_(IKEV2_PROFILE_SET_ID_REPLY, ikev2_profile_set_id_reply) \
+_(IKEV2_PROFILE_SET_TS_REPLY, ikev2_profile_set_ts_reply) \
+_(IKEV2_SET_LOCAL_KEY_REPLY, ikev2_set_local_key_reply) \
+_(DELETE_LOOPBACK_REPLY, delete_loopback_reply) \
+_(BD_IP_MAC_ADD_DEL_REPLY, bd_ip_mac_add_del_reply) \
+_(DHCP_COMPL_EVENT, dhcp_compl_event) \
+_(VNET_INTERFACE_COUNTERS, vnet_interface_counters) \
+_(VNET_IP4_FIB_COUNTERS, vnet_ip4_fib_counters) \
+_(VNET_IP6_FIB_COUNTERS, vnet_ip6_fib_counters) \
+_(MAP_ADD_DOMAIN_REPLY, map_add_domain_reply) \
+_(MAP_DEL_DOMAIN_REPLY, map_del_domain_reply) \
+_(MAP_ADD_DEL_RULE_REPLY, map_add_del_rule_reply) \
+_(MAP_DOMAIN_DETAILS, map_domain_details) \
+_(MAP_RULE_DETAILS, map_rule_details) \
+_(WANT_INTERFACE_EVENTS_REPLY, want_interface_events_reply) \
+_(WANT_STATS_REPLY, want_stats_reply) \
+_(GET_FIRST_MSG_ID_REPLY, get_first_msg_id_reply) \
+_(COP_INTERFACE_ENABLE_DISABLE_REPLY, cop_interface_enable_disable_reply) \
+_(COP_WHITELIST_ENABLE_DISABLE_REPLY, cop_whitelist_enable_disable_reply) \
+_(GET_NODE_GRAPH_REPLY, get_node_graph_reply) \
+_(SW_INTERFACE_CLEAR_STATS_REPLY, sw_interface_clear_stats_reply) \
+_(TRACE_PROFILE_ADD_REPLY, trace_profile_add_reply) \
+_(TRACE_PROFILE_APPLY_REPLY, trace_profile_apply_reply) \
+_(TRACE_PROFILE_DEL_REPLY, trace_profile_del_reply) \
+_(LISP_ADD_DEL_LOCATOR_SET_REPLY, lisp_add_del_locator_set_reply) \
+_(LISP_ADD_DEL_LOCATOR_REPLY, lisp_add_del_locator_reply) \
+_(LISP_ADD_DEL_LOCAL_EID_REPLY, lisp_add_del_local_eid_reply) \
+_(LISP_ADD_DEL_REMOTE_MAPPING_REPLY, lisp_add_del_remote_mapping_reply) \
+_(LISP_ADD_DEL_ADJACENCY_REPLY, lisp_add_del_adjacency_reply) \
+_(LISP_GPE_ADD_DEL_FWD_ENTRY_REPLY, lisp_gpe_add_del_fwd_entry_reply) \
+_(LISP_ADD_DEL_MAP_RESOLVER_REPLY, lisp_add_del_map_resolver_reply) \
+_(LISP_GPE_ENABLE_DISABLE_REPLY, lisp_gpe_enable_disable_reply) \
+_(LISP_ENABLE_DISABLE_REPLY, lisp_enable_disable_reply) \
+_(LISP_PITR_SET_LOCATOR_SET_REPLY, lisp_pitr_set_locator_set_reply) \
+_(LISP_EID_TABLE_ADD_DEL_MAP_REPLY, lisp_eid_table_add_del_map_reply) \
+_(LISP_GPE_ADD_DEL_IFACE_REPLY, lisp_gpe_add_del_iface_reply) \
+_(LISP_LOCATOR_SET_DETAILS, lisp_locator_set_details) \
+_(LISP_LOCAL_EID_TABLE_DETAILS, lisp_local_eid_table_details) \
+_(LISP_EID_TABLE_MAP_DETAILS, lisp_eid_table_map_details) \
+_(LISP_GPE_TUNNEL_DETAILS, lisp_gpe_tunnel_details) \
+_(LISP_MAP_RESOLVER_DETAILS, lisp_map_resolver_details) \
+_(LISP_ENABLE_DISABLE_STATUS_DETAILS, \
+ lisp_enable_disable_status_details) \
+_(LISP_ADD_DEL_MAP_REQUEST_ITR_RLOCS_REPLY, \
+ lisp_add_del_map_request_itr_rlocs_reply) \
+_(LISP_GET_MAP_REQUEST_ITR_RLOCS_REPLY, \
+ lisp_get_map_request_itr_rlocs_reply) \
+_(SHOW_LISP_PITR_REPLY, show_lisp_pitr_reply) \
+_(AF_PACKET_CREATE_REPLY, af_packet_create_reply) \
+_(AF_PACKET_DELETE_REPLY, af_packet_delete_reply) \
+_(POLICER_ADD_DEL_REPLY, policer_add_del_reply) \
+_(POLICER_DETAILS, policer_details) \
+_(NETMAP_CREATE_REPLY, netmap_create_reply) \
+_(NETMAP_DELETE_REPLY, netmap_delete_reply) \
+_(MPLS_GRE_TUNNEL_DETAILS, mpls_gre_tunnel_details) \
+_(MPLS_ETH_TUNNEL_DETAILS, mpls_eth_tunnel_details) \
+_(MPLS_FIB_ENCAP_DETAILS, mpls_fib_encap_details) \
+_(MPLS_FIB_DECAP_DETAILS, mpls_fib_decap_details) \
+_(CLASSIFY_TABLE_IDS_REPLY, classify_table_ids_reply) \
+_(CLASSIFY_TABLE_BY_INTERFACE_REPLY, classify_table_by_interface_reply) \
+_(CLASSIFY_TABLE_INFO_REPLY, classify_table_info_reply) \
+_(CLASSIFY_SESSION_DETAILS, classify_session_details) \
+_(IPFIX_ENABLE_REPLY, ipfix_enable_reply) \
+_(IPFIX_DETAILS, ipfix_details) \
+_(GET_NEXT_INDEX_REPLY, get_next_index_reply) \
+_(PG_CREATE_INTERFACE_REPLY, pg_create_interface_reply) \
+_(PG_CAPTURE_REPLY, pg_capture_reply) \
+_(PG_ENABLE_DISABLE_REPLY, pg_enable_disable_reply)
+
+/* M: construct, but don't yet send a message */
+
+#define M(T,t) \
+do { \
+ vam->result_ready = 0; \
+ mp = vl_msg_api_alloc(sizeof(*mp)); \
+ memset (mp, 0, sizeof (*mp)); \
+ mp->_vl_msg_id = ntohs (VL_API_##T); \
+ mp->client_index = vam->my_client_index; \
+} while(0);
+
+#define M2(T,t,n) \
+do { \
+ vam->result_ready = 0; \
+ mp = vl_msg_api_alloc(sizeof(*mp)+(n)); \
+ memset (mp, 0, sizeof (*mp)); \
+ mp->_vl_msg_id = ntohs (VL_API_##T); \
+ mp->client_index = vam->my_client_index; \
+} while(0);
+
+
+/* S: send a message */
+#define S (vl_msg_api_send_shmem (vam->vl_input_queue, (u8 *)&mp))
+
+/* W: wait for results, with timeout */
+#define W \
+do { \
+ timeout = vat_time_now (vam) + 1.0; \
+ \
+ while (vat_time_now (vam) < timeout) { \
+ if (vam->result_ready == 1) { \
+ return (vam->retval); \
+ } \
+ } \
+ return -99; \
+} while(0);
+
+/* W2: wait for results, with timeout */
+#define W2(body) \
+do { \
+ timeout = vat_time_now (vam) + 1.0; \
+ \
+ while (vat_time_now (vam) < timeout) { \
+ if (vam->result_ready == 1) { \
+ (body); \
+ return (vam->retval); \
+ } \
+ } \
+ return -99; \
+} while(0);
+
+typedef struct {
+ u8 * name;
+ u32 value;
+} name_sort_t;
+
+
+#define STR_VTR_OP_CASE(op) \
+ case L2_VTR_ ## op: \
+ return "" # op;
+
+static const char *str_vtr_op(u32 vtr_op)
+{
+ switch(vtr_op) {
+ STR_VTR_OP_CASE(DISABLED);
+ STR_VTR_OP_CASE(PUSH_1);
+ STR_VTR_OP_CASE(PUSH_2);
+ STR_VTR_OP_CASE(POP_1);
+ STR_VTR_OP_CASE(POP_2);
+ STR_VTR_OP_CASE(TRANSLATE_1_1);
+ STR_VTR_OP_CASE(TRANSLATE_1_2);
+ STR_VTR_OP_CASE(TRANSLATE_2_1);
+ STR_VTR_OP_CASE(TRANSLATE_2_2);
+ }
+
+ return "UNKNOWN";
+}
+
+static int dump_sub_interface_table (vat_main_t * vam)
+{
+ const sw_interface_subif_t * sub = NULL;
+
+ if (vam->json_output) {
+ clib_warning ("JSON output supported only for VPE API calls and dump_stats_table");
+ return -99;
+ }
+
+ fformat (vam->ofp,
+ "%-30s%-12s%-11s%-7s%-5s%-9s%-9s%-6s%-8s%-10s%-10s\n",
+ "Interface", "sw_if_index",
+ "sub id", "dot1ad", "tags", "outer id",
+ "inner id", "exact", "default",
+ "outer any", "inner any");
+
+ vec_foreach (sub, vam->sw_if_subif_table) {
+ fformat (vam->ofp,
+ "%-30s%-12d%-11d%-7s%-5d%-9d%-9d%-6d%-8d%-10d%-10d\n",
+ sub->interface_name,
+ sub->sw_if_index,
+ sub->sub_id, sub->sub_dot1ad ? "dot1ad" : "dot1q",
+ sub->sub_number_of_tags, sub->sub_outer_vlan_id,
+ sub->sub_inner_vlan_id, sub->sub_exact_match, sub->sub_default,
+ sub->sub_outer_vlan_id_any, sub->sub_inner_vlan_id_any);
+ if (sub->vtr_op != L2_VTR_DISABLED) {
+ fformat (vam->ofp,
+ " vlan-tag-rewrite - op: %-14s [ dot1q: %d "
+ "tag1: %d tag2: %d ]\n",
+ str_vtr_op(sub->vtr_op), sub->vtr_push_dot1q,
+ sub->vtr_tag1, sub->vtr_tag2);
+ }
+ }
+
+ return 0;
+}
+
+static int name_sort_cmp (void * a1, void * a2)
+{
+ name_sort_t * n1 = a1;
+ name_sort_t * n2 = a2;
+
+ return strcmp ((char *)n1->name, (char *)n2->name);
+}
+
+static int dump_interface_table (vat_main_t * vam)
+{
+ hash_pair_t * p;
+ name_sort_t * nses = 0, * ns;
+
+ if (vam->json_output) {
+ clib_warning ("JSON output supported only for VPE API calls and dump_stats_table");
+ return -99;
+ }
+
+ hash_foreach_pair (p, vam->sw_if_index_by_interface_name,
+ ({
+ vec_add2 (nses, ns, 1);
+ ns->name = (u8 *)(p->key);
+ ns->value = (u32) p->value[0];
+ }));
+
+ vec_sort_with_function (nses, name_sort_cmp);
+
+ fformat (vam->ofp, "%-25s%-15s\n", "Interface", "sw_if_index");
+ vec_foreach (ns, nses) {
+ fformat (vam->ofp, "%-25s%-15d\n", ns->name, ns->value);
+ }
+ vec_free (nses);
+ return 0;
+}
+
+static int dump_ip_table (vat_main_t * vam, int is_ipv6)
+{
+ const ip_details_t * det = NULL;
+ const ip_address_details_t * address = NULL;
+ u32 i = ~0;
+
+ fformat (vam->ofp,
+ "%-12s\n",
+ "sw_if_index");
+
+ if (0 == vam) {
+ return 0;
+ }
+
+ vec_foreach (det, vam->ip_details_by_sw_if_index[is_ipv6]) {
+ i++;
+ if (!det->present) {
+ continue;
+ }
+ fformat (vam->ofp,
+ "%-12d\n",
+ i);
+ fformat (vam->ofp,
+ " %-30s%-13s\n",
+ "Address", "Prefix length");
+ if (!det->addr) {
+ continue;
+ }
+ vec_foreach (address, det->addr) {
+ fformat (vam->ofp,
+ " %-30U%-13d\n",
+ is_ipv6 ? format_ip6_address : format_ip4_address,
+ address->ip,
+ address->prefix_length);
+ }
+ }
+
+ return 0;
+}
+
+static int dump_ipv4_table (vat_main_t * vam)
+{
+ if (vam->json_output) {
+ clib_warning ("JSON output supported only for VPE API calls and dump_stats_table");
+ return -99;
+ }
+
+ return dump_ip_table (vam, 0);
+}
+
+static int dump_ipv6_table (vat_main_t * vam)
+{
+ if (vam->json_output) {
+ clib_warning ("JSON output supported only for VPE API calls and dump_stats_table");
+ return -99;
+ }
+
+ return dump_ip_table (vam, 1);
+}
+
+static char* counter_type_to_str (u8 counter_type, u8 is_combined)
+{
+ if (!is_combined) {
+ switch(counter_type) {
+ case VNET_INTERFACE_COUNTER_DROP:
+ return "drop";
+ case VNET_INTERFACE_COUNTER_PUNT:
+ return "punt";
+ case VNET_INTERFACE_COUNTER_IP4:
+ return "ip4";
+ case VNET_INTERFACE_COUNTER_IP6:
+ return "ip6";
+ case VNET_INTERFACE_COUNTER_RX_NO_BUF:
+ return "rx-no-buf";
+ case VNET_INTERFACE_COUNTER_RX_MISS:
+ return "rx-miss";
+ case VNET_INTERFACE_COUNTER_RX_ERROR:
+ return "rx-error";
+ case VNET_INTERFACE_COUNTER_TX_ERROR:
+ return "tx-error";
+ default:
+ return "INVALID-COUNTER-TYPE";
+ }
+ } else {
+ switch(counter_type) {
+ case VNET_INTERFACE_COUNTER_RX:
+ return "rx";
+ case VNET_INTERFACE_COUNTER_TX:
+ return "tx";
+ default:
+ return "INVALID-COUNTER-TYPE";
+ }
+ }
+}
+
+static int dump_stats_table (vat_main_t * vam)
+{
+ vat_json_node_t node;
+ vat_json_node_t *msg_array;
+ vat_json_node_t *msg;
+ vat_json_node_t *counter_array;
+ vat_json_node_t *counter;
+ interface_counter_t c;
+ u64 packets;
+ ip4_fib_counter_t *c4;
+ ip6_fib_counter_t *c6;
+ int i, j;
+
+ if (!vam->json_output) {
+ clib_warning ("dump_stats_table supported only in JSON format");
+ return -99;
+ }
+
+ vat_json_init_object(&node);
+
+ /* interface counters */
+ msg_array = vat_json_object_add(&node, "interface_counters");
+ vat_json_init_array(msg_array);
+ for (i = 0; i < vec_len(vam->simple_interface_counters); i++) {
+ msg = vat_json_array_add(msg_array);
+ vat_json_init_object(msg);
+ vat_json_object_add_string_copy(msg, "vnet_counter_type",
+ (u8*)counter_type_to_str(i, 0));
+ vat_json_object_add_int(msg, "is_combined", 0);
+ counter_array = vat_json_object_add(msg, "data");
+ vat_json_init_array(counter_array);
+ for (j = 0; j < vec_len(vam->simple_interface_counters[i]); j++) {
+ packets = vam->simple_interface_counters[i][j];
+ vat_json_array_add_uint(counter_array, packets);
+ }
+ }
+ for (i = 0; i < vec_len(vam->combined_interface_counters); i++) {
+ msg = vat_json_array_add(msg_array);
+ vat_json_init_object(msg);
+ vat_json_object_add_string_copy(msg, "vnet_counter_type",
+ (u8*)counter_type_to_str(i, 1));
+ vat_json_object_add_int(msg, "is_combined", 1);
+ counter_array = vat_json_object_add(msg, "data");
+ vat_json_init_array(counter_array);
+ for (j = 0; j < vec_len(vam->combined_interface_counters[i]); j++) {
+ c = vam->combined_interface_counters[i][j];
+ counter = vat_json_array_add(counter_array);
+ vat_json_init_object(counter);
+ vat_json_object_add_uint(counter, "packets", c.packets);
+ vat_json_object_add_uint(counter, "bytes", c.bytes);
+ }
+ }
+
+ /* ip4 fib counters */
+ msg_array = vat_json_object_add(&node, "ip4_fib_counters");
+ vat_json_init_array(msg_array);
+ for (i = 0; i < vec_len(vam->ip4_fib_counters); i++) {
+ msg = vat_json_array_add(msg_array);
+ vat_json_init_object(msg);
+ vat_json_object_add_uint(msg, "vrf_id", vam->ip4_fib_counters_vrf_id_by_index[i]);
+ counter_array = vat_json_object_add(msg, "c");
+ vat_json_init_array(counter_array);
+ for (j = 0; j < vec_len(vam->ip4_fib_counters[i]); j++) {
+ counter = vat_json_array_add(counter_array);
+ vat_json_init_object(counter);
+ c4 = &vam->ip4_fib_counters[i][j];
+ vat_json_object_add_ip4(counter, "address", c4->address);
+ vat_json_object_add_uint(counter, "address_length", c4->address_length);
+ vat_json_object_add_uint(counter, "packets", c4->packets);
+ vat_json_object_add_uint(counter, "bytes", c4->bytes);
+ }
+ }
+
+ /* ip6 fib counters */
+ msg_array = vat_json_object_add(&node, "ip6_fib_counters");
+ vat_json_init_array(msg_array);
+ for (i = 0; i < vec_len(vam->ip6_fib_counters); i++) {
+ msg = vat_json_array_add(msg_array);
+ vat_json_init_object(msg);
+ vat_json_object_add_uint(msg, "vrf_id", vam->ip6_fib_counters_vrf_id_by_index[i]);
+ counter_array = vat_json_object_add(msg, "c");
+ vat_json_init_array(counter_array);
+ for (j = 0; j < vec_len(vam->ip6_fib_counters[i]); j++) {
+ counter = vat_json_array_add(counter_array);
+ vat_json_init_object(counter);
+ c6 = &vam->ip6_fib_counters[i][j];
+ vat_json_object_add_ip6(counter, "address", c6->address);
+ vat_json_object_add_uint(counter, "address_length", c6->address_length);
+ vat_json_object_add_uint(counter, "packets", c6->packets);
+ vat_json_object_add_uint(counter, "bytes", c6->bytes);
+ }
+ }
+
+ vat_json_print(vam->ofp, &node);
+ vat_json_free(&node);
+
+ return 0;
+}
+
+int exec (vat_main_t * vam)
+{
+ api_main_t * am = &api_main;
+ vl_api_cli_request_t *mp;
+ f64 timeout;
+ void * oldheap;
+ u8 * cmd = 0;
+ unformat_input_t * i = vam->input;
+
+ if (vec_len(i->buffer) == 0)
+ return -1;
+
+ if (vam->exec_mode == 0 && unformat (i, "mode")) {
+ vam->exec_mode = 1;
+ return 0;
+ }
+ if (vam->exec_mode == 1 &&
+ (unformat (i, "exit") || unformat (i, "quit"))) {
+ vam->exec_mode = 0;
+ return 0;
+ }
+
+
+ M(CLI_REQUEST, cli_request);
+
+ /*
+ * Copy cmd into shared memory.
+ * In order for the CLI command to work, it
+ * must be a vector ending in \n, not a C-string ending
+ * in \n\0.
+ */
+ pthread_mutex_lock (&am->vlib_rp->mutex);
+ oldheap = svm_push_data_heap (am->vlib_rp);
+
+ vec_validate (cmd, vec_len(vam->input->buffer)-1);
+ clib_memcpy (cmd, vam->input->buffer, vec_len(vam->input->buffer));
+
+ svm_pop_heap (oldheap);
+ pthread_mutex_unlock (&am->vlib_rp->mutex);
+
+ mp->cmd_in_shmem = (u64) cmd;
+ S;
+ timeout = vat_time_now (vam) + 10.0;
+
+ while (vat_time_now (vam) < timeout) {
+ if (vam->result_ready == 1) {
+ u8 * free_me;
+ if (vam->shmem_result != NULL)
+ fformat (vam->ofp, "%s", vam->shmem_result);
+ pthread_mutex_lock (&am->vlib_rp->mutex);
+ oldheap = svm_push_data_heap (am->vlib_rp);
+
+ free_me = (u8 *)vam->shmem_result;
+ vec_free (free_me);
+
+ svm_pop_heap (oldheap);
+ pthread_mutex_unlock (&am->vlib_rp->mutex);
+ return 0;
+ }
+ }
+ return -99;
+}
+
+static int api_create_loopback (vat_main_t * vam)
+{
+ unformat_input_t * i = vam->input;
+ vl_api_create_loopback_t *mp;
+ f64 timeout;
+ u8 mac_address[6];
+ u8 mac_set = 0;
+
+ memset (mac_address, 0, sizeof (mac_address));
+
+ while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (i, "mac %U", unformat_ethernet_address, mac_address))
+ mac_set = 1;
+ else
+ break;
+ }
+
+ /* Construct the API message */
+ M(CREATE_LOOPBACK, create_loopback);
+ if (mac_set)
+ clib_memcpy (mp->mac_address, mac_address, sizeof (mac_address));
+
+ S; W;
+}
+
+static int api_delete_loopback (vat_main_t * vam)
+{
+ unformat_input_t * i = vam->input;
+ vl_api_delete_loopback_t *mp;
+ f64 timeout;
+ u32 sw_if_index = ~0;
+
+ while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (i, "sw_if_index %d", &sw_if_index))
+ ;
+ else
+ break;
+ }
+
+ if (sw_if_index == ~0)
+ {
+ errmsg ("missing sw_if_index\n");
+ return -99;
+ }
+
+ /* Construct the API message */
+ M(DELETE_LOOPBACK, delete_loopback);
+ mp->sw_if_index = ntohl (sw_if_index);
+
+ S; W;
+}
+
+static int api_want_stats (vat_main_t * vam)
+{
+ unformat_input_t * i = vam->input;
+ vl_api_want_stats_t * mp;
+ f64 timeout;
+ int enable = -1;
+
+ while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (i, "enable"))
+ enable = 1;
+ else if (unformat (i, "disable"))
+ enable = 0;
+ else
+ break;
+ }
+
+ if (enable == -1)
+ {
+ errmsg ("missing enable|disable\n");
+ return -99;
+ }
+
+ M(WANT_STATS, want_stats);
+ mp->enable_disable = enable;
+
+ S; W;
+}
+
+static int api_want_interface_events (vat_main_t * vam)
+{
+ unformat_input_t * i = vam->input;
+ vl_api_want_interface_events_t * mp;
+ f64 timeout;
+ int enable = -1;
+
+ while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (i, "enable"))
+ enable = 1;
+ else if (unformat (i, "disable"))
+ enable = 0;
+ else
+ break;
+ }
+
+ if (enable == -1)
+ {
+ errmsg ("missing enable|disable\n");
+ return -99;
+ }
+
+ M(WANT_INTERFACE_EVENTS, want_interface_events);
+ mp->enable_disable = enable;
+
+ vam->interface_event_display = enable;
+
+ S; W;
+}
+
+
+/* Note: non-static, called once to set up the initial intfc table */
+int api_sw_interface_dump (vat_main_t * vam)
+{
+ vl_api_sw_interface_dump_t *mp;
+ f64 timeout;
+ hash_pair_t * p;
+ name_sort_t * nses = 0, * ns;
+ sw_interface_subif_t * sub = NULL;
+
+ /* Toss the old name table */
+ hash_foreach_pair (p, vam->sw_if_index_by_interface_name,
+ ({
+ vec_add2 (nses, ns, 1);
+ ns->name = (u8 *)(p->key);
+ ns->value = (u32) p->value[0];
+ }));
+
+ hash_free (vam->sw_if_index_by_interface_name);
+
+ vec_foreach (ns, nses)
+ vec_free (ns->name);
+
+ vec_free (nses);
+
+ vec_foreach (sub, vam->sw_if_subif_table) {
+ vec_free (sub->interface_name);
+ }
+ vec_free (vam->sw_if_subif_table);
+
+ /* recreate the interface name hash table */
+ vam->sw_if_index_by_interface_name
+ = hash_create_string (0, sizeof(uword));
+
+ /* Get list of ethernets */
+ M(SW_INTERFACE_DUMP, sw_interface_dump);
+ mp->name_filter_valid = 1;
+ strncpy ((char *) mp->name_filter, "Ether", sizeof(mp->name_filter)-1);
+ S;
+
+ /* and local / loopback interfaces */
+ M(SW_INTERFACE_DUMP, sw_interface_dump);
+ mp->name_filter_valid = 1;
+ strncpy ((char *) mp->name_filter, "lo", sizeof(mp->name_filter)-1);
+ S;
+
+
+ /* and vxlan-gpe tunnel interfaces */
+ M(SW_INTERFACE_DUMP, sw_interface_dump);
+ mp->name_filter_valid = 1;
+ strncpy ((char *) mp->name_filter, "vxlan_gpe", sizeof(mp->name_filter)-1);
+ S;
+
+ /* and vxlan tunnel interfaces */
+ M(SW_INTERFACE_DUMP, sw_interface_dump);
+ mp->name_filter_valid = 1;
+ strncpy ((char *) mp->name_filter, "vxlan", sizeof(mp->name_filter)-1);
+ S;
+
+ /* and host (af_packet) interfaces */
+ M(SW_INTERFACE_DUMP, sw_interface_dump);
+ mp->name_filter_valid = 1;
+ strncpy ((char *) mp->name_filter, "host", sizeof(mp->name_filter)-1);
+ S;
+
+ /* and l2tpv3 tunnel interfaces */
+ M(SW_INTERFACE_DUMP, sw_interface_dump);
+ mp->name_filter_valid = 1;
+ strncpy ((char *) mp->name_filter, "l2tpv3_tunnel", sizeof(mp->name_filter)-1);
+ S;
+
+ /* and GRE tunnel interfaces */
+ M(SW_INTERFACE_DUMP, sw_interface_dump);
+ mp->name_filter_valid = 1;
+ strncpy ((char *) mp->name_filter, "gre", sizeof(mp->name_filter)-1);
+ S;
+
+ /* Use a control ping for synchronization */
+ {
+ vl_api_control_ping_t * mp;
+ M(CONTROL_PING, control_ping);
+ S;
+ }
+ W;
+}
+
+static int api_sw_interface_set_flags (vat_main_t * vam)
+{
+ unformat_input_t * i = vam->input;
+ vl_api_sw_interface_set_flags_t *mp;
+ f64 timeout;
+ u32 sw_if_index;
+ u8 sw_if_index_set = 0;
+ u8 admin_up = 0, link_up = 0;
+
+ /* Parse args required to build the message */
+ while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
+ if (unformat (i, "admin-up"))
+ admin_up = 1;
+ else if (unformat (i, "admin-down"))
+ admin_up = 0;
+ else if (unformat (i, "link-up"))
+ link_up = 1;
+ else if (unformat (i, "link-down"))
+ link_up = 0;
+ else if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
+ sw_if_index_set = 1;
+ else if (unformat (i, "sw_if_index %d", &sw_if_index))
+ sw_if_index_set = 1;
+ else
+ break;
+ }
+
+ if (sw_if_index_set == 0) {
+ errmsg ("missing interface name or sw_if_index\n");
+ return -99;
+ }
+
+ /* Construct the API message */
+ M(SW_INTERFACE_SET_FLAGS, sw_interface_set_flags);
+ mp->sw_if_index = ntohl (sw_if_index);
+ mp->admin_up_down = admin_up;
+ mp->link_up_down = link_up;
+
+ /* send it... */
+ S;
+
+ /* Wait for a reply, return the good/bad news... */
+ W;
+}
+
+static int api_sw_interface_clear_stats (vat_main_t * vam)
+{
+ unformat_input_t * i = vam->input;
+ vl_api_sw_interface_clear_stats_t *mp;
+ f64 timeout;
+ u32 sw_if_index;
+ u8 sw_if_index_set = 0;
+
+ /* Parse args required to build the message */
+ while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
+ if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
+ sw_if_index_set = 1;
+ else if (unformat (i, "sw_if_index %d", &sw_if_index))
+ sw_if_index_set = 1;
+ else
+ break;
+ }
+
+ /* Construct the API message */
+ M(SW_INTERFACE_CLEAR_STATS, sw_interface_clear_stats);
+
+ if (sw_if_index_set == 1)
+ mp->sw_if_index = ntohl (sw_if_index);
+ else
+ mp->sw_if_index = ~0;
+
+ /* send it... */
+ S;
+
+ /* Wait for a reply, return the good/bad news... */
+ W;
+}
+
+static int api_sw_interface_add_del_address (vat_main_t * vam)
+{
+ unformat_input_t * i = vam->input;
+ vl_api_sw_interface_add_del_address_t *mp;
+ f64 timeout;
+ u32 sw_if_index;
+ u8 sw_if_index_set = 0;
+ u8 is_add = 1, del_all = 0;
+ u32 address_length = 0;
+ u8 v4_address_set = 0;
+ u8 v6_address_set = 0;
+ ip4_address_t v4address;
+ ip6_address_t v6address;
+
+ /* Parse args required to build the message */
+ while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
+ if (unformat (i, "del-all"))
+ del_all = 1;
+ else if (unformat (i, "del"))
+ is_add = 0;
+ else if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
+ sw_if_index_set = 1;
+ else if (unformat (i, "sw_if_index %d", &sw_if_index))
+ sw_if_index_set = 1;
+ else if (unformat (i, "%U/%d",
+ unformat_ip4_address, &v4address,
+ &address_length))
+ v4_address_set = 1;
+ else if (unformat (i, "%U/%d",
+ unformat_ip6_address, &v6address,
+ &address_length))
+ v6_address_set = 1;
+ else
+ break;
+ }
+
+ if (sw_if_index_set == 0) {
+ errmsg ("missing interface name or sw_if_index\n");
+ return -99;
+ }
+ if (v4_address_set && v6_address_set) {
+ errmsg ("both v4 and v6 addresses set\n");
+ return -99;
+ }
+ if (!v4_address_set && !v6_address_set && !del_all) {
+ errmsg ("no addresses set\n");
+ return -99;
+ }
+
+ /* Construct the API message */
+ M(SW_INTERFACE_ADD_DEL_ADDRESS, sw_interface_add_del_address);
+
+ mp->sw_if_index = ntohl (sw_if_index);
+ mp->is_add = is_add;
+ mp->del_all = del_all;
+ if (v6_address_set) {
+ mp->is_ipv6 = 1;
+ clib_memcpy (mp->address, &v6address, sizeof (v6address));
+ } else {
+ clib_memcpy (mp->address, &v4address, sizeof (v4address));
+ }
+ mp->address_length = address_length;
+
+ /* send it... */
+ S;
+
+ /* Wait for a reply, return good/bad news */
+ W;
+}
+
+static int api_sw_interface_set_table (vat_main_t * vam)
+{
+ unformat_input_t * i = vam->input;
+ vl_api_sw_interface_set_table_t *mp;
+ f64 timeout;
+ u32 sw_if_index, vrf_id = 0;
+ u8 sw_if_index_set = 0;
+ u8 is_ipv6 = 0;
+
+ /* Parse args required to build the message */
+ while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
+ if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
+ sw_if_index_set = 1;
+ else if (unformat (i, "sw_if_index %d", &sw_if_index))
+ sw_if_index_set = 1;
+ else if (unformat (i, "vrf %d", &vrf_id))
+ ;
+ else if (unformat (i, "ipv6"))
+ is_ipv6 = 1;
+ else
+ break;
+ }
+
+ if (sw_if_index_set == 0) {
+ errmsg ("missing interface name or sw_if_index\n");
+ return -99;
+ }
+
+ /* Construct the API message */
+ M(SW_INTERFACE_SET_TABLE, sw_interface_set_table);
+
+ mp->sw_if_index = ntohl (sw_if_index);
+ mp->is_ipv6 = is_ipv6;
+ mp->vrf_id = ntohl (vrf_id);
+
+ /* send it... */
+ S;
+
+ /* Wait for a reply... */
+ W;
+}
+
+static int api_sw_interface_set_vpath (vat_main_t * vam)
+{
+ unformat_input_t * i = vam->input;
+ vl_api_sw_interface_set_vpath_t *mp;
+ f64 timeout;
+ u32 sw_if_index = 0;
+ u8 sw_if_index_set = 0;
+ u8 is_enable = 0;
+
+ /* Parse args required to build the message */
+ while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
+ if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
+ sw_if_index_set = 1;
+ else if (unformat (i, "sw_if_index %d", &sw_if_index))
+ sw_if_index_set = 1;
+ else if (unformat (i, "enable"))
+ is_enable = 1;
+ else if (unformat (i, "disable"))
+ is_enable = 0;
+ else
+ break;
+ }
+
+ if (sw_if_index_set == 0) {
+ errmsg ("missing interface name or sw_if_index\n");
+ return -99;
+ }
+
+ /* Construct the API message */
+ M(SW_INTERFACE_SET_VPATH, sw_interface_set_vpath);
+
+ mp->sw_if_index = ntohl (sw_if_index);
+ mp->enable = is_enable;
+
+ /* send it... */
+ S;
+
+ /* Wait for a reply... */
+ W;
+}
+
+static int api_sw_interface_set_l2_xconnect (vat_main_t * vam)
+{
+ unformat_input_t * i = vam->input;
+ vl_api_sw_interface_set_l2_xconnect_t *mp;
+ f64 timeout;
+ u32 rx_sw_if_index;
+ u8 rx_sw_if_index_set = 0;
+ u32 tx_sw_if_index;
+ u8 tx_sw_if_index_set = 0;
+ u8 enable = 1;
+
+ /* Parse args required to build the message */
+ while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
+ if (unformat (i, "rx_sw_if_index %d", &rx_sw_if_index))
+ rx_sw_if_index_set = 1;
+ else if (unformat (i, "tx_sw_if_index %d", &tx_sw_if_index))
+ tx_sw_if_index_set = 1;
+ else if (unformat (i, "rx")) {
+ if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
+ if (unformat (i, "%U", unformat_sw_if_index, vam,
+ &rx_sw_if_index))
+ rx_sw_if_index_set = 1;
+ } else
+ break;
+ } else if (unformat (i, "tx")) {
+ if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
+ if (unformat (i, "%U", unformat_sw_if_index, vam,
+ &tx_sw_if_index))
+ tx_sw_if_index_set = 1;
+ } else
+ break;
+ } else if (unformat (i, "enable"))
+ enable = 1;
+ else if (unformat (i, "disable"))
+ enable = 0;
+ else
+ break;
+ }
+
+ if (rx_sw_if_index_set == 0) {
+ errmsg ("missing rx interface name or rx_sw_if_index\n");
+ return -99;
+ }
+
+ if (enable && (tx_sw_if_index_set == 0)) {
+ errmsg ("missing tx interface name or tx_sw_if_index\n");
+ return -99;
+ }
+
+ M(SW_INTERFACE_SET_L2_XCONNECT, sw_interface_set_l2_xconnect);
+
+ mp->rx_sw_if_index = ntohl(rx_sw_if_index);
+ mp->tx_sw_if_index = ntohl(tx_sw_if_index);
+ mp->enable = enable;
+
+ S; W;
+ /* NOTREACHED */
+ return 0;
+}
+
+static int api_sw_interface_set_l2_bridge (vat_main_t * vam)
+{
+ unformat_input_t * i = vam->input;
+ vl_api_sw_interface_set_l2_bridge_t *mp;
+ f64 timeout;
+ u32 rx_sw_if_index;
+ u8 rx_sw_if_index_set = 0;
+ u32 bd_id;
+ u8 bd_id_set = 0;
+ u8 bvi = 0;
+ u32 shg = 0;
+ u8 enable = 1;
+
+ /* Parse args required to build the message */
+ while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
+ if (unformat (i, "sw_if_index %d", &rx_sw_if_index))
+ rx_sw_if_index_set = 1;
+ else if (unformat (i, "bd_id %d", &bd_id))
+ bd_id_set = 1;
+ else if (unformat (i, "%U", unformat_sw_if_index, vam,
+ &rx_sw_if_index))
+ rx_sw_if_index_set = 1;
+ else if (unformat (i, "shg %d", &shg))
+ ;
+ else if (unformat (i, "bvi"))
+ bvi = 1;
+ else if (unformat (i, "enable"))
+ enable = 1;
+ else if (unformat (i, "disable"))
+ enable = 0;
+ else
+ break;
+ }
+
+ if (rx_sw_if_index_set == 0) {
+ errmsg ("missing rx interface name or sw_if_index\n");
+ return -99;
+ }
+
+ if (enable && (bd_id_set == 0)) {
+ errmsg ("missing bridge domain\n");
+ return -99;
+ }
+
+ M(SW_INTERFACE_SET_L2_BRIDGE, sw_interface_set_l2_bridge);
+
+ mp->rx_sw_if_index = ntohl(rx_sw_if_index);
+ mp->bd_id = ntohl(bd_id);
+ mp->shg = (u8)shg;
+ mp->bvi = bvi;
+ mp->enable = enable;
+
+ S; W;
+ /* NOTREACHED */
+ return 0;
+}
+
+static int api_bridge_domain_dump (vat_main_t * vam)
+{
+ unformat_input_t * i = vam->input;
+ vl_api_bridge_domain_dump_t *mp;
+ f64 timeout;
+ u32 bd_id = ~0;
+
+ /* Parse args required to build the message */
+ while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
+ if (unformat (i, "bd_id %d", &bd_id))
+ ;
+ else
+ break;
+ }
+
+ M(BRIDGE_DOMAIN_DUMP, bridge_domain_dump);
+ mp->bd_id = ntohl(bd_id);
+ S;
+
+ /* Use a control ping for synchronization */
+ {
+ vl_api_control_ping_t * mp;
+ M(CONTROL_PING, control_ping);
+ S;
+ }
+
+ W;
+ /* NOTREACHED */
+ return 0;
+}
+
+static int api_bridge_domain_add_del (vat_main_t * vam)
+{
+ unformat_input_t * i = vam->input;
+ vl_api_bridge_domain_add_del_t *mp;
+ f64 timeout;
+ u32 bd_id = ~0;
+ u8 is_add = 1;
+ u32 flood = 1, forward = 1, learn = 1, uu_flood = 1, arp_term = 0;
+
+ /* Parse args required to build the message */
+ while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
+ if (unformat (i, "bd_id %d", &bd_id))
+ ;
+ else if (unformat (i, "flood %d", &flood))
+ ;
+ else if (unformat (i, "uu-flood %d", &uu_flood))
+ ;
+ else if (unformat (i, "forward %d", &forward))
+ ;
+ else if (unformat (i, "learn %d", &learn))
+ ;
+ else if (unformat (i, "arp-term %d", &arp_term))
+ ;
+ else if (unformat (i, "del")) {
+ is_add = 0;
+ flood = uu_flood = forward = learn = 0;
+ }
+ else
+ break;
+ }
+
+ if (bd_id == ~0) {
+ errmsg ("missing bridge domain\n");
+ return -99;
+ }
+
+ M(BRIDGE_DOMAIN_ADD_DEL, bridge_domain_add_del);
+
+ mp->bd_id = ntohl(bd_id);
+ mp->flood = flood;
+ mp->uu_flood = uu_flood;
+ mp->forward = forward;
+ mp->learn = learn;
+ mp->arp_term = arp_term;
+ mp->is_add = is_add;
+
+ S; W;
+ /* NOTREACHED */
+ return 0;
+}
+
+static int api_l2fib_add_del (vat_main_t * vam)
+{
+ unformat_input_t * i = vam->input;
+ vl_api_l2fib_add_del_t *mp;
+ f64 timeout;
+ u64 mac = 0;
+ u8 mac_set = 0;
+ u32 bd_id;
+ u8 bd_id_set = 0;
+ u32 sw_if_index;
+ u8 sw_if_index_set = 0;
+ u8 is_add = 1;
+ u8 static_mac = 0;
+ u8 filter_mac = 0;
+ u8 bvi_mac = 0;
+ int count = 1;
+ f64 before = 0;
+ int j;
+
+ /* Parse args required to build the message */
+ while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
+ if (unformat (i, "mac %U", unformat_ethernet_address, &mac))
+ mac_set = 1;
+ else if (unformat (i, "bd_id %d", &bd_id))
+ bd_id_set = 1;
+ else if (unformat (i, "sw_if_index %d", &sw_if_index))
+ sw_if_index_set = 1;
+ else if (unformat (i, "sw_if")) {
+ if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
+ if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
+ sw_if_index_set = 1;
+ } else
+ break;
+ } else if (unformat (i, "static"))
+ static_mac = 1;
+ else if (unformat (i, "filter")) {
+ filter_mac = 1;
+ static_mac = 1;
+ } else if (unformat (i, "bvi")) {
+ bvi_mac = 1;
+ static_mac = 1;
+ } else if (unformat (i, "del"))
+ is_add = 0;
+ else if (unformat (i, "count %d", &count))
+ ;
+ else
+ break;
+ }
+
+ if (mac_set == 0) {
+ errmsg ("missing mac address\n");
+ return -99;
+ }
+
+ if (bd_id_set == 0) {
+ errmsg ("missing bridge domain\n");
+ return -99;
+ }
+
+ if (is_add && (sw_if_index_set == 0)) {
+ errmsg ("missing interface name or sw_if_index\n");
+ return -99;
+ }
+
+ if (count > 1) {
+ /* Turn on async mode */
+ vam->async_mode = 1;
+ vam->async_errors = 0;
+ before = vat_time_now(vam);
+ }
+
+ for (j = 0; j < count; j++) {
+ M(L2FIB_ADD_DEL, l2fib_add_del);
+
+ mp->mac = mac;
+ mp->bd_id = ntohl(bd_id);
+ mp->is_add = is_add;
+
+ if (is_add) {
+ mp->sw_if_index = ntohl(sw_if_index);
+ mp->static_mac = static_mac;
+ mp->filter_mac = filter_mac;
+ mp->bvi_mac = bvi_mac;
+ }
+ increment_mac_address (&mac);
+ /* send it... */
+ S;
+ }
+
+ if (count > 1) {
+ vl_api_control_ping_t * mp;
+ f64 after;
+
+ /* Shut off async mode */
+ vam->async_mode = 0;
+
+ M(CONTROL_PING, control_ping);
+ S;
+
+ timeout = vat_time_now(vam) + 1.0;
+ while (vat_time_now (vam) < timeout)
+ if (vam->result_ready == 1)
+ goto out;
+ vam->retval = -99;
+
+ out:
+ if (vam->retval == -99)
+ errmsg ("timeout\n");
+
+ if (vam->async_errors > 0) {
+ errmsg ("%d asynchronous errors\n", vam->async_errors);
+ vam->retval = -98;
+ }
+ vam->async_errors = 0;
+ after = vat_time_now(vam);
+
+ fformat(vam->ofp, "%d routes in %.6f secs, %.2f routes/sec\n",
+ count, after - before, count / (after - before));
+ } else {
+ /* Wait for a reply... */
+ W;
+ }
+ /* Return the good/bad news */
+ return (vam->retval);
+}
+
+static int api_l2_flags (vat_main_t * vam)
+{
+ unformat_input_t * i = vam->input;
+ vl_api_l2_flags_t *mp;
+ f64 timeout;
+ u32 sw_if_index;
+ u32 feature_bitmap = 0;
+ u8 sw_if_index_set = 0;
+
+ /* Parse args required to build the message */
+ while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
+ if (unformat (i, "sw_if_index %d", &sw_if_index))
+ sw_if_index_set = 1;
+ else if (unformat (i, "sw_if")) {
+ if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
+ if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
+ sw_if_index_set = 1;
+ } else
+ break;
+ } else if (unformat (i, "learn"))
+ feature_bitmap |= L2INPUT_FEAT_LEARN;
+ else if (unformat (i, "forward"))
+ feature_bitmap |= L2INPUT_FEAT_FWD;
+ else if (unformat (i, "flood"))
+ feature_bitmap |= L2INPUT_FEAT_FLOOD;
+ else if (unformat (i, "uu-flood"))
+ feature_bitmap |= L2INPUT_FEAT_UU_FLOOD;
+ else
+ break;
+ }
+
+ if (sw_if_index_set == 0) {
+ errmsg ("missing interface name or sw_if_index\n");
+ return -99;
+ }
+
+ M(L2_FLAGS, l2_flags);
+
+ mp->sw_if_index = ntohl(sw_if_index);
+ mp->feature_bitmap = ntohl(feature_bitmap);
+
+ S; W;
+ /* NOTREACHED */
+ return 0;
+}
+
+static int api_bridge_flags (vat_main_t * vam)
+{
+ unformat_input_t * i = vam->input;
+ vl_api_bridge_flags_t *mp;
+ f64 timeout;
+ u32 bd_id;
+ u8 bd_id_set = 0;
+ u8 is_set = 1;
+ u32 flags = 0;
+
+ /* Parse args required to build the message */
+ while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
+ if (unformat (i, "bd_id %d", &bd_id))
+ bd_id_set = 1;
+ else if (unformat (i, "learn"))
+ flags |= L2_LEARN;
+ else if (unformat (i, "forward"))
+ flags |= L2_FWD;
+ else if (unformat (i, "flood"))
+ flags |= L2_FLOOD;
+ else if (unformat (i, "uu-flood"))
+ flags |= L2_UU_FLOOD;
+ else if (unformat (i, "arp-term"))
+ flags |= L2_ARP_TERM;
+ else if (unformat (i, "off"))
+ is_set = 0;
+ else if (unformat (i, "disable"))
+ is_set = 0;
+ else
+ break;
+ }
+
+ if (bd_id_set == 0) {
+ errmsg ("missing bridge domain\n");
+ return -99;
+ }
+
+ M(BRIDGE_FLAGS, bridge_flags);
+
+ mp->bd_id = ntohl(bd_id);
+ mp->feature_bitmap = ntohl(flags);
+ mp->is_set = is_set;
+
+ S; W;
+ /* NOTREACHED */
+ return 0;
+}
+
+static int api_bd_ip_mac_add_del (vat_main_t * vam)
+{
+ unformat_input_t * i = vam->input;
+ vl_api_bd_ip_mac_add_del_t *mp;
+ f64 timeout;
+ u32 bd_id;
+ u8 is_ipv6 = 0;
+ u8 is_add = 1;
+ u8 bd_id_set = 0;
+ u8 ip_set = 0;
+ u8 mac_set = 0;
+ ip4_address_t v4addr;
+ ip6_address_t v6addr;
+ u8 macaddr[6];
+
+
+ /* Parse args required to build the message */
+ while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
+ if (unformat (i, "bd_id %d", &bd_id)) {
+ bd_id_set++;
+ } else if (unformat (i, "%U", unformat_ip4_address, &v4addr)) {
+ ip_set++;
+ } else if (unformat (i, "%U", unformat_ip6_address, &v6addr)) {
+ ip_set++;
+ is_ipv6++;
+ } else if (unformat (i, "%U", unformat_ethernet_address, macaddr)) {
+ mac_set++;
+ } else if (unformat (i, "del"))
+ is_add = 0;
+ else
+ break;
+ }
+
+ if (bd_id_set == 0) {
+ errmsg ("missing bridge domain\n");
+ return -99;
+ } else if (ip_set == 0) {
+ errmsg ("missing IP address\n");
+ return -99;
+ } else if (mac_set == 0) {
+ errmsg ("missing MAC address\n");
+ return -99;
+ }
+
+ M(BD_IP_MAC_ADD_DEL, bd_ip_mac_add_del);
+
+ mp->bd_id = ntohl(bd_id);
+ mp->is_ipv6 = is_ipv6;
+ mp->is_add = is_add;
+ if (is_ipv6)
+ clib_memcpy (mp->ip_address, &v6addr, sizeof (v6addr));
+ else clib_memcpy (mp->ip_address, &v4addr, sizeof (v4addr));
+ clib_memcpy (mp->mac_address, macaddr, 6);
+ S; W;
+ /* NOTREACHED */
+ return 0;
+}
+
+static int api_tap_connect (vat_main_t * vam)
+{
+ unformat_input_t * i = vam->input;
+ vl_api_tap_connect_t *mp;
+ f64 timeout;
+ u8 mac_address[6];
+ u8 random_mac = 1;
+ u8 name_set = 0;
+ u8 * tap_name;
+
+ memset (mac_address, 0, sizeof (mac_address));
+
+ /* Parse args required to build the message */
+ while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
+ if (unformat (i, "mac %U", unformat_ethernet_address, mac_address)) {
+ random_mac = 0;
+ }
+ else if (unformat (i, "random-mac"))
+ random_mac = 1;
+ else if (unformat (i, "tapname %s", &tap_name))
+ name_set = 1;
+ else
+ break;
+ }
+
+ if (name_set == 0) {
+ errmsg ("missing tap name\n");
+ return -99;
+ }
+ if (vec_len (tap_name) > 63) {
+ errmsg ("tap name too long\n");
+ }
+ vec_add1 (tap_name, 0);
+
+ /* Construct the API message */
+ M(TAP_CONNECT, tap_connect);
+
+ mp->use_random_mac = random_mac;
+ clib_memcpy (mp->mac_address, mac_address, 6);
+ clib_memcpy (mp->tap_name, tap_name, vec_len (tap_name));
+ vec_free (tap_name);
+
+ /* send it... */
+ S;
+
+ /* Wait for a reply... */
+ W;
+}
+
+static int api_tap_modify (vat_main_t * vam)
+{
+ unformat_input_t * i = vam->input;
+ vl_api_tap_modify_t *mp;
+ f64 timeout;
+ u8 mac_address[6];
+ u8 random_mac = 1;
+ u8 name_set = 0;
+ u8 * tap_name;
+ u32 sw_if_index = ~0;
+ u8 sw_if_index_set = 0;
+
+ memset (mac_address, 0, sizeof (mac_address));
+
+ /* Parse args required to build the message */
+ while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
+ if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
+ sw_if_index_set = 1;
+ else if (unformat (i, "sw_if_index %d", &sw_if_index))
+ sw_if_index_set = 1;
+ else if (unformat (i, "mac %U", unformat_ethernet_address, mac_address)) {
+ random_mac = 0;
+ }
+ else if (unformat (i, "random-mac"))
+ random_mac = 1;
+ else if (unformat (i, "tapname %s", &tap_name))
+ name_set = 1;
+ else
+ break;
+ }
+
+ if (sw_if_index_set == 0) {
+ errmsg ("missing vpp interface name");
+ return -99;
+ }
+ if (name_set == 0) {
+ errmsg ("missing tap name\n");
+ return -99;
+ }
+ if (vec_len (tap_name) > 63) {
+ errmsg ("tap name too long\n");
+ }
+ vec_add1 (tap_name, 0);
+
+ /* Construct the API message */
+ M(TAP_MODIFY, tap_modify);
+
+ mp->use_random_mac = random_mac;
+ mp->sw_if_index = ntohl(sw_if_index);
+ clib_memcpy (mp->mac_address, mac_address, 6);
+ clib_memcpy (mp->tap_name, tap_name, vec_len (tap_name));
+ vec_free (tap_name);
+
+ /* send it... */
+ S;
+
+ /* Wait for a reply... */
+ W;
+}
+
+static int api_tap_delete (vat_main_t * vam)
+{
+ unformat_input_t * i = vam->input;
+ vl_api_tap_delete_t *mp;
+ f64 timeout;
+ u32 sw_if_index = ~0;
+ u8 sw_if_index_set = 0;
+
+ /* Parse args required to build the message */
+ while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
+ if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
+ sw_if_index_set = 1;
+ else if (unformat (i, "sw_if_index %d", &sw_if_index))
+ sw_if_index_set = 1;
+ else
+ break;
+ }
+
+ if (sw_if_index_set == 0) {
+ errmsg ("missing vpp interface name");
+ return -99;
+ }
+
+ /* Construct the API message */
+ M(TAP_DELETE, tap_delete);
+
+ mp->sw_if_index = ntohl(sw_if_index);
+
+ /* send it... */
+ S;
+
+ /* Wait for a reply... */
+ W;
+}
+
+static int api_ip_add_del_route (vat_main_t * vam)
+{
+ unformat_input_t * i = vam->input;
+ vl_api_ip_add_del_route_t *mp;
+ f64 timeout;
+ u32 sw_if_index = ~0, vrf_id = 0;
+ u8 sw_if_index_set = 0;
+ u8 is_ipv6 = 0;
+ u8 is_local = 0, is_drop = 0;
+ u8 create_vrf_if_needed = 0;
+ u8 is_add = 1;
+ u8 next_hop_weight = 1;
+ u8 not_last = 0;
+ u8 is_multipath = 0;
+ u8 address_set = 0;
+ u8 address_length_set = 0;
+ u32 lookup_in_vrf = 0;
+ u32 resolve_attempts = 0;
+ u32 dst_address_length = 0;
+ u8 next_hop_set = 0;
+ ip4_address_t v4_dst_address, v4_next_hop_address;
+ ip6_address_t v6_dst_address, v6_next_hop_address;
+ int count = 1;
+ int j;
+ f64 before = 0;
+ u32 random_add_del = 0;
+ u32 * random_vector = 0;
+ uword * random_hash;
+ u32 random_seed = 0xdeaddabe;
+ u32 classify_table_index = ~0;
+ u8 is_classify = 0;
+
+ /* Parse args required to build the message */
+ while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
+ if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
+ sw_if_index_set = 1;
+ else if (unformat (i, "sw_if_index %d", &sw_if_index))
+ sw_if_index_set = 1;
+ else if (unformat (i, "%U", unformat_ip4_address,
+ &v4_dst_address)) {
+ address_set = 1;
+ is_ipv6 = 0;
+ }
+ else if (unformat (i, "%U", unformat_ip6_address, &v6_dst_address)) {
+ address_set = 1;
+ is_ipv6 = 1;
+ }
+ else if (unformat (i, "/%d", &dst_address_length)) {
+ address_length_set = 1;
+ }
+
+ else if (is_ipv6 == 0 && unformat (i, "via %U", unformat_ip4_address,
+ &v4_next_hop_address)) {
+ next_hop_set = 1;
+ }
+ else if (is_ipv6 == 1 && unformat (i, "via %U", unformat_ip6_address,
+ &v6_next_hop_address)) {
+ next_hop_set = 1;
+ }
+ else if (unformat (i, "resolve-attempts %d", &resolve_attempts))
+ ;
+ else if (unformat (i, "weight %d", &next_hop_weight))
+ ;
+ else if (unformat (i, "drop")) {
+ is_drop = 1;
+ } else if (unformat (i, "local")) {
+ is_local = 1;
+ } else if (unformat (i, "classify %d", &classify_table_index)) {
+ is_classify = 1;
+ } else if (unformat (i, "del"))
+ is_add = 0;
+ else if (unformat (i, "add"))
+ is_add = 1;
+ else if (unformat (i, "not-last"))
+ not_last = 1;
+ else if (unformat (i, "multipath"))
+ is_multipath = 1;
+ else if (unformat (i, "vrf %d", &vrf_id))
+ ;
+ else if (unformat (i, "create-vrf"))
+ create_vrf_if_needed = 1;
+ else if (unformat (i, "count %d", &count))
+ ;
+ else if (unformat (i, "lookup-in-vrf %d", &lookup_in_vrf))
+ ;
+ else if (unformat (i, "random"))
+ random_add_del = 1;
+ else if (unformat (i, "seed %d", &random_seed))
+ ;
+ else {
+ clib_warning ("parse error '%U'", format_unformat_error, i);
+ return -99;
+ }
+ }
+
+ if (resolve_attempts > 0 && sw_if_index_set == 0) {
+ errmsg ("ARP resolution needs explicit interface or sw_if_index\n");
+ return -99;
+ }
+
+ if (!next_hop_set && !is_drop && !is_local && !is_classify) {
+ errmsg ("next hop / local / drop / classify not set\n");
+ return -99;
+ }
+
+ if (address_set == 0) {
+ errmsg ("missing addresses\n");
+ return -99;
+ }
+
+ if (address_length_set == 0) {
+ errmsg ("missing address length\n");
+ return -99;
+ }
+
+ /* Generate a pile of unique, random routes */
+ if (random_add_del) {
+ u32 this_random_address;
+ random_hash = hash_create (count, sizeof(uword));
+
+ hash_set (random_hash, v4_next_hop_address.as_u32, 1);
+ for (j = 0; j <= count; j++) {
+ do {
+ this_random_address = random_u32 (&random_seed);
+ this_random_address =
+ clib_host_to_net_u32 (this_random_address);
+ } while (hash_get (random_hash, this_random_address));
+ vec_add1 (random_vector, this_random_address);
+ hash_set (random_hash, this_random_address, 1);
+ }
+ hash_free (random_hash);
+ v4_dst_address.as_u32 = random_vector[0];
+ }
+
+ if (count > 1) {
+ /* Turn on async mode */
+ vam->async_mode = 1;
+ vam->async_errors = 0;
+ before = vat_time_now(vam);
+ }
+
+ for (j = 0; j < count; j++) {
+ /* Construct the API message */
+ M(IP_ADD_DEL_ROUTE, ip_add_del_route);
+
+ mp->next_hop_sw_if_index = ntohl (sw_if_index);
+ mp->vrf_id = ntohl (vrf_id);
+ if (resolve_attempts > 0) {
+ mp->resolve_attempts = ntohl (resolve_attempts);
+ mp->resolve_if_needed = 1;
+ }
+ mp->create_vrf_if_needed = create_vrf_if_needed;
+
+ mp->is_add = is_add;
+ mp->is_drop = is_drop;
+ mp->is_ipv6 = is_ipv6;
+ mp->is_local = is_local;
+ mp->is_classify = is_classify;
+ mp->is_multipath = is_multipath;
+ mp->not_last = not_last;
+ mp->next_hop_weight = next_hop_weight;
+ mp->dst_address_length = dst_address_length;
+ mp->lookup_in_vrf = ntohl(lookup_in_vrf);
+ mp->classify_table_index = ntohl(classify_table_index);
+
+ if (is_ipv6){
+ clib_memcpy (mp->dst_address, &v6_dst_address, sizeof (v6_dst_address));
+ if (next_hop_set)
+ clib_memcpy (mp->next_hop_address, &v6_next_hop_address,
+ sizeof (v6_next_hop_address));
+ increment_v6_address (&v6_dst_address);
+ } else {
+ clib_memcpy (mp->dst_address, &v4_dst_address, sizeof (v4_dst_address));
+ if (next_hop_set)
+ clib_memcpy (mp->next_hop_address, &v4_next_hop_address,
+ sizeof (v4_next_hop_address));
+ if (random_add_del)
+ v4_dst_address.as_u32 = random_vector[j+1];
+ else
+ increment_v4_address (&v4_dst_address);
+ }
+ /* send it... */
+ S;
+ }
+
+ /* When testing multiple add/del ops, use a control-ping to sync */
+ if (count > 1) {
+ vl_api_control_ping_t * mp;
+ f64 after;
+
+ /* Shut off async mode */
+ vam->async_mode = 0;
+
+ M(CONTROL_PING, control_ping);
+ S;
+
+ timeout = vat_time_now(vam) + 1.0;
+ while (vat_time_now (vam) < timeout)
+ if (vam->result_ready == 1)
+ goto out;
+ vam->retval = -99;
+
+ out:
+ if (vam->retval == -99)
+ errmsg ("timeout\n");
+
+ if (vam->async_errors > 0) {
+ errmsg ("%d asynchronous errors\n", vam->async_errors);
+ vam->retval = -98;
+ }
+ vam->async_errors = 0;
+ after = vat_time_now(vam);
+
+ fformat(vam->ofp, "%d routes in %.6f secs, %.2f routes/sec\n",
+ count, after - before, count / (after - before));
+ } else {
+ /* Wait for a reply... */
+ W;
+ }
+
+ /* Return the good/bad news */
+ return (vam->retval);
+}
+
+static int api_proxy_arp_add_del (vat_main_t * vam)
+{
+ unformat_input_t * i = vam->input;
+ vl_api_proxy_arp_add_del_t *mp;
+ f64 timeout;
+ u32 vrf_id = 0;
+ u8 is_add = 1;
+ ip4_address_t lo, hi;
+ u8 range_set = 0;
+
+ while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
+ if (unformat (i, "vrf %d", &vrf_id))
+ ;
+ else if (unformat (i, "%U - %U", unformat_ip4_address, &lo,
+ unformat_ip4_address, &hi))
+ range_set = 1;
+ else if (unformat (i, "del"))
+ is_add = 0;
+ else {
+ clib_warning ("parse error '%U'", format_unformat_error, i);
+ return -99;
+ }
+ }
+
+ if (range_set == 0) {
+ errmsg ("address range not set\n");
+ return -99;
+ }
+
+ M(PROXY_ARP_ADD_DEL, proxy_arp_add_del);
+
+ mp->vrf_id = ntohl(vrf_id);
+ mp->is_add = is_add;
+ clib_memcpy(mp->low_address, &lo, sizeof (mp->low_address));
+ clib_memcpy(mp->hi_address, &hi, sizeof (mp->hi_address));
+
+ S; W;
+ /* NOTREACHED */
+ return 0;
+}
+
+static int api_proxy_arp_intfc_enable_disable (vat_main_t * vam)
+{
+ unformat_input_t * i = vam->input;
+ vl_api_proxy_arp_intfc_enable_disable_t *mp;
+ f64 timeout;
+ u32 sw_if_index;
+ u8 enable = 1;
+ u8 sw_if_index_set = 0;
+
+ while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
+ if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
+ sw_if_index_set = 1;
+ else if (unformat (i, "sw_if_index %d", &sw_if_index))
+ sw_if_index_set = 1;
+ else if (unformat (i, "enable"))
+ enable = 1;
+ else if (unformat (i, "disable"))
+ enable = 0;
+ else {
+ clib_warning ("parse error '%U'", format_unformat_error, i);
+ return -99;
+ }
+ }
+
+ if (sw_if_index_set == 0) {
+ errmsg ("missing interface name or sw_if_index\n");
+ return -99;
+ }
+
+ M(PROXY_ARP_INTFC_ENABLE_DISABLE, proxy_arp_intfc_enable_disable);
+
+ mp->sw_if_index = ntohl(sw_if_index);
+ mp->enable_disable = enable;
+
+ S; W;
+ /* NOTREACHED */
+ return 0;
+}
+
+static int api_mpls_add_del_decap (vat_main_t * vam)
+{
+ unformat_input_t * i = vam->input;
+ vl_api_mpls_add_del_decap_t *mp;
+ f64 timeout;
+ u32 rx_vrf_id = 0;
+ u32 tx_vrf_id = 0;
+ u32 label = 0;
+ u8 is_add = 1;
+ u8 s_bit = 1;
+ u32 next_index = 1;
+
+ while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
+ if (unformat (i, "rx_vrf_id %d", &rx_vrf_id))
+ ;
+ else if (unformat (i, "tx_vrf_id %d", &tx_vrf_id))
+ ;
+ else if (unformat (i, "label %d", &label))
+ ;
+ else if (unformat (i, "next-index %d", &next_index))
+ ;
+ else if (unformat (i, "del"))
+ is_add = 0;
+ else if (unformat (i, "s-bit-clear"))
+ s_bit = 0;
+ else {
+ clib_warning ("parse error '%U'", format_unformat_error, i);
+ return -99;
+ }
+ }
+
+ M(MPLS_ADD_DEL_DECAP, mpls_add_del_decap);
+
+ mp->rx_vrf_id = ntohl(rx_vrf_id);
+ mp->tx_vrf_id = ntohl(tx_vrf_id);
+ mp->label = ntohl(label);
+ mp->next_index = ntohl(next_index);
+ mp->s_bit = s_bit;
+ mp->is_add = is_add;
+
+ S; W;
+ /* NOTREACHED */
+ return 0;
+}
+
+static int api_mpls_add_del_encap (vat_main_t * vam)
+{
+ unformat_input_t * i = vam->input;
+ vl_api_mpls_add_del_encap_t *mp;
+ f64 timeout;
+ u32 vrf_id = 0;
+ u32 *labels = 0;
+ u32 label;
+ ip4_address_t dst_address;
+ u8 is_add = 1;
+
+ while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
+ if (unformat (i, "vrf %d", &vrf_id))
+ ;
+ else if (unformat (i, "label %d", &label))
+ vec_add1 (labels, ntohl(label));
+ else if (unformat (i, "dst %U", unformat_ip4_address, &dst_address))
+ ;
+ else if (unformat (i, "del"))
+ is_add = 0;
+ else {
+ clib_warning ("parse error '%U'", format_unformat_error, i);
+ return -99;
+ }
+ }
+
+ if (vec_len (labels) == 0) {
+ errmsg ("missing encap label stack\n");
+ return -99;
+ }
+
+ M2(MPLS_ADD_DEL_ENCAP, mpls_add_del_encap,
+ sizeof (u32) * vec_len (labels));
+
+ mp->vrf_id = ntohl(vrf_id);
+ clib_memcpy(mp->dst_address, &dst_address, sizeof (dst_address));
+ mp->is_add = is_add;
+ mp->nlabels = vec_len (labels);
+ clib_memcpy(mp->labels, labels, sizeof(u32)*mp->nlabels);
+
+ vec_free(labels);
+
+ S; W;
+ /* NOTREACHED */
+ return 0;
+}
+
+static int api_mpls_gre_add_del_tunnel (vat_main_t * vam)
+{
+ unformat_input_t * i = vam->input;
+ vl_api_mpls_gre_add_del_tunnel_t *mp;
+ f64 timeout;
+ u32 inner_vrf_id = 0;
+ u32 outer_vrf_id = 0;
+ ip4_address_t src_address;
+ ip4_address_t dst_address;
+ ip4_address_t intfc_address;
+ u32 tmp;
+ u8 intfc_address_length = 0;
+ u8 is_add = 1;
+ u8 l2_only = 0;
+
+ while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
+ if (unformat (i, "inner_vrf_id %d", &inner_vrf_id))
+ ;
+ else if (unformat (i, "outer_vrf_id %d", &outer_vrf_id))
+ ;
+ else if (unformat (i, "src %U", unformat_ip4_address, &src_address))
+ ;
+ else if (unformat (i, "dst %U", unformat_ip4_address, &dst_address))
+ ;
+ else if (unformat (i, "adj %U/%d", unformat_ip4_address,
+ &intfc_address, &tmp))
+ intfc_address_length = tmp;
+ else if (unformat (i, "l2-only"))
+ l2_only = 1;
+ else if (unformat (i, "del"))
+ is_add = 0;
+ else {
+ clib_warning ("parse error '%U'", format_unformat_error, i);
+ return -99;
+ }
+ }
+
+ M(MPLS_GRE_ADD_DEL_TUNNEL, mpls_gre_add_del_tunnel);
+
+ mp->inner_vrf_id = ntohl(inner_vrf_id);
+ mp->outer_vrf_id = ntohl(outer_vrf_id);
+ clib_memcpy(mp->src_address, &src_address, sizeof (src_address));
+ clib_memcpy(mp->dst_address, &dst_address, sizeof (dst_address));
+ clib_memcpy(mp->intfc_address, &intfc_address, sizeof (intfc_address));
+ mp->intfc_address_length = intfc_address_length;
+ mp->l2_only = l2_only;
+ mp->is_add = is_add;
+
+ S; W;
+ /* NOTREACHED */
+ return 0;
+}
+
+static int api_mpls_ethernet_add_del_tunnel (vat_main_t * vam)
+{
+ unformat_input_t * i = vam->input;
+ vl_api_mpls_ethernet_add_del_tunnel_t *mp;
+ f64 timeout;
+ u32 inner_vrf_id = 0;
+ ip4_address_t intfc_address;
+ u8 dst_mac_address[6];
+ int dst_set = 1;
+ u32 tmp;
+ u8 intfc_address_length = 0;
+ u8 is_add = 1;
+ u8 l2_only = 0;
+ u32 tx_sw_if_index;
+ int tx_sw_if_index_set = 0;
+
+ while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
+ if (unformat (i, "vrf %d", &inner_vrf_id))
+ ;
+ else if (unformat (i, "adj %U/%d", unformat_ip4_address,
+ &intfc_address, &tmp))
+ intfc_address_length = tmp;
+ else if (unformat (i, "%U",
+ unformat_sw_if_index, vam, &tx_sw_if_index))
+ tx_sw_if_index_set = 1;
+ else if (unformat (i, "tx_sw_if_index %d", &tx_sw_if_index))
+ tx_sw_if_index_set = 1;
+ else if (unformat (i, "dst %U", unformat_ethernet_address,
+ dst_mac_address))
+ dst_set = 1;
+ else if (unformat (i, "l2-only"))
+ l2_only = 1;
+ else if (unformat (i, "del"))
+ is_add = 0;
+ else {
+ clib_warning ("parse error '%U'", format_unformat_error, i);
+ return -99;
+ }
+ }
+
+ if (!dst_set) {
+ errmsg ("dst (mac address) not set\n");
+ return -99;
+ }
+ if (!tx_sw_if_index_set) {
+ errmsg ("tx-intfc not set\n");
+ return -99;
+ }
+
+ M(MPLS_ETHERNET_ADD_DEL_TUNNEL, mpls_ethernet_add_del_tunnel);
+
+ mp->vrf_id = ntohl(inner_vrf_id);
+ clib_memcpy (mp->adj_address, &intfc_address, sizeof (intfc_address));
+ mp->adj_address_length = intfc_address_length;
+ clib_memcpy (mp->dst_mac_address, dst_mac_address, sizeof (dst_mac_address));
+ mp->tx_sw_if_index = ntohl(tx_sw_if_index);
+ mp->l2_only = l2_only;
+ mp->is_add = is_add;
+
+ S; W;
+ /* NOTREACHED */
+ return 0;
+}
+
+static int api_mpls_ethernet_add_del_tunnel_2 (vat_main_t * vam)
+{
+ unformat_input_t * i = vam->input;
+ vl_api_mpls_ethernet_add_del_tunnel_2_t *mp;
+ f64 timeout;
+ u32 inner_vrf_id = 0;
+ u32 outer_vrf_id = 0;
+ ip4_address_t adj_address;
+ int adj_address_set = 0;
+ ip4_address_t next_hop_address;
+ int next_hop_address_set = 0;
+ u32 tmp;
+ u8 adj_address_length = 0;
+ u8 l2_only = 0;
+ u8 is_add = 1;
+ u32 resolve_attempts = 5;
+ u8 resolve_if_needed = 1;
+
+ while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
+ if (unformat (i, "inner_vrf_id %d", &inner_vrf_id))
+ ;
+ else if (unformat (i, "outer_vrf_id %d", &outer_vrf_id))
+ ;
+ else if (unformat (i, "adj %U/%d", unformat_ip4_address,
+ &adj_address, &tmp)) {
+ adj_address_length = tmp;
+ adj_address_set = 1;
+ }
+ else if (unformat (i, "next-hop %U", unformat_ip4_address,
+ &next_hop_address))
+ next_hop_address_set = 1;
+ else if (unformat (i, "resolve-attempts %d", &resolve_attempts))
+ ;
+ else if (unformat (i, "resolve-if-needed %d", &tmp))
+ resolve_if_needed = tmp;
+ else if (unformat (i, "l2-only"))
+ l2_only = 1;
+ else if (unformat (i, "del"))
+ is_add = 0;
+ else {
+ clib_warning ("parse error '%U'", format_unformat_error, i);
+ return -99;
+ }
+ }
+
+ if (!adj_address_set) {
+ errmsg ("adjacency address/mask not set\n");
+ return -99;
+ }
+ if (!next_hop_address_set) {
+ errmsg ("ip4 next hop address (in outer fib) not set\n");
+ return -99;
+ }
+
+ M(MPLS_ETHERNET_ADD_DEL_TUNNEL_2, mpls_ethernet_add_del_tunnel_2);
+
+ mp->inner_vrf_id = ntohl(inner_vrf_id);
+ mp->outer_vrf_id = ntohl(outer_vrf_id);
+ mp->resolve_attempts = ntohl(resolve_attempts);
+ mp->resolve_if_needed = resolve_if_needed;
+ mp->is_add = is_add;
+ mp->l2_only = l2_only;
+ clib_memcpy (mp->adj_address, &adj_address, sizeof (adj_address));
+ mp->adj_address_length = adj_address_length;
+ clib_memcpy (mp->next_hop_ip4_address_in_outer_vrf, &next_hop_address,
+ sizeof (next_hop_address));
+
+ S; W;
+ /* NOTREACHED */
+ return 0;
+}
+
+static int api_sw_interface_set_unnumbered (vat_main_t * vam)
+{
+ unformat_input_t * i = vam->input;
+ vl_api_sw_interface_set_unnumbered_t *mp;
+ f64 timeout;
+ u32 sw_if_index;
+ u32 unnum_sw_index;
+ u8 is_add = 1;
+ u8 sw_if_index_set = 0;
+
+ while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
+ if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
+ sw_if_index_set = 1;
+ else if (unformat (i, "sw_if_index %d", &sw_if_index))
+ sw_if_index_set = 1;
+ else if (unformat (i, "unnum_if_index %d", &unnum_sw_index))
+ ;
+ else if (unformat (i, "del"))
+ is_add = 0;
+ else {
+ clib_warning ("parse error '%U'", format_unformat_error, i);
+ return -99;
+ }
+ }
+
+ if (sw_if_index_set == 0) {
+ errmsg ("missing interface name or sw_if_index\n");
+ return -99;
+ }