feature: API/CLI to enable/disable feature per interface
[vpp.git] / vpp / vpp-api / api.c
index 1ecd148..b2b639a 100644 (file)
@@ -89,6 +89,7 @@
 #include <vnet/ipsec-gre/ipsec_gre.h>
 #include <vnet/flow/flow_report_classify.h>
 #include <vnet/ip/punt.h>
+#include <vnet/feature/feature.h>
 
 #undef BIHASH_TYPE
 #undef __included_bihash_template_h__
@@ -466,7 +467,8 @@ _(IPSEC_SPD_DUMP, ipsec_spd_dump)                                       \
 _(IP_FIB_DUMP, ip_fib_dump)                                             \
 _(IP_FIB_DETAILS, ip_fib_details)                                       \
 _(IP6_FIB_DUMP, ip6_fib_dump)                                           \
-_(IP6_FIB_DETAILS, ip6_fib_details)
+_(IP6_FIB_DETAILS, ip6_fib_details)                                     \
+_(FEATURE_ENABLE_DISABLE, feature_enable_disable)
 
 #define QUOTE_(x) #x
 #define QUOTE(x) QUOTE_(x)
@@ -3922,7 +3924,9 @@ _(memory_size)                                  \
 _(skip_n_vectors)                               \
 _(match_n_vectors)                              \
 _(next_table_index)                             \
-_(miss_next_index)
+_(miss_next_index)                              \
+_(current_data_flag)                            \
+_(current_data_offset)
 
 static void vl_api_classify_add_del_table_t_handler
   (vl_api_classify_add_del_table_t * mp)
@@ -3941,17 +3945,25 @@ static void vl_api_classify_add_del_table_t_handler
 #undef _
 
   /* The underlying API fails silently, on purpose, so check here */
-  if (mp->is_add == 0)
-    if (pool_is_free_index (cm->tables, table_index))
-      {
-       rv = VNET_API_ERROR_NO_SUCH_TABLE;
-       goto out;
-      }
+  if (mp->is_add == 0)         /* delete */
+    {
+      if (pool_is_free_index (cm->tables, table_index))
+       {
+         rv = VNET_API_ERROR_NO_SUCH_TABLE;
+         goto out;
+       }
+    }
+  else                         /* add or update */
+    {
+      if (table_index != ~0 && pool_is_free_index (cm->tables, table_index))
+       table_index = ~0;
+    }
 
   rv = vnet_classify_add_del_table
     (cm, mp->mask, nbuckets, memory_size,
      skip_n_vectors, match_n_vectors,
-     next_table_index, miss_next_index, &table_index, mp->is_add);
+     next_table_index, miss_next_index, &table_index,
+     current_data_flag, current_data_offset, mp->is_add);
 
 out:
   /* *INDENT-OFF* */
@@ -3980,17 +3992,20 @@ static void vl_api_classify_add_del_session_t_handler
   vnet_classify_main_t *cm = &vnet_classify_main;
   vl_api_classify_add_del_session_reply_t *rmp;
   int rv;
-  u32 table_index, hit_next_index, opaque_index;
+  u32 table_index, hit_next_index, opaque_index, metadata;
   i32 advance;
+  u8 action;
 
   table_index = ntohl (mp->table_index);
   hit_next_index = ntohl (mp->hit_next_index);
   opaque_index = ntohl (mp->opaque_index);
   advance = ntohl (mp->advance);
+  action = mp->action;
+  metadata = ntohl (mp->metadata);
 
   rv = vnet_classify_add_del_session
     (cm, table_index, mp->match, hit_next_index, opaque_index,
-     advance, mp->is_add);
+     advance, action, metadata, mp->is_add);
 
   REPLY_MACRO (VL_API_CLASSIFY_ADD_DEL_SESSION_REPLY);
 }
@@ -7592,6 +7607,33 @@ vl_api_mpls_fib_details_t_print (vl_api_mpls_fib_details_t * mp)
   clib_warning ("BUG");
 }
 
+
+static void
+copy_fib_next_hop (fib_route_path_encode_t * api_rpath,
+                  vl_api_fib_path_t * fp)
+{
+  int is_ip4;
+
+  if (api_rpath->rpath.frp_proto == FIB_PROTOCOL_IP4)
+    fp->afi = IP46_TYPE_IP4;
+  else if (api_rpath->rpath.frp_proto == FIB_PROTOCOL_IP6)
+    fp->afi = IP46_TYPE_IP6;
+  else
+    {
+      is_ip4 = ip46_address_is_ip4 (&api_rpath->rpath.frp_addr);
+      if (is_ip4)
+       fp->afi = IP46_TYPE_IP4;
+      else
+       fp->afi = IP46_TYPE_IP6;
+    }
+  if (fp->afi == IP46_TYPE_IP4)
+    memcpy (fp->next_hop, &api_rpath->rpath.frp_addr.ip4,
+           sizeof (api_rpath->rpath.frp_addr.ip4));
+  else
+    memcpy (fp->next_hop, &api_rpath->rpath.frp_addr.ip6,
+           sizeof (api_rpath->rpath.frp_addr.ip6));
+}
+
 static void
 send_mpls_fib_details (vpe_api_main_t * am,
                       unix_shared_memory_queue_t * q,
@@ -7601,7 +7643,7 @@ send_mpls_fib_details (vpe_api_main_t * am,
   vl_api_mpls_fib_details_t *mp;
   fib_route_path_encode_t *api_rpath;
   vl_api_fib_path_t *fp;
-  int is_ip4, path_count;
+  int path_count;
 
   path_count = vec_len (api_rpaths);
   mp = vl_msg_api_alloc (sizeof (*mp) + path_count * sizeof (*fp));
@@ -7622,19 +7664,7 @@ send_mpls_fib_details (vpe_api_main_t * am,
     memset (fp, 0, sizeof (*fp));
     fp->weight = htonl (api_rpath->rpath.frp_weight);
     fp->sw_if_index = htonl (api_rpath->rpath.frp_sw_if_index);
-    memcpy (fp->next_hop, &api_rpath->rpath.frp_addr, sizeof (fp->next_hop));
-    if (api_rpath->rpath.frp_proto == FIB_PROTOCOL_IP4)
-      fp->afi = IP46_TYPE_IP4;
-    else if (api_rpath->rpath.frp_proto == FIB_PROTOCOL_IP6)
-      fp->afi = IP46_TYPE_IP6;
-    else
-      {
-       is_ip4 = ip46_address_is_ip4 (&api_rpath->rpath.frp_addr);
-       if (is_ip4)
-         fp->afi = IP46_TYPE_IP4;
-       else
-         fp->afi = IP46_TYPE_IP6;
-      }
+    copy_fib_next_hop (api_rpath, fp);
     fp++;
   }
 
@@ -7714,7 +7744,7 @@ send_ip_fib_details (vpe_api_main_t * am,
   vl_api_ip_fib_details_t *mp;
   fib_route_path_encode_t *api_rpath;
   vl_api_fib_path_t *fp;
-  int is_ip4, path_count;
+  int path_count;
 
   path_count = vec_len(api_rpaths);
   mp = vl_msg_api_alloc (sizeof (*mp) + path_count * sizeof (*fp));
@@ -7762,19 +7792,7 @@ send_ip_fib_details (vpe_api_main_t * am,
       }
     fp->weight = htonl(api_rpath->rpath.frp_weight);
     fp->sw_if_index = htonl(api_rpath->rpath.frp_sw_if_index);
-    memcpy(fp->next_hop, &api_rpath->rpath.frp_addr, sizeof(fp->next_hop));
-    if (api_rpath->rpath.frp_proto == FIB_PROTOCOL_IP4)
-       fp->afi = IP46_TYPE_IP4;
-    else if (api_rpath->rpath.frp_proto == FIB_PROTOCOL_IP6)
-       fp->afi = IP46_TYPE_IP6;
-    else
-      {
-       is_ip4 = ip46_address_is_ip4 (&api_rpath->rpath.frp_addr);
-       if (is_ip4)
-           fp->afi = IP46_TYPE_IP4;
-       else
-           fp->afi = IP46_TYPE_IP6;
-      }
+    copy_fib_next_hop (api_rpath, fp);
     fp++;
   }
 
@@ -7858,7 +7876,7 @@ send_ip6_fib_details (vpe_api_main_t * am,
   vl_api_ip6_fib_details_t *mp;
   fib_route_path_encode_t *api_rpath;
   vl_api_fib_path_t *fp;
-  int is_ip4, path_count;
+  int path_count;
 
   path_count = vec_len(api_rpaths);
   mp = vl_msg_api_alloc (sizeof (*mp) + path_count * sizeof (*fp));
@@ -7906,19 +7924,7 @@ send_ip6_fib_details (vpe_api_main_t * am,
       }
     fp->weight = htonl(api_rpath->rpath.frp_weight);
     fp->sw_if_index = htonl(api_rpath->rpath.frp_sw_if_index);
-    memcpy(fp->next_hop, &api_rpath->rpath.frp_addr, sizeof(fp->next_hop));
-    if (api_rpath->rpath.frp_proto == FIB_PROTOCOL_IP4)
-      fp->afi = IP46_TYPE_IP4;
-    else if (api_rpath->rpath.frp_proto == FIB_PROTOCOL_IP6)
-      fp->afi = IP46_TYPE_IP6;
-    else
-      {
-       is_ip4 = ip46_address_is_ip4 (&api_rpath->rpath.frp_addr);
-       if (is_ip4)
-         fp->afi = IP46_TYPE_IP4;
-       else
-         fp->afi = IP46_TYPE_IP6;
-      }
+    copy_fib_next_hop (api_rpath, fp);
     fp++;
   }
 
@@ -9170,6 +9176,45 @@ vl_api_ipsec_spd_dump_t_handler (vl_api_ipsec_spd_dump_t * mp)
 #endif
 }
 
+static void
+vl_api_feature_enable_disable_t_handler (vl_api_feature_enable_disable_t * mp)
+{
+  vl_api_feature_enable_disable_reply_t *rmp;
+  int rv = 0;
+
+  u8 *arc_name = format (0, "%s%c", mp->arc_name, 0);
+  u8 *feature_name = format (0, "%s%c", mp->feature_name, 0);
+  u32 sw_if_index = ntohl (mp->sw_if_index);
+
+  vnet_feature_registration_t *reg;
+  reg =
+    vnet_get_feature_reg ((const char *) arc_name,
+                         (const char *) feature_name);
+  if (reg == 0)
+    rv = VNET_API_ERROR_INVALID_VALUE;
+  else
+    {
+      clib_error_t *error = 0;
+
+      if (reg->enable_disable_cb)
+       error = reg->enable_disable_cb (sw_if_index, mp->enable);
+      if (!error)
+       vnet_feature_enable_disable ((const char *) arc_name,
+                                    (const char *) feature_name,
+                                    sw_if_index, mp->enable, 0, 0);
+      else
+       {
+         clib_error_report (error);
+         rv = VNET_API_ERROR_CANNOT_ENABLE_DISABLE_FEATURE;
+       }
+    }
+
+  vec_free (feature_name);
+  vec_free (arc_name);
+
+  REPLY_MACRO (VL_API_FEATURE_ENABLE_DISABLE_REPLY);
+}
+
 #define BOUNCE_HANDLER(nn)                                              \
 static void vl_api_##nn##_t_handler (                                   \
     vl_api_##nn##_t *mp)                                                \