+ /* 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);
+ }
+ }
+
+ /* ip4 nbr counters */
+ msg_array = vat_json_object_add (&node, "ip4_nbr_counters");
+ vat_json_init_array (msg_array);
+ for (i = 0; i < vec_len (vam->ip4_nbr_counters); i++)
+ {
+ msg = vat_json_array_add (msg_array);
+ vat_json_init_object (msg);
+ vat_json_object_add_uint (msg, "sw_if_index", i);
+ counter_array = vat_json_object_add (msg, "c");
+ vat_json_init_array (counter_array);
+ for (j = 0; j < vec_len (vam->ip4_nbr_counters[i]); j++)
+ {
+ counter = vat_json_array_add (counter_array);
+ vat_json_init_object (counter);
+ n4 = &vam->ip4_nbr_counters[i][j];
+ vat_json_object_add_ip4 (counter, "address", n4->address);
+ vat_json_object_add_uint (counter, "link-type", n4->linkt);
+ vat_json_object_add_uint (counter, "packets", n4->packets);
+ vat_json_object_add_uint (counter, "bytes", n4->bytes);
+ }
+ }
+
+ /* ip6 nbr counters */
+ msg_array = vat_json_object_add (&node, "ip6_nbr_counters");
+ vat_json_init_array (msg_array);
+ for (i = 0; i < vec_len (vam->ip6_nbr_counters); i++)
+ {
+ msg = vat_json_array_add (msg_array);
+ vat_json_init_object (msg);
+ vat_json_object_add_uint (msg, "sw_if_index", i);
+ counter_array = vat_json_object_add (msg, "c");
+ vat_json_init_array (counter_array);
+ for (j = 0; j < vec_len (vam->ip6_nbr_counters[i]); j++)
+ {
+ counter = vat_json_array_add (counter_array);
+ vat_json_init_object (counter);
+ n6 = &vam->ip6_nbr_counters[i][j];
+ vat_json_object_add_ip6 (counter, "address", n6->address);
+ vat_json_object_add_uint (counter, "packets", n6->packets);
+ vat_json_object_add_uint (counter, "bytes", n6->bytes);
+ }
+ }
+
+ vat_json_print (vam->ofp, &node);
+ vat_json_free (&node);
+
+ return 0;
+}
+
+/*
+ * Pass CLI buffers directly in the CLI_INBAND API message,
+ * instead of an additional shared memory area.
+ */
+static int
+exec_inband (vat_main_t * vam)
+{
+ vl_api_cli_inband_t *mp;
+ unformat_input_t *i = vam->input;
+ int ret;
+
+ 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;
+ }
+
+ /*
+ * In order for the CLI command to work, it
+ * must be a vector ending in \n, not a C-string ending
+ * in \n\0.
+ */
+ u32 len = vec_len (vam->input->buffer);
+ M2 (CLI_INBAND, mp, len);
+ clib_memcpy (mp->cmd, vam->input->buffer, len);
+ mp->length = htonl (len);
+
+ S (mp);
+ W (ret);
+ /* json responses may or may not include a useful reply... */
+ if (vec_len (vam->cmd_reply))
+ print (vam->ofp, "%v", (char *) (vam->cmd_reply));
+ return ret;
+}
+
+int
+exec (vat_main_t * vam)
+{
+ return exec_inband (vam);
+}
+
+static int
+api_create_loopback (vat_main_t * vam)
+{
+ unformat_input_t *i = vam->input;
+ vl_api_create_loopback_t *mp;
+ vl_api_create_loopback_instance_t *mp_lbi;
+ u8 mac_address[6];
+ u8 mac_set = 0;
+ u8 is_specified = 0;
+ u32 user_instance = 0;
+ int ret;
+
+ 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;
+ if (unformat (i, "instance %d", &user_instance))
+ is_specified = 1;
+ else
+ break;
+ }
+
+ if (is_specified)
+ {
+ M (CREATE_LOOPBACK_INSTANCE, mp_lbi);
+ mp_lbi->is_specified = is_specified;
+ if (is_specified)
+ mp_lbi->user_instance = htonl (user_instance);
+ if (mac_set)
+ clib_memcpy (mp_lbi->mac_address, mac_address, sizeof (mac_address));
+ S (mp_lbi);
+ }
+ else
+ {
+ /* Construct the API message */
+ M (CREATE_LOOPBACK, mp);
+ if (mac_set)
+ clib_memcpy (mp->mac_address, mac_address, sizeof (mac_address));
+ S (mp);
+ }
+
+ W (ret);
+ return ret;
+}
+
+static int
+api_delete_loopback (vat_main_t * vam)
+{
+ unformat_input_t *i = vam->input;
+ vl_api_delete_loopback_t *mp;
+ u32 sw_if_index = ~0;
+ int ret;
+
+ 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");
+ return -99;
+ }
+
+ /* Construct the API message */
+ M (DELETE_LOOPBACK, mp);
+ mp->sw_if_index = ntohl (sw_if_index);
+
+ S (mp);
+ W (ret);
+ return ret;
+}
+
+static int
+api_want_stats (vat_main_t * vam)
+{
+ unformat_input_t *i = vam->input;
+ vl_api_want_stats_t *mp;
+ int enable = -1;
+ int ret;
+
+ 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");
+ return -99;
+ }
+
+ M (WANT_STATS, mp);
+ mp->enable_disable = enable;
+
+ S (mp);
+ W (ret);
+ return ret;
+}
+
+static int
+api_want_interface_events (vat_main_t * vam)
+{
+ unformat_input_t *i = vam->input;
+ vl_api_want_interface_events_t *mp;
+ int enable = -1;
+ int ret;
+
+ 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");
+ return -99;
+ }
+
+ M (WANT_INTERFACE_EVENTS, mp);
+ mp->enable_disable = enable;
+
+ vam->interface_event_display = enable;
+
+ S (mp);
+ W (ret);
+ return ret;
+}
+
+
+/* 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;
+ vl_api_control_ping_t *mp_ping;
+ hash_pair_t *p;
+ name_sort_t *nses = 0, *ns;
+ sw_interface_subif_t *sub = NULL;
+ int ret;
+
+ /* Toss the old name table */
+ /* *INDENT-OFF* */
+ 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];
+ }));
+ /* *INDENT-ON* */
+
+ 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));
+
+ /*
+ * Ask for all interface names. Otherwise, the epic catalog of
+ * name filters becomes ridiculously long, and vat ends up needing
+ * to be taught about new interface types.
+ */
+ M (SW_INTERFACE_DUMP, mp);
+ S (mp);
+
+ /* Use a control ping for synchronization */
+ MPING (CONTROL_PING, mp_ping);
+ S (mp_ping);
+
+ W (ret);
+ return ret;
+}
+
+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;
+ u32 sw_if_index;
+ u8 sw_if_index_set = 0;
+ u8 admin_up = 0;
+ int ret;