+ vec_validate_aligned (match, len - 1, sizeof (u32x4));
+
+ if (dst)
+ clib_memcpy (match, dst_val, 6);
+
+ if (src)
+ clib_memcpy (match + 6, src_val, 6);
+
+ if (tag2)
+ {
+ /* inner vlan tag */
+ match[19] = tag2_val[1];
+ match[18] = tag2_val[0];
+ if (cos2)
+ match[18] |= (cos2_val & 0x7) << 5;
+ if (proto)
+ {
+ match[21] = proto_val & 0xff;
+ match[20] = proto_val >> 8;
+ }
+ if (tag1)
+ {
+ match[15] = tag1_val[1];
+ match[14] = tag1_val[0];
+ }
+ if (cos1)
+ match[14] |= (cos1_val & 0x7) << 5;
+ *matchp = match;
+ return 1;
+ }
+ if (tag1)
+ {
+ match[15] = tag1_val[1];
+ match[14] = tag1_val[0];
+ if (proto)
+ {
+ match[17] = proto_val & 0xff;
+ match[16] = proto_val >> 8;
+ }
+ if (cos1)
+ match[14] |= (cos1_val & 0x7) << 5;
+
+ *matchp = match;
+ return 1;
+ }
+ if (cos2)
+ match[18] |= (cos2_val & 0x7) << 5;
+ if (cos1)
+ match[14] |= (cos1_val & 0x7) << 5;
+ if (proto)
+ {
+ match[13] = proto_val & 0xff;
+ match[12] = proto_val >> 8;
+ }
+
+ *matchp = match;
+ return 1;
+}
+
+
+uword
+unformat_classify_match (unformat_input_t * input, va_list * args)
+{
+ u8 **matchp = va_arg (*args, u8 **);
+ u32 skip_n_vectors = va_arg (*args, u32);
+ u32 match_n_vectors = va_arg (*args, u32);
+
+ u8 *match = 0;
+ u8 *l2 = 0;
+ u8 *l3 = 0;
+
+ while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (input, "hex %U", unformat_hex_string, &match))
+ ;
+ else if (unformat (input, "l2 %U", unformat_l2_match, &l2))
+ ;
+ else if (unformat (input, "l3 %U", unformat_l3_match, &l3))
+ ;
+ else
+ break;
+ }
+
+ if (match || l2 || l3)
+ {
+ if (l2 || l3)
+ {
+ /* "Win a free Ethernet header in every packet" */
+ if (l2 == 0)
+ vec_validate_aligned (l2, 13, sizeof (u32x4));
+ match = l2;
+ vec_append_aligned (match, l3, sizeof (u32x4));
+ vec_free (l3);
+ }
+
+ /* Make sure the vector is big enough even if key is all 0's */
+ vec_validate_aligned
+ (match, ((match_n_vectors + skip_n_vectors) * sizeof (u32x4)) - 1,
+ sizeof (u32x4));
+
+ /* Set size, include skipped vectors */
+ _vec_len (match) = (match_n_vectors + skip_n_vectors) * sizeof (u32x4);
+
+ *matchp = match;
+
+ return 1;
+ }
+
+ return 0;
+}
+
+static int
+api_classify_add_del_session (vat_main_t * vam)
+{
+ unformat_input_t *i = vam->input;
+ vl_api_classify_add_del_session_t *mp;
+ int is_add = 1;
+ u32 table_index = ~0;
+ u32 hit_next_index = ~0;
+ u32 opaque_index = ~0;
+ u8 *match = 0;
+ i32 advance = 0;
+ f64 timeout;
+ u32 skip_n_vectors = 0;
+ u32 match_n_vectors = 0;
+
+ /*
+ * Warning: you have to supply skip_n and match_n
+ * because the API client cant simply look at the classify
+ * table object.
+ */
+
+ while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (i, "del"))
+ is_add = 0;
+ else if (unformat (i, "hit-next %U", unformat_ip_next_index,
+ &hit_next_index))
+ ;
+ else if (unformat (i, "l2-hit-next %U", unformat_l2_next_index,
+ &hit_next_index))
+ ;
+ else if (unformat (i, "acl-hit-next %U", unformat_acl_next_index,
+ &hit_next_index))
+ ;
+ else if (unformat (i, "policer-hit-next %d", &hit_next_index))
+ ;
+ else if (unformat (i, "%U", unformat_policer_precolor, &opaque_index))
+ ;
+ else if (unformat (i, "opaque-index %d", &opaque_index))
+ ;
+ else if (unformat (i, "skip_n %d", &skip_n_vectors))
+ ;
+ else if (unformat (i, "match_n %d", &match_n_vectors))
+ ;
+ else if (unformat (i, "match %U", unformat_classify_match,
+ &match, skip_n_vectors, match_n_vectors))
+ ;
+ else if (unformat (i, "advance %d", &advance))
+ ;
+ else if (unformat (i, "table-index %d", &table_index))
+ ;
+ else
+ break;
+ }
+
+ if (table_index == ~0)
+ {
+ errmsg ("Table index required\n");
+ return -99;
+ }
+
+ if (is_add && match == 0)
+ {
+ errmsg ("Match value required\n");
+ return -99;
+ }
+
+ M2 (CLASSIFY_ADD_DEL_SESSION, classify_add_del_session, vec_len (match));
+
+ mp->is_add = is_add;
+ mp->table_index = ntohl (table_index);
+ mp->hit_next_index = ntohl (hit_next_index);
+ mp->opaque_index = ntohl (opaque_index);
+ mp->advance = ntohl (advance);
+ clib_memcpy (mp->match, match, vec_len (match));
+ vec_free (match);
+
+ S;
+ W;
+ /* NOTREACHED */
+}
+
+static int
+api_classify_set_interface_ip_table (vat_main_t * vam)
+{
+ unformat_input_t *i = vam->input;
+ vl_api_classify_set_interface_ip_table_t *mp;
+ f64 timeout;
+ u32 sw_if_index;
+ int sw_if_index_set;
+ u32 table_index = ~0;
+ u8 is_ipv6 = 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, "table %d", &table_index))
+ ;
+ 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 (CLASSIFY_SET_INTERFACE_IP_TABLE, classify_set_interface_ip_table);
+
+ mp->sw_if_index = ntohl (sw_if_index);
+ mp->table_index = ntohl (table_index);
+ mp->is_ipv6 = is_ipv6;
+
+ S;
+ W;
+ /* NOTREACHED */
+ return 0;
+}
+
+static int
+api_classify_set_interface_l2_tables (vat_main_t * vam)
+{
+ unformat_input_t *i = vam->input;
+ vl_api_classify_set_interface_l2_tables_t *mp;
+ f64 timeout;
+ u32 sw_if_index;
+ int sw_if_index_set;
+ u32 ip4_table_index = ~0;
+ u32 ip6_table_index = ~0;
+ u32 other_table_index = ~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, "ip4-table %d", &ip4_table_index))
+ ;
+ else if (unformat (i, "ip6-table %d", &ip6_table_index))
+ ;
+ else if (unformat (i, "other-table %d", &other_table_index))
+ ;
+ 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 (CLASSIFY_SET_INTERFACE_L2_TABLES, classify_set_interface_l2_tables);
+
+ mp->sw_if_index = ntohl (sw_if_index);
+ mp->ip4_table_index = ntohl (ip4_table_index);
+ mp->ip6_table_index = ntohl (ip6_table_index);
+ mp->other_table_index = ntohl (other_table_index);
+
+
+ S;
+ W;
+ /* NOTREACHED */
+ return 0;
+}
+
+static int
+api_ipfix_enable (vat_main_t * vam)
+{
+ unformat_input_t *i = vam->input;
+ vl_api_ipfix_enable_t *mp;
+ ip4_address_t collector_address;
+ u8 collector_address_set = 0;
+ u32 collector_port = ~0;
+ ip4_address_t src_address;
+ u8 src_address_set = 0;
+ u32 vrf_id = ~0;
+ u32 path_mtu = ~0;
+ u32 template_interval = ~0;
+ f64 timeout;
+
+ while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (i, "collector_address %U", unformat_ip4_address,
+ &collector_address))
+ collector_address_set = 1;
+ else if (unformat (i, "collector_port %d", &collector_port))
+ ;
+ else if (unformat (i, "src_address %U", unformat_ip4_address,
+ &src_address))
+ src_address_set = 1;
+ else if (unformat (i, "vrf_id %d", &vrf_id))
+ ;
+ else if (unformat (i, "path_mtu %d", &path_mtu))
+ ;
+ else if (unformat (i, "template_interval %d", &template_interval))
+ ;
+ else
+ break;
+ }
+
+ if (collector_address_set == 0)
+ {
+ errmsg ("collector_address required\n");
+ return -99;
+ }
+
+ if (src_address_set == 0)
+ {
+ errmsg ("src_address required\n");
+ return -99;
+ }
+
+ M (IPFIX_ENABLE, ipfix_enable);
+
+ memcpy (mp->collector_address, collector_address.data,
+ sizeof (collector_address.data));
+ mp->collector_port = htons ((u16) collector_port);
+ memcpy (mp->src_address, src_address.data, sizeof (src_address.data));
+ mp->vrf_id = htonl (vrf_id);
+ mp->path_mtu = htonl (path_mtu);
+ mp->template_interval = htonl (template_interval);
+
+ S;
+ W;
+ /* NOTREACHED */
+}
+
+static int
+api_get_node_index (vat_main_t * vam)
+{
+ unformat_input_t *i = vam->input;
+ vl_api_get_node_index_t *mp;
+ f64 timeout;
+ u8 *name = 0;
+
+ while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (i, "node %s", &name))
+ ;
+ else
+ break;
+ }
+ if (name == 0)
+ {
+ errmsg ("node name required\n");
+ return -99;
+ }
+ if (vec_len (name) >= ARRAY_LEN (mp->node_name))
+ {
+ errmsg ("node name too long, max %d\n", ARRAY_LEN (mp->node_name));
+ return -99;
+ }
+
+ M (GET_NODE_INDEX, get_node_index);
+ clib_memcpy (mp->node_name, name, vec_len (name));
+ vec_free (name);
+
+ S;
+ W;
+ /* NOTREACHED */
+ return 0;
+}
+
+static int
+api_get_next_index (vat_main_t * vam)
+{
+ unformat_input_t *i = vam->input;
+ vl_api_get_next_index_t *mp;
+ f64 timeout;
+ u8 *node_name = 0, *next_node_name = 0;
+
+ while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (i, "node-name %s", &node_name))
+ ;
+ else if (unformat (i, "next-node-name %s", &next_node_name))
+ break;
+ }
+
+ if (node_name == 0)
+ {
+ errmsg ("node name required\n");
+ return -99;
+ }
+ if (vec_len (node_name) >= ARRAY_LEN (mp->node_name))
+ {
+ errmsg ("node name too long, max %d\n", ARRAY_LEN (mp->node_name));
+ return -99;
+ }
+
+ if (next_node_name == 0)
+ {
+ errmsg ("next node name required\n");
+ return -99;
+ }
+ if (vec_len (next_node_name) >= ARRAY_LEN (mp->next_name))
+ {
+ errmsg ("next node name too long, max %d\n", ARRAY_LEN (mp->next_name));
+ return -99;
+ }
+
+ M (GET_NEXT_INDEX, get_next_index);
+ clib_memcpy (mp->node_name, node_name, vec_len (node_name));
+ clib_memcpy (mp->next_name, next_node_name, vec_len (next_node_name));
+ vec_free (node_name);
+ vec_free (next_node_name);
+
+ S;
+ W;
+ /* NOTREACHED */
+ return 0;
+}
+
+static int
+api_add_node_next (vat_main_t * vam)
+{
+ unformat_input_t *i = vam->input;
+ vl_api_add_node_next_t *mp;
+ f64 timeout;
+ u8 *name = 0;
+ u8 *next = 0;
+
+ while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (i, "node %s", &name))
+ ;
+ else if (unformat (i, "next %s", &next))
+ ;
+ else
+ break;
+ }
+ if (name == 0)
+ {
+ errmsg ("node name required\n");
+ return -99;
+ }
+ if (vec_len (name) >= ARRAY_LEN (mp->node_name))
+ {
+ errmsg ("node name too long, max %d\n", ARRAY_LEN (mp->node_name));
+ return -99;
+ }
+ if (next == 0)
+ {
+ errmsg ("next node required\n");
+ return -99;
+ }
+ if (vec_len (next) >= ARRAY_LEN (mp->next_name))
+ {
+ errmsg ("next name too long, max %d\n", ARRAY_LEN (mp->next_name));
+ return -99;
+ }
+
+ M (ADD_NODE_NEXT, add_node_next);
+ clib_memcpy (mp->node_name, name, vec_len (name));
+ clib_memcpy (mp->next_name, next, vec_len (next));
+ vec_free (name);
+ vec_free (next);
+
+ S;
+ W;
+ /* NOTREACHED */
+ return 0;
+}
+
+static int
+api_l2tpv3_create_tunnel (vat_main_t * vam)
+{
+ unformat_input_t *i = vam->input;
+ ip6_address_t client_address, our_address;
+ int client_address_set = 0;
+ int our_address_set = 0;
+ u32 local_session_id = 0;
+ u32 remote_session_id = 0;
+ u64 local_cookie = 0;
+ u64 remote_cookie = 0;
+ u8 l2_sublayer_present = 0;
+ vl_api_l2tpv3_create_tunnel_t *mp;
+ f64 timeout;
+
+ while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (i, "client_address %U", unformat_ip6_address,
+ &client_address))
+ client_address_set = 1;
+ else if (unformat (i, "our_address %U", unformat_ip6_address,
+ &our_address))
+ our_address_set = 1;
+ else if (unformat (i, "local_session_id %d", &local_session_id))
+ ;
+ else if (unformat (i, "remote_session_id %d", &remote_session_id))
+ ;
+ else if (unformat (i, "local_cookie %lld", &local_cookie))
+ ;
+ else if (unformat (i, "remote_cookie %lld", &remote_cookie))
+ ;
+ else if (unformat (i, "l2-sublayer-present"))
+ l2_sublayer_present = 1;
+ else
+ break;
+ }
+
+ if (client_address_set == 0)
+ {
+ errmsg ("client_address required\n");
+ return -99;
+ }
+
+ if (our_address_set == 0)
+ {
+ errmsg ("our_address required\n");
+ return -99;
+ }
+
+ M (L2TPV3_CREATE_TUNNEL, l2tpv3_create_tunnel);
+
+ clib_memcpy (mp->client_address, client_address.as_u8,
+ sizeof (mp->client_address));
+
+ clib_memcpy (mp->our_address, our_address.as_u8, sizeof (mp->our_address));
+
+ mp->local_session_id = ntohl (local_session_id);
+ mp->remote_session_id = ntohl (remote_session_id);
+ mp->local_cookie = clib_host_to_net_u64 (local_cookie);
+ mp->remote_cookie = clib_host_to_net_u64 (remote_cookie);
+ mp->l2_sublayer_present = l2_sublayer_present;
+ mp->is_ipv6 = 1;
+
+ S;
+ W;
+ /* NOTREACHED */
+ return 0;
+}
+
+static int
+api_l2tpv3_set_tunnel_cookies (vat_main_t * vam)
+{
+ unformat_input_t *i = vam->input;
+ u32 sw_if_index;
+ u8 sw_if_index_set = 0;
+ u64 new_local_cookie = 0;
+ u64 new_remote_cookie = 0;
+ vl_api_l2tpv3_set_tunnel_cookies_t *mp;
+ f64 timeout;
+
+ 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, "new_local_cookie %lld", &new_local_cookie))
+ ;
+ else if (unformat (i, "new_remote_cookie %lld", &new_remote_cookie))
+ ;
+ else
+ break;
+ }
+
+ if (sw_if_index_set == 0)
+ {
+ errmsg ("missing interface name or sw_if_index\n");
+ return -99;
+ }
+
+ M (L2TPV3_SET_TUNNEL_COOKIES, l2tpv3_set_tunnel_cookies);
+
+ mp->sw_if_index = ntohl (sw_if_index);
+ mp->new_local_cookie = clib_host_to_net_u64 (new_local_cookie);
+ mp->new_remote_cookie = clib_host_to_net_u64 (new_remote_cookie);
+
+ S;
+ W;
+ /* NOTREACHED */
+ return 0;
+}
+
+static int
+api_l2tpv3_interface_enable_disable (vat_main_t * vam)
+{
+ unformat_input_t *i = vam->input;
+ vl_api_l2tpv3_interface_enable_disable_t *mp;
+ f64 timeout;
+ u32 sw_if_index;
+ u8 sw_if_index_set = 0;
+ u8 enable_disable = 1;
+
+ 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_disable = 1;
+ else if (unformat (i, "disable"))
+ enable_disable = 0;
+ else
+ break;
+ }
+
+ if (sw_if_index_set == 0)
+ {
+ errmsg ("missing interface name or sw_if_index\n");
+ return -99;
+ }
+
+ M (L2TPV3_INTERFACE_ENABLE_DISABLE, l2tpv3_interface_enable_disable);
+
+ mp->sw_if_index = ntohl (sw_if_index);
+ mp->enable_disable = enable_disable;
+
+ S;
+ W;
+ /* NOTREACHED */
+ return 0;
+}
+
+static int
+api_l2tpv3_set_lookup_key (vat_main_t * vam)
+{
+ unformat_input_t *i = vam->input;
+ vl_api_l2tpv3_set_lookup_key_t *mp;
+ f64 timeout;
+ u8 key = ~0;
+
+ while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (i, "lookup_v6_src"))
+ key = L2T_LOOKUP_SRC_ADDRESS;
+ else if (unformat (i, "lookup_v6_dst"))
+ key = L2T_LOOKUP_DST_ADDRESS;
+ else if (unformat (i, "lookup_session_id"))
+ key = L2T_LOOKUP_SESSION_ID;
+ else
+ break;
+ }
+
+ if (key == (u8) ~ 0)
+ {
+ errmsg ("l2tp session lookup key unset\n");
+ return -99;
+ }
+
+ M (L2TPV3_SET_LOOKUP_KEY, l2tpv3_set_lookup_key);
+
+ mp->key = key;
+
+ S;
+ W;
+ /* NOTREACHED */
+ return 0;
+}
+
+static void vl_api_sw_if_l2tpv3_tunnel_details_t_handler
+ (vl_api_sw_if_l2tpv3_tunnel_details_t * mp)
+{
+ vat_main_t *vam = &vat_main;
+
+ fformat (vam->ofp, "* %U (our) %U (client) (sw_if_index %d)\n",
+ format_ip6_address, mp->our_address,
+ format_ip6_address, mp->client_address,
+ clib_net_to_host_u32 (mp->sw_if_index));
+
+ fformat (vam->ofp,
+ " local cookies %016llx %016llx remote cookie %016llx\n",
+ clib_net_to_host_u64 (mp->local_cookie[0]),
+ clib_net_to_host_u64 (mp->local_cookie[1]),
+ clib_net_to_host_u64 (mp->remote_cookie));
+
+ fformat (vam->ofp, " local session-id %d remote session-id %d\n",
+ clib_net_to_host_u32 (mp->local_session_id),
+ clib_net_to_host_u32 (mp->remote_session_id));
+
+ fformat (vam->ofp, " l2 specific sublayer %s\n\n",
+ mp->l2_sublayer_present ? "preset" : "absent");
+
+}
+
+static void vl_api_sw_if_l2tpv3_tunnel_details_t_handler_json
+ (vl_api_sw_if_l2tpv3_tunnel_details_t * mp)
+{
+ vat_main_t *vam = &vat_main;
+ vat_json_node_t *node = NULL;
+ struct in6_addr addr;
+
+ 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);
+
+ clib_memcpy (&addr, mp->our_address, sizeof (addr));
+ vat_json_object_add_ip6 (node, "our_address", addr);
+ clib_memcpy (&addr, mp->client_address, sizeof (addr));
+ vat_json_object_add_ip6 (node, "client_address", addr);
+
+ vat_json_node_t *lc = vat_json_object_add (node, "local_cookie");
+ vat_json_init_array (lc);
+ vat_json_array_add_uint (lc, clib_net_to_host_u64 (mp->local_cookie[0]));
+ vat_json_array_add_uint (lc, clib_net_to_host_u64 (mp->local_cookie[1]));
+ vat_json_object_add_uint (node, "remote_cookie",
+ clib_net_to_host_u64 (mp->remote_cookie));
+
+ printf ("local id: %u", clib_net_to_host_u32 (mp->local_session_id));
+ vat_json_object_add_uint (node, "local_session_id",
+ clib_net_to_host_u32 (mp->local_session_id));
+ vat_json_object_add_uint (node, "remote_session_id",
+ clib_net_to_host_u32 (mp->remote_session_id));
+ vat_json_object_add_string_copy (node, "l2_sublayer",
+ mp->l2_sublayer_present ? (u8 *) "present"
+ : (u8 *) "absent");
+}
+
+static int
+api_sw_if_l2tpv3_tunnel_dump (vat_main_t * vam)
+{
+ vl_api_sw_if_l2tpv3_tunnel_dump_t *mp;
+ f64 timeout;
+
+ /* Get list of l2tpv3-tunnel interfaces */
+ M (SW_IF_L2TPV3_TUNNEL_DUMP, sw_if_l2tpv3_tunnel_dump);
+ S;
+
+ /* Use a control ping for synchronization */
+ {
+ vl_api_control_ping_t *mp;
+ M (CONTROL_PING, control_ping);
+ S;
+ }
+ W;
+}
+
+
+static void vl_api_sw_interface_tap_details_t_handler
+ (vl_api_sw_interface_tap_details_t * mp)
+{
+ vat_main_t *vam = &vat_main;
+
+ fformat (vam->ofp, "%-16s %d\n",
+ mp->dev_name, clib_net_to_host_u32 (mp->sw_if_index));
+}
+
+static void vl_api_sw_interface_tap_details_t_handler_json
+ (vl_api_sw_interface_tap_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_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
+ vat_json_object_add_string_copy (node, "dev_name", mp->dev_name);
+}
+
+static int
+api_sw_interface_tap_dump (vat_main_t * vam)
+{
+ vl_api_sw_interface_tap_dump_t *mp;
+ f64 timeout;
+
+ fformat (vam->ofp, "\n%-16s %s\n", "dev_name", "sw_if_index");
+ /* Get list of tap interfaces */
+ M (SW_INTERFACE_TAP_DUMP, sw_interface_tap_dump);
+ S;
+
+ /* Use a control ping for synchronization */
+ {
+ vl_api_control_ping_t *mp;
+ M (CONTROL_PING, control_ping);
+ S;
+ }
+ W;
+}
+
+static uword unformat_vxlan_decap_next
+ (unformat_input_t * input, va_list * args)
+{
+ u32 *result = va_arg (*args, u32 *);
+ u32 tmp;
+
+ if (unformat (input, "drop"))
+ *result = VXLAN_INPUT_NEXT_DROP;
+ else if (unformat (input, "ip4"))
+ *result = VXLAN_INPUT_NEXT_IP4_INPUT;
+ else if (unformat (input, "ip6"))
+ *result = VXLAN_INPUT_NEXT_IP6_INPUT;
+ else if (unformat (input, "l2"))
+ *result = VXLAN_INPUT_NEXT_L2_INPUT;
+ else if (unformat (input, "%d", &tmp))
+ *result = tmp;
+ else
+ return 0;
+ return 1;
+}
+
+static int
+api_vxlan_add_del_tunnel (vat_main_t * vam)
+{
+ unformat_input_t *line_input = vam->input;
+ vl_api_vxlan_add_del_tunnel_t *mp;
+ f64 timeout;
+ ip4_address_t src4, dst4;
+ ip6_address_t src6, dst6;
+ u8 is_add = 1;
+ u8 ipv4_set = 0, ipv6_set = 0;
+ u8 src_set = 0;
+ u8 dst_set = 0;
+ u32 encap_vrf_id = 0;
+ u32 decap_next_index = ~0;
+ u32 vni = 0;
+
+ while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (line_input, "del"))
+ is_add = 0;
+ else if (unformat (line_input, "src %U", unformat_ip4_address, &src4))
+ {
+ ipv4_set = 1;
+ src_set = 1;
+ }
+ else if (unformat (line_input, "dst %U", unformat_ip4_address, &dst4))
+ {
+ ipv4_set = 1;
+ dst_set = 1;
+ }
+ else if (unformat (line_input, "src %U", unformat_ip6_address, &src6))
+ {
+ ipv6_set = 1;
+ src_set = 1;
+ }
+ else if (unformat (line_input, "dst %U", unformat_ip6_address, &dst6))
+ {
+ ipv6_set = 1;
+ dst_set = 1;
+ }
+ else if (unformat (line_input, "encap-vrf-id %d", &encap_vrf_id))
+ ;
+ else if (unformat (line_input, "decap-next %U",
+ unformat_vxlan_decap_next, &decap_next_index))
+ ;
+ else if (unformat (line_input, "vni %d", &vni))
+ ;
+ else
+ {
+ errmsg ("parse error '%U'\n", format_unformat_error, line_input);
+ return -99;
+ }
+ }
+
+ if (src_set == 0)
+ {
+ errmsg ("tunnel src address not specified\n");
+ return -99;
+ }
+ if (dst_set == 0)
+ {
+ errmsg ("tunnel dst address not specified\n");
+ return -99;
+ }