+ /* NOTREACHED */
+ return 0;
+}
+
+int
+api_ip_source_and_port_range_check_add_del (vat_main_t * vam)
+{
+ unformat_input_t *input = vam->input;
+ vl_api_ip_source_and_port_range_check_add_del_t *mp;
+ f64 timeout;
+
+ u16 *low_ports = 0;
+ u16 *high_ports = 0;
+ u16 this_low;
+ u16 this_hi;
+ ip4_address_t ip4_addr;
+ ip6_address_t ip6_addr;
+ u32 length;
+ u32 tmp, tmp2;
+ u8 prefix_set = 0;
+ u32 vrf_id = ~0;
+ u8 is_add = 1;
+ u8 is_ipv6 = 0;
+
+ while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (input, "%U/%d", unformat_ip4_address, &ip4_addr, &length))
+ {
+ prefix_set = 1;
+ }
+ else
+ if (unformat
+ (input, "%U/%d", unformat_ip6_address, &ip6_addr, &length))
+ {
+ prefix_set = 1;
+ is_ipv6 = 1;
+ }
+ else if (unformat (input, "vrf %d", &vrf_id))
+ ;
+ else if (unformat (input, "del"))
+ is_add = 0;
+ else if (unformat (input, "port %d", &tmp))
+ {
+ if (tmp == 0 || tmp > 65535)
+ {
+ errmsg ("port %d out of range", tmp);
+ return -99;
+ }
+ this_low = tmp;
+ this_hi = this_low + 1;
+ vec_add1 (low_ports, this_low);
+ vec_add1 (high_ports, this_hi);
+ }
+ else if (unformat (input, "range %d - %d", &tmp, &tmp2))
+ {
+ if ((tmp > tmp2) || (tmp == 0) || (tmp2 > 65535))
+ {
+ errmsg ("incorrect range parameters\n");
+ return -99;
+ }
+ this_low = tmp;
+ /* Note: in debug CLI +1 is added to high before
+ passing to real fn that does "the work"
+ (ip_source_and_port_range_check_add_del).
+ This fn is a wrapper around the binary API fn a
+ control plane will call, which expects this increment
+ to have occurred. Hence letting the binary API control
+ plane fn do the increment for consistency between VAT
+ and other control planes.
+ */
+ this_hi = tmp2;
+ vec_add1 (low_ports, this_low);
+ vec_add1 (high_ports, this_hi);
+ }
+ else
+ break;
+ }
+
+ if (prefix_set == 0)
+ {
+ errmsg ("<address>/<mask> not specified\n");
+ return -99;
+ }
+
+ if (vrf_id == ~0)
+ {
+ errmsg ("VRF ID required, not specified\n");
+ return -99;
+ }
+
+ if (vrf_id == 0)
+ {
+ errmsg
+ ("VRF ID should not be default. Should be distinct VRF for this purpose.\n");
+ return -99;
+ }
+
+ if (vec_len (low_ports) == 0)
+ {
+ errmsg ("At least one port or port range required\n");
+ return -99;
+ }
+
+ M (IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL,
+ ip_source_and_port_range_check_add_del);
+
+ mp->is_add = is_add;
+
+ if (is_ipv6)
+ {
+ mp->is_ipv6 = 1;
+ clib_memcpy (mp->address, &ip6_addr, sizeof (ip6_addr));
+ }
+ else
+ {
+ mp->is_ipv6 = 0;
+ clib_memcpy (mp->address, &ip4_addr, sizeof (ip4_addr));
+ }
+
+ mp->mask_length = length;
+ mp->number_of_ranges = vec_len (low_ports);
+
+ clib_memcpy (mp->low_ports, low_ports, vec_len (low_ports));
+ vec_free (low_ports);
+
+ clib_memcpy (mp->high_ports, high_ports, vec_len (high_ports));
+ vec_free (high_ports);
+
+ mp->vrf_id = ntohl (vrf_id);
+
+ S;
+ W;
+ /* NOTREACHED */
+ return 0;
+}
+
+int
+api_ip_source_and_port_range_check_interface_add_del (vat_main_t * vam)
+{
+ unformat_input_t *input = vam->input;
+ vl_api_ip_source_and_port_range_check_interface_add_del_t *mp;
+ f64 timeout;
+ u32 sw_if_index = ~0;
+ int vrf_set = 0;
+ u32 tcp_out_vrf_id = ~0, udp_out_vrf_id = ~0;
+ u32 tcp_in_vrf_id = ~0, udp_in_vrf_id = ~0;
+ u8 is_add = 1;
+
+ while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (input, "%U", unformat_sw_if_index, vam, &sw_if_index))
+ ;
+ else if (unformat (input, "sw_if_index %d", &sw_if_index))
+ ;
+ else if (unformat (input, "tcp-out-vrf %d", &tcp_out_vrf_id))
+ vrf_set = 1;
+ else if (unformat (input, "udp-out-vrf %d", &udp_out_vrf_id))
+ vrf_set = 1;
+ else if (unformat (input, "tcp-in-vrf %d", &tcp_in_vrf_id))
+ vrf_set = 1;
+ else if (unformat (input, "udp-in-vrf %d", &udp_in_vrf_id))
+ vrf_set = 1;
+ else if (unformat (input, "del"))
+ is_add = 0;
+ else
+ break;
+ }
+
+ if (sw_if_index == ~0)
+ {
+ errmsg ("Interface required but not specified\n");
+ return -99;
+ }
+
+ if (vrf_set == 0)
+ {
+ errmsg ("VRF ID required but not specified\n");
+ return -99;
+ }
+
+ if (tcp_out_vrf_id == 0
+ || udp_out_vrf_id == 0 || tcp_in_vrf_id == 0 || udp_in_vrf_id == 0)
+ {
+ errmsg
+ ("VRF ID should not be default. Should be distinct VRF for this purpose.\n");
+ return -99;
+ }
+
+ /* Construct the API message */
+ M (IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL,
+ ip_source_and_port_range_check_interface_add_del);
+
+ mp->sw_if_index = ntohl (sw_if_index);
+ mp->is_add = is_add;
+ mp->tcp_out_vrf_id = ntohl (tcp_out_vrf_id);
+ mp->udp_out_vrf_id = ntohl (udp_out_vrf_id);
+ mp->tcp_in_vrf_id = ntohl (tcp_in_vrf_id);
+ mp->udp_in_vrf_id = ntohl (udp_in_vrf_id);
+
+ /* send it... */
+ S;
+
+ /* Wait for a reply... */
+ W;
+}
+
+static int
+api_ipsec_gre_add_del_tunnel (vat_main_t * vam)
+{
+ unformat_input_t *i = vam->input;
+ vl_api_ipsec_gre_add_del_tunnel_t *mp;
+ f64 timeout;
+ u32 local_sa_id = 0;
+ u32 remote_sa_id = 0;
+ ip4_address_t src_address;
+ ip4_address_t dst_address;
+ u8 is_add = 1;
+
+ while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (i, "local_sa %d", &local_sa_id))
+ ;
+ else if (unformat (i, "remote_sa %d", &remote_sa_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, "del"))
+ is_add = 0;
+ else
+ {
+ clib_warning ("parse error '%U'", format_unformat_error, i);
+ return -99;
+ }
+ }
+
+ M (IPSEC_GRE_ADD_DEL_TUNNEL, ipsec_gre_add_del_tunnel);
+
+ mp->local_sa_id = ntohl (local_sa_id);
+ mp->remote_sa_id = ntohl (remote_sa_id);
+ clib_memcpy (mp->src_address, &src_address, sizeof (src_address));
+ clib_memcpy (mp->dst_address, &dst_address, sizeof (dst_address));
+ mp->is_add = is_add;
+
+ S;
+ W;
+ /* NOTREACHED */
+ return 0;
+}
+
+static int
+api_punt (vat_main_t * vam)
+{
+ unformat_input_t *i = vam->input;
+ vl_api_punt_t *mp;
+ f64 timeout;
+ u32 ipv = ~0;
+ u32 protocol = ~0;
+ u32 port = ~0;
+ int is_add = 1;
+
+ while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (i, "ip %d", &ipv))
+ ;
+ else if (unformat (i, "protocol %d", &protocol))
+ ;
+ else if (unformat (i, "port %d", &port))
+ ;
+ else if (unformat (i, "del"))
+ is_add = 0;
+ else
+ {
+ clib_warning ("parse error '%U'", format_unformat_error, i);
+ return -99;
+ }
+ }
+
+ M (PUNT, punt);
+
+ mp->is_add = (u8) is_add;
+ mp->ipv = (u8) ipv;
+ mp->l4_protocol = (u8) protocol;
+ mp->l4_port = htons ((u16) port);
+
+ S;
+ W;
+ /* NOTREACHED */
+ return 0;
+}
+
+static void vl_api_ipsec_gre_tunnel_details_t_handler
+ (vl_api_ipsec_gre_tunnel_details_t * mp)
+{
+ vat_main_t *vam = &vat_main;
+
+ fformat (vam->ofp, "%11d%15U%15U%14d%14d\n",
+ ntohl (mp->sw_if_index),
+ format_ip4_address, &mp->src_address,
+ format_ip4_address, &mp->dst_address,
+ ntohl (mp->local_sa_id), ntohl (mp->remote_sa_id));
+}
+
+static void vl_api_ipsec_gre_tunnel_details_t_handler_json
+ (vl_api_ipsec_gre_tunnel_details_t * mp)
+{
+ vat_main_t *vam = &vat_main;
+ vat_json_node_t *node = NULL;
+ 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);
+ vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
+ clib_memcpy (&ip4, &mp->src_address, sizeof (ip4));
+ vat_json_object_add_ip4 (node, "src_address", ip4);
+ clib_memcpy (&ip4, &mp->dst_address, sizeof (ip4));
+ vat_json_object_add_ip4 (node, "dst_address", ip4);
+ vat_json_object_add_uint (node, "local_sa_id", ntohl (mp->local_sa_id));
+ vat_json_object_add_uint (node, "remote_sa_id", ntohl (mp->remote_sa_id));
+}
+
+static int
+api_ipsec_gre_tunnel_dump (vat_main_t * vam)
+{
+ unformat_input_t *i = vam->input;
+ vl_api_ipsec_gre_tunnel_dump_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, "sw_if_index %d", &sw_if_index))
+ sw_if_index_set = 1;
+ else
+ break;
+ }
+
+ if (sw_if_index_set == 0)
+ {
+ sw_if_index = ~0;
+ }
+
+ if (!vam->json_output)
+ {
+ fformat (vam->ofp, "%11s%15s%15s%14s%14s\n",
+ "sw_if_index", "src_address", "dst_address",
+ "local_sa_id", "remote_sa_id");
+ }
+
+ /* Get list of gre-tunnel interfaces */
+ M (IPSEC_GRE_TUNNEL_DUMP, ipsec_gre_tunnel_dump);
+
+ mp->sw_if_index = htonl (sw_if_index);
+
+ S;
+
+ /* Use a control ping for synchronization */
+ {
+ vl_api_control_ping_t *mp;
+ M (CONTROL_PING, control_ping);
+ S;
+ }
+ W;
+}
+
+static int
+api_delete_subif (vat_main_t * vam)
+{
+ unformat_input_t *i = vam->input;
+ vl_api_delete_subif_t *mp;
+ f64 timeout;
+ u32 sw_if_index = ~0;
+
+ while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
+ ;
+ 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_SUBIF, delete_subif);
+ mp->sw_if_index = ntohl (sw_if_index);
+
+ S;
+ W;
+}
+
+#define foreach_pbb_vtr_op \
+_("disable", L2_VTR_DISABLED) \
+_("pop", L2_VTR_POP_2) \
+_("push", L2_VTR_PUSH_2)
+
+static int
+api_l2_interface_pbb_tag_rewrite (vat_main_t * vam)
+{
+ unformat_input_t *i = vam->input;
+ vl_api_l2_interface_pbb_tag_rewrite_t *mp;
+ f64 timeout;
+ u32 sw_if_index = ~0, vtr_op = ~0;
+ u16 outer_tag = ~0;
+ u8 dmac[6], smac[6];
+ u8 dmac_set = 0, smac_set = 0;
+ u16 vlanid = 0;
+ u32 sid = ~0;
+ u32 tmp;
+
+ /* Shut up coverity */
+ memset (dmac, 0, sizeof (dmac));
+ memset (smac, 0, sizeof (smac));
+
+ while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
+ ;
+ else if (unformat (i, "sw_if_index %d", &sw_if_index))
+ ;
+ else if (unformat (i, "vtr_op %d", &vtr_op))
+ ;
+#define _(n,v) else if (unformat(i, n)) {vtr_op = v;}
+ foreach_pbb_vtr_op
+#undef _
+ else if (unformat (i, "translate_pbb_stag"))
+ {
+ if (unformat (i, "%d", &tmp))
+ {
+ vtr_op = L2_VTR_TRANSLATE_2_1;
+ outer_tag = tmp;
+ }
+ else
+ {
+ errmsg
+ ("translate_pbb_stag operation requires outer tag definition\n");
+ return -99;
+ }
+ }
+ else if (unformat (i, "dmac %U", unformat_ethernet_address, dmac))
+ dmac_set++;
+ else if (unformat (i, "smac %U", unformat_ethernet_address, smac))
+ smac_set++;
+ else if (unformat (i, "sid %d", &sid))
+ ;
+ else if (unformat (i, "vlanid %d", &tmp))
+ vlanid = tmp;
+ else
+ {
+ clib_warning ("parse error '%U'", format_unformat_error, i);
+ return -99;
+ }
+ }
+
+ if ((sw_if_index == ~0) || (vtr_op == ~0))
+ {
+ errmsg ("missing sw_if_index or vtr operation\n");
+ return -99;
+ }
+ if (((vtr_op == L2_VTR_PUSH_2) || (vtr_op == L2_VTR_TRANSLATE_2_2))
+ && ((dmac_set == 0) || (smac_set == 0) || (sid == ~0)))
+ {
+ errmsg
+ ("push and translate_qinq operations require dmac, smac, sid and optionally vlanid\n");
+ return -99;
+ }
+
+ M (L2_INTERFACE_PBB_TAG_REWRITE, l2_interface_pbb_tag_rewrite);
+ mp->sw_if_index = ntohl (sw_if_index);
+ mp->vtr_op = ntohl (vtr_op);
+ mp->outer_tag = ntohs (outer_tag);
+ clib_memcpy (mp->b_dmac, dmac, sizeof (dmac));
+ clib_memcpy (mp->b_smac, smac, sizeof (smac));
+ mp->b_vlanid = ntohs (vlanid);
+ mp->i_sid = ntohl (sid);
+
+ S;
+ W;
+ /* NOTREACHED */
+ return 0;
+}
+
+static int
+api_flow_classify_set_interface (vat_main_t * vam)
+{
+ unformat_input_t *i = vam->input;
+ vl_api_flow_classify_set_interface_t *mp;
+ f64 timeout;
+ u32 sw_if_index;
+ int sw_if_index_set;
+ u32 ip4_table_index = ~0;
+ u32 ip6_table_index = ~0;
+ u8 is_add = 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, "del"))
+ is_add = 0;
+ else if (unformat (i, "ip4-table %d", &ip4_table_index))
+ ;
+ else if (unformat (i, "ip6-table %d", &ip6_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 (FLOW_CLASSIFY_SET_INTERFACE, flow_classify_set_interface);
+
+ 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->is_add = is_add;
+
+ S;
+ W;
+ /* NOTREACHED */
+ return 0;
+}
+
+static int
+api_flow_classify_dump (vat_main_t * vam)
+{
+ unformat_input_t *i = vam->input;
+ vl_api_flow_classify_dump_t *mp;
+ f64 timeout = ~0;
+ u8 type = FLOW_CLASSIFY_N_TABLES;
+
+ if (unformat (i, "type %U", unformat_flow_classify_table_type, &type))
+ ;
+ else
+ {
+ errmsg ("classify table type must be specified\n");
+ return -99;
+ }
+
+ if (!vam->json_output)
+ {
+ fformat (vam->ofp, "%10s%20s\n", "Intfc idx", "Classify table");
+ }
+
+ M (FLOW_CLASSIFY_DUMP, flow_classify_dump);
+ mp->type = type;
+ /* send it... */
+ S;
+
+ /* Use a control ping for synchronization */
+ {
+ vl_api_control_ping_t *mp;
+ M (CONTROL_PING, control_ping);
+ S;
+ }
+ /* Wait for a reply... */
+ W;
+
+ /* NOTREACHED */
+ return 0;
+}
+
+static int
+api_feature_enable_disable (vat_main_t * vam)
+{
+ unformat_input_t *i = vam->input;
+ vl_api_feature_enable_disable_t *mp;
+ f64 timeout;
+ u8 *arc_name = 0;
+ u8 *feature_name = 0;
+ u32 sw_if_index = ~0;
+ u8 enable = 1;
+
+ while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (i, "arc_name %s", &arc_name))
+ ;
+ else if (unformat (i, "feature_name %s", &feature_name))
+ ;
+ else if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
+ ;
+ else if (unformat (i, "sw_if_index %d", &sw_if_index))
+ ;
+ else if (unformat (i, "disable"))
+ enable = 0;
+ else
+ break;
+ }
+
+ if (arc_name == 0)
+ {
+ errmsg ("missing arc name\n");
+ return -99;
+ }
+ if (vec_len (arc_name) > 63)
+ {
+ errmsg ("arc name too long\n");
+ }
+
+ if (feature_name == 0)
+ {
+ errmsg ("missing feature name\n");
+ return -99;
+ }
+ if (vec_len (feature_name) > 63)
+ {
+ errmsg ("feature name too long\n");
+ }
+
+ if (sw_if_index == ~0)
+ {
+ errmsg ("missing interface name or sw_if_index\n");
+ return -99;
+ }
+
+ /* Construct the API message */
+ M (FEATURE_ENABLE_DISABLE, feature_enable_disable);
+ mp->sw_if_index = ntohl (sw_if_index);
+ mp->enable = enable;
+ clib_memcpy (mp->arc_name, arc_name, vec_len (arc_name));
+ clib_memcpy (mp->feature_name, feature_name, vec_len (feature_name));
+ vec_free (arc_name);
+ vec_free (feature_name);
+
+ S;
+ W;