VPP-108 : API calls to read classify table and sessions

Added new API calls to read
- classify table ids as array
- classify table ids for specified interface
- classsify table info
and to dump sessions of specified classify table.

Change-Id: I089604fa98eea92866495089d76c2330ae7d850c
Signed-off-by: Pavel Kotucek <pavel.kotucek@pantheon.tech>
diff --git a/vnet/vnet/api_errno.h b/vnet/vnet/api_errno.h
index 5d08fb4..bf49c0a 100644
--- a/vnet/vnet/api_errno.h
+++ b/vnet/vnet/api_errno.h
@@ -80,7 +80,8 @@
 _(UNSUPPORTED_JNI_VERSION, -87, "Unsupported JNI version") \
 _(FAILED_TO_ATTACH_TO_JAVA_THREAD, -88, "Failed to attach to Java thread") \
 _(INVALID_WORKER, -89, "Invalid worker thread")                         \
-_(LISP_DISABLED, -90, "LISP is disabled")
+_(LISP_DISABLED, -90, "LISP is disabled")                               \
+_(CLASSIFY_TABLE_NOT_FOUND, -91, "Classify table not found")
 
 typedef enum {
 #define _(a,b,c) VNET_API_ERROR_##a = (b),
diff --git a/vpp-api-test/vat/api_format.c b/vpp-api-test/vat/api_format.c
index 48e924a..50654aa 100644
--- a/vpp-api-test/vat/api_format.c
+++ b/vpp-api-test/vat/api_format.c
@@ -2358,6 +2358,175 @@
     vec_free(type_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);
+}
 
 #define vl_api_vnet_ip4_fib_counters_t_endian vl_noop_handler
 #define vl_api_vnet_ip4_fib_counters_t_print vl_noop_handler
@@ -2652,7 +2821,11 @@
 _(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)
+_(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)
 
 /* M: construct, but don't yet send a message */
 
@@ -11322,6 +11495,113 @@
     W;
 }
 
+int api_classify_table_ids (vat_main_t *vam)
+{
+    vl_api_classify_table_ids_t *mp;
+    f64 timeout;
+
+    /* Construct the API message */
+    M(CLASSIFY_TABLE_IDS, classify_table_ids);
+    mp->context = 0;
+
+    S; W;
+    /* NOTREACHED */
+    return 0;
+}
+
+int api_classify_table_by_interface (vat_main_t *vam)
+{
+    unformat_input_t * input = vam->input;
+    vl_api_classify_table_by_interface_t *mp;
+    f64 timeout;
+
+    u32 sw_if_index = ~0;
+    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
+            break;
+    }
+    if (sw_if_index == ~0) {
+        errmsg ("missing interface name or sw_if_index\n");
+        return -99;
+    }
+
+    /* Construct the API message */
+    M(CLASSIFY_TABLE_BY_INTERFACE, classify_table_by_interface);
+    mp->context = 0;
+    mp->sw_if_index = ntohl(sw_if_index);
+
+    S; W;
+    /* NOTREACHED */
+    return 0;
+}
+
+int api_classify_table_info (vat_main_t *vam)
+{
+    unformat_input_t * input = vam->input;
+    vl_api_classify_table_info_t *mp;
+    f64 timeout;
+
+    u32 table_id = ~0;
+    while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
+        if (unformat (input, "table_id %d", &table_id))
+            ;
+        else
+            break;
+    }
+    if (table_id == ~0) {
+        errmsg ("missing table id\n");
+        return -99;
+    }
+
+    /* Construct the API message */
+    M(CLASSIFY_TABLE_INFO, classify_table_info);
+    mp->context = 0;
+    mp->table_id = ntohl(table_id);
+
+    S; W;
+    /* NOTREACHED */
+    return 0;
+}
+
+int api_classify_session_dump (vat_main_t *vam)
+{
+    unformat_input_t * input = vam->input;
+    vl_api_classify_session_dump_t *mp;
+    f64 timeout;
+
+    u32 table_id = ~0;
+    while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
+        if (unformat (input, "table_id %d", &table_id))
+            ;
+        else
+            break;
+    }
+    if (table_id == ~0) {
+        errmsg ("missing table id\n");
+        return -99;
+    }
+
+    /* Construct the API message */
+    M(CLASSIFY_SESSION_DUMP, classify_session_dump);
+    mp->context = 0;
+    mp->table_id = ntohl(table_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 q_or_quit (vat_main_t * vam)
 {
     longjmp (vam->jump_buf, 1);
@@ -11822,7 +12102,11 @@
 _(mpls_gre_tunnel_dump, "tunnel_index <tunnel-id>")                     \
 _(mpls_eth_tunnel_dump, "tunnel_index <tunnel-id>")                     \
 _(mpls_fib_encap_dump, "")                                              \
-_(mpls_fib_decap_dump, "")
+_(mpls_fib_decap_dump, "")                                              \
+_(classify_table_ids, "")                                               \
+_(classify_table_by_interface, "sw_if_index <sw_if_index>")             \
+_(classify_table_info, "table_id <nn>")                                 \
+_(classify_session_dump, "table_id <nn>")
 
 /* List of command functions, CLI names map directly to functions */
 #define foreach_cli_function                                    \
diff --git a/vpp/api/api.c b/vpp/api/api.c
index 1550dc8..302b7d4 100644
--- a/vpp/api/api.c
+++ b/vpp/api/api.c
@@ -359,7 +359,12 @@
 _(MPLS_FIB_ENCAP_DUMP, mpls_fib_encap_dump)                             \
 _(MPLS_FIB_ENCAP_DETAILS, mpls_fib_encap_details)                       \
 _(MPLS_FIB_DECAP_DUMP, mpls_fib_decap_dump)                             \
-_(MPLS_FIB_DECAP_DETAILS, mpls_fib_decap_details)
+_(MPLS_FIB_DECAP_DETAILS, mpls_fib_decap_details)                       \
+_(CLASSIFY_TABLE_IDS,classify_table_ids)                                \
+_(CLASSIFY_TABLE_BY_INTERFACE, classify_table_by_interface)             \
+_(CLASSIFY_TABLE_INFO,classify_table_info)                              \
+_(CLASSIFY_SESSION_DUMP,classify_session_dump)                          \
+_(CLASSIFY_SESSION_DETAILS,classify_session_details)
 
 #define QUOTE_(x) #x
 #define QUOTE(x) QUOTE_(x)
@@ -6661,6 +6666,195 @@
     vec_free(records);
 }
 
+static void vl_api_classify_table_ids_t_handler (vl_api_classify_table_ids_t *mp)
+{
+    unix_shared_memory_queue_t * q;
+
+    q = vl_api_client_index_to_input_queue (mp->client_index);
+    if (q == 0)
+        return;
+
+    vnet_classify_main_t * cm = &vnet_classify_main;
+    vnet_classify_table_t * t;
+    u32 * table_ids = 0;
+    u32 count;
+
+    pool_foreach (t, cm->tables,
+    ({
+        vec_add1 (table_ids, ntohl(t - cm->tables));
+    }));
+    count = vec_len(table_ids);
+
+    vl_api_classify_table_ids_reply_t *rmp;
+    rmp = vl_msg_api_alloc_as_if_client(sizeof (*rmp) + count);
+    rmp->_vl_msg_id = ntohs (VL_API_CLASSIFY_TABLE_IDS_REPLY);
+    rmp->context = mp->context;
+    rmp->count = ntohl(count);
+    clib_memcpy(rmp->ids, table_ids, count * sizeof(u32));
+    rmp->retval = 0;
+
+    vl_msg_api_send_shmem (q, (u8 *)&rmp);
+
+    vec_free (table_ids);
+}
+
+static void vl_api_classify_table_by_interface_t_handler (vl_api_classify_table_by_interface_t *mp)
+{
+    vl_api_classify_table_by_interface_reply_t *rmp;
+    int rv = 0;
+
+    u32 sw_if_index = ntohl(mp->sw_if_index);
+    u32 * acl = 0;
+
+    vec_validate (acl, INPUT_ACL_N_TABLES - 1);
+    vec_set (acl, ~0);
+
+    VALIDATE_SW_IF_INDEX(mp);
+
+    input_acl_main_t * am = &input_acl_main;
+
+    int if_idx;
+    u32 type;
+
+    for (type = 0; type < INPUT_ACL_N_TABLES; type++)
+    {
+    	u32 * vec_tbl = am->classify_table_index_by_sw_if_index[type];
+		if (vec_len(vec_tbl)) {
+			for (if_idx = 0; if_idx < vec_len (vec_tbl); if_idx++)
+			{
+			    if (vec_elt(vec_tbl, if_idx) == ~0 || sw_if_index != if_idx) {
+				    continue;
+			    }
+			    acl[type] = vec_elt(vec_tbl, if_idx);
+			}
+		}
+    }
+
+    BAD_SW_IF_INDEX_LABEL;
+
+    REPLY_MACRO2(VL_API_CLASSIFY_TABLE_BY_INTERFACE_REPLY,
+    ({
+       rmp->sw_if_index = ntohl(sw_if_index);
+       rmp->l2_table_id = ntohl(acl[INPUT_ACL_TABLE_L2]);
+       rmp->ip4_table_id = ntohl(acl[INPUT_ACL_TABLE_IP4]);
+       rmp->ip6_table_id = ntohl(acl[INPUT_ACL_TABLE_IP6]);
+    }));
+    vec_free(acl);
+}
+
+static void vl_api_classify_table_info_t_handler (vl_api_classify_table_info_t *mp)
+{
+    unix_shared_memory_queue_t * q;
+
+    q = vl_api_client_index_to_input_queue (mp->client_index);
+    if (q == 0)
+        return;
+
+    vl_api_classify_table_info_reply_t *rmp = 0;
+
+    vnet_classify_main_t * cm = &vnet_classify_main;
+    u32 table_id = ntohl(mp->table_id);
+    vnet_classify_table_t * t;
+
+    pool_foreach (t, cm->tables,
+    ({
+        if (table_id == t - cm->tables) {
+            rmp = vl_msg_api_alloc_as_if_client(sizeof (*rmp) + t->match_n_vectors * sizeof (u32x4));
+            rmp->_vl_msg_id = ntohs (VL_API_CLASSIFY_TABLE_INFO_REPLY);
+            rmp->context = mp->context;
+            rmp->table_id = ntohl(table_id);
+            rmp->nbuckets = ntohl(t->nbuckets);
+            rmp->match_n_vectors = ntohl(t->match_n_vectors);
+            rmp->skip_n_vectors = ntohl(t->skip_n_vectors);
+            rmp->active_sessions = ntohl(t->active_elements);
+            rmp->next_table_index = ntohl(t->next_table_index);
+            rmp->miss_next_index = ntohl(t->miss_next_index);
+            rmp->mask_length = ntohl(t->match_n_vectors * sizeof (u32x4));
+            clib_memcpy(rmp->mask, t->mask, t->match_n_vectors * sizeof(u32x4));
+            rmp->retval = 0;
+            break;
+        }
+    }));
+
+    if (rmp == 0) {
+        rmp = vl_msg_api_alloc (sizeof (*rmp));
+        rmp->_vl_msg_id = ntohs((VL_API_CLASSIFY_TABLE_INFO_REPLY));
+        rmp->context = mp->context;
+        rmp->retval = ntohl(VNET_API_ERROR_CLASSIFY_TABLE_NOT_FOUND);
+    }
+
+    vl_msg_api_send_shmem (q, (u8 *)&rmp);
+}
+
+static void vl_api_classify_session_details_t_handler (vl_api_classify_session_details_t * mp)
+{
+    clib_warning ("BUG");
+}
+
+static void send_classify_session_details (unix_shared_memory_queue_t * q,
+                                           u32 table_id,
+                                           u32 match_length,
+                                           vnet_classify_entry_t * e,
+                                           u32 context)
+{
+    vl_api_classify_session_details_t *rmp;
+
+    rmp = vl_msg_api_alloc (sizeof (*rmp));
+    memset (rmp, 0, sizeof (*rmp));
+    rmp->_vl_msg_id = ntohs(VL_API_CLASSIFY_SESSION_DETAILS);
+    rmp->context = context;
+    rmp->table_id = ntohl(table_id);
+    rmp->hit_next_index = ntohl(e->next_index);
+    rmp->advance = ntohl(e->advance);
+    rmp->opaque_index = ntohl(e->opaque_index);
+    rmp->match_length = ntohl(match_length);
+    clib_memcpy(rmp->match, e->key, match_length);
+
+    vl_msg_api_send_shmem (q, (u8 *)&rmp);
+}
+
+static void vl_api_classify_session_dump_t_handler (vl_api_classify_session_dump_t *mp)
+{
+    vnet_classify_main_t * cm = &vnet_classify_main;
+    unix_shared_memory_queue_t * q;
+
+    u32 table_id = ntohl(mp->table_id);
+    vnet_classify_table_t * t;
+
+    q = vl_api_client_index_to_input_queue (mp->client_index);
+
+    pool_foreach (t, cm->tables,
+    ({
+        if (table_id == t - cm->tables) {
+            vnet_classify_bucket_t * b;
+            vnet_classify_entry_t * v, * save_v;
+            int i, j, k;
+
+            for (i = 0; i < t->nbuckets; i++)
+            {
+                b = &t->buckets [i];
+                if (b->offset == 0)
+                   continue;
+
+                save_v = vnet_classify_get_entry (t, b->offset);
+                for (j = 0; j < (1<<b->log2_pages); j++)
+                {
+                	for (k = 0; k < t->entries_per_page; k++)
+                	{
+                	    v = vnet_classify_entry_at_index (t, save_v, j*t->entries_per_page + k);
+                	    if (vnet_classify_entry_is_free (v))
+                	        continue;
+
+                		send_classify_session_details(q, table_id,
+                				t->match_n_vectors * sizeof (u32x4), v, mp->context);
+                	}
+                }
+            }
+            break;
+        }
+    }));
+}
+
 #define BOUNCE_HANDLER(nn)                                              \
 static void vl_api_##nn##_t_handler (                                   \
     vl_api_##nn##_t *mp)                                                \
diff --git a/vpp/api/custom_dump.c b/vpp/api/custom_dump.c
index fa9dce6..123883f 100644
--- a/vpp/api/custom_dump.c
+++ b/vpp/api/custom_dump.c
@@ -1799,6 +1799,52 @@
     FINISH;
 }
 
+static void *vl_api_classify_table_ids_t_print
+(vl_api_classify_table_ids_t * mp, void *handle)
+{
+    u8 * s;
+
+    s = format (0, "SCRIPT: classify_table_ids ");
+
+    FINISH;
+}
+
+static void *vl_api_classify_table_by_interface_t_print
+(vl_api_classify_table_by_interface_t * mp, void *handle)
+{
+    u8 * s;
+
+    s = format (0, "SCRIPT: classify_table_by_interface ");
+    if (mp->sw_if_index != ~0)
+      s = format (s, "sw_if_index %d ", ntohl(mp->sw_if_index));
+
+    FINISH;
+}
+
+static void *vl_api_classify_table_info_t_print
+(vl_api_classify_table_info_t * mp, void *handle)
+{
+    u8 * s;
+
+    s = format (0, "SCRIPT: classify_table_info ");
+    if (mp->table_id != ~0)
+      s = format (s, "table_id %d ", ntohl(mp->table_id));
+
+    FINISH;
+}
+
+static void *vl_api_classify_session_dump_t_print
+(vl_api_classify_session_dump_t * mp, void *handle)
+{
+    u8 * s;
+
+    s = format (0, "SCRIPT: classify_session_dump ");
+    if (mp->table_id != ~0)
+      s = format (s, "table_id %d ", ntohl(mp->table_id));
+
+    FINISH;
+}
+
 #define foreach_custom_print_function                                   \
 _(CREATE_LOOPBACK, create_loopback)                                     \
 _(SW_INTERFACE_SET_FLAGS, sw_interface_set_flags)                       \
@@ -1890,7 +1936,11 @@
 _(MPLS_GRE_TUNNEL_DUMP, mpls_gre_tunnel_dump)                           \
 _(MPLS_ETH_TUNNEL_DUMP, mpls_eth_tunnel_dump)                           \
 _(MPLS_FIB_ENCAP_DUMP, mpls_fib_encap_dump)                             \
-_(MPLS_FIB_DECAP_DUMP, mpls_fib_decap_dump)
+_(MPLS_FIB_DECAP_DUMP, mpls_fib_decap_dump)                             \
+_(CLASSIFY_TABLE_IDS,classify_table_ids)                                \
+_(CLASSIFY_TABLE_BY_INTERFACE, classify_table_by_interface)             \
+_(CLASSIFY_TABLE_INFO,classify_table_info)                              \
+_(CLASSIFY_SESSION_DUMP,classify_session_dump)
 
 void vl_msg_api_custom_dump_configure (api_main_t *am) 
 {
diff --git a/vpp/api/vpe.api b/vpp/api/vpe.api
index f91dd87..a1ea1b2 100644
--- a/vpp/api/vpe.api
+++ b/vpp/api/vpe.api
@@ -3835,3 +3835,120 @@
     u32 tx_table_id;
     u8  swif_tag[8];
 };
+
+/** \brief Classify get table IDs request
+    @param client_index - opaque cookie to identify the sender
+    @param context - sender context, to match reply w/ request
+*/
+define classify_table_ids {
+    u32 client_index;
+    u32 context;
+};
+
+/** \brief Reply for classify get table IDs request
+    @param context - sender context which was passed in the request
+    @param count - number of ids returned in response
+    @param ids - array of classify table ids
+*/
+manual_java define classify_table_ids_reply {
+    u32 context;
+    u32 retval;
+    u32 count;
+    u32 ids[0];
+};
+
+/** \brief Classify table ids by interface index request
+    @param client_index - opaque cookie to identify the sender
+    @param context - sender context, to match reply w/ request
+    @param sw_if_index - index of the interface
+*/
+define classify_table_by_interface {
+    u32 client_index;
+    u32 context;
+    u32 sw_if_index;
+};
+
+/** \brief Reply for classify table id by interface index request
+    @param context - sender context which was passed in the request
+    @param count - number of ids returned in response
+    @param sw_if_index - index of the interface
+    @param l2_table_id - l2 classify table index
+    @param ip4_table_id - ip4 classify table index
+    @param ip6_table_id - ip6 classify table index
+*/
+manual_java define classify_table_by_interface_reply {
+    u32 context;
+    u32 retval;
+    u32 sw_if_index;
+    u32 l2_table_id;
+    u32 ip4_table_id;
+    u32 ip6_table_id;
+};
+
+/** \brief Classify table info
+    @param client_index - opaque cookie to identify the sender
+    @param context - sender context, to match reply w/ request
+    @param table_id - classify table index
+*/
+define classify_table_info {
+    u32 client_index;
+    u32 context;
+    u32 table_id;
+};
+
+/** \brief Reply for classify table info request
+    @param context - sender context which was passed in the request
+    @param count - number of ids returned in response
+    @param table_id - classify table index
+    @param nbuckets - number of buckets when adding a table
+    @param match_n_vectors - number of match vectors
+    @param skip_n_vectors - number of skip_n_vectors
+    @param active_sessions - number of sessions (active entries)
+    @param next_table_index - index of next table
+    @param miss_next_index - index of miss table
+    @param mask[] - match mask
+*/
+manual_java define classify_table_info_reply {
+    u32 context;
+    i32 retval;
+    u32 table_id;
+    u32 nbuckets;
+    u32 match_n_vectors;
+    u32 skip_n_vectors;
+    u32 active_sessions;
+    u32 next_table_index;
+    u32 miss_next_index;
+    u32 mask_length;
+    u8  mask[0];
+};
+
+/** \brief Classify sessions dump request
+    @param client_index - opaque cookie to identify the sender
+    @param context - sender context, to match reply w/ request
+    @param table_id - classify table index
+*/
+define classify_session_dump {
+    u32 client_index;
+    u32 context;
+    u32 table_id;
+};
+
+/** \brief Reply for classify table session dump request
+    @param context - sender context which was passed in the request
+    @param count - number of ids returned in response
+    @param table_id - classify table index
+    @param hit_next_index - hit_next_index of session
+    @param opaque_index - for add, opaque_index of session
+    @param advance - advance value of session
+    @param match[] - match value for session
+*/ 
+manual_java define classify_session_details {
+    u32 context;
+    i32 retval;
+    u32 table_id;
+    u32 hit_next_index;
+    i32 advance;
+    u32 opaque_index;
+    u32 match_length;
+    u8 match[0];
+};