gbp: add anonymous l3-out external interfaces
[vpp.git] / src / plugins / gbp / gbp_ext_itf.c
index be2d614..89bcb3d 100644 (file)
@@ -130,6 +130,120 @@ gbp_ext_itf_delete (u32 sw_if_index)
   return (VNET_API_ERROR_NO_SUCH_ENTRY);
 }
 
+int
+gbp_ext_itf_anon_add (u32 sw_if_index, u32 bd_id, u32 rd_id)
+{
+  int rv = gbp_ext_itf_add (sw_if_index, bd_id, rd_id);
+  if (rv)
+    return rv;
+  /* add interface to the BD */
+  index_t itf = gbp_itf_add_and_lock (sw_if_index, bd_id);
+  /* setup GBP L2 features on this interface */
+  gbp_itf_set_l2_input_feature (itf, 0,
+                               L2INPUT_FEAT_GBP_LPM_ANON_CLASSIFY |
+                               L2INPUT_FEAT_LEARN);
+  gbp_itf_set_l2_output_feature (itf, 0, L2OUTPUT_FEAT_GBP_POLICY_LPM);
+  return 0;
+}
+
+int
+gbp_ext_itf_anon_delete (u32 sw_if_index)
+{
+  int rv = gbp_ext_itf_delete (sw_if_index);
+  if (rv)
+    return rv;
+  gbp_itf_unlock (sw_if_index);
+  return 0;
+}
+
+static clib_error_t *
+gbp_ext_itf_add_del_cli (vlib_main_t * vm,
+                        unformat_input_t * input, vlib_cli_command_t * cmd)
+{
+  unformat_input_t _line_input, *line_input = &_line_input;
+  u32 sw_if_index = ~0, bd_id = ~0, rd_id = ~0;
+  int add = 1, anon = 0;
+  int rv;
+
+  /* Get a line of input. */
+  if (!unformat_user (input, unformat_line_input, line_input))
+    return 0;
+
+  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
+    {
+      if (unformat (line_input, "del"))
+       add = 0;
+      else
+       if (unformat
+           (line_input, "%U", unformat_vnet_sw_interface, vnet_get_main (),
+            &sw_if_index))
+       ;
+      else if (unformat (line_input, "bd %d", &bd_id))
+       ;
+      else if (unformat (line_input, "rd %d", &rd_id))
+       ;
+      else if (unformat (line_input, "anon-l3-out"))
+       anon = 1;
+      else
+       return clib_error_return (0, "unknown input `%U'",
+                                 format_unformat_error, line_input);
+    }
+  unformat_free (line_input);
+
+  if (~0 == sw_if_index)
+    return clib_error_return (0, "interface must be specified");
+
+  if (add)
+    {
+      if (~0 == bd_id)
+       return clib_error_return (0, "BD-ID must be specified");
+      if (~0 == rd_id)
+       return clib_error_return (0, "RD-ID must be specified");
+      if (anon)
+       rv = gbp_ext_itf_anon_add (sw_if_index, bd_id, rd_id);
+      else
+       rv = gbp_ext_itf_add (sw_if_index, bd_id, rd_id);
+    }
+  else
+    {
+      if (anon)
+       rv = gbp_ext_itf_anon_delete (sw_if_index);
+      else
+       rv = gbp_ext_itf_delete (sw_if_index);
+    }
+
+  switch (rv)
+    {
+    case 0:
+      return 0;
+    case VNET_API_ERROR_ENTRY_ALREADY_EXISTS:
+      return clib_error_return (0, "interface already exists");
+    case VNET_API_ERROR_NO_SUCH_ENTRY: /* fallthrough */
+    case VNET_API_ERROR_INVALID_SW_IF_INDEX:
+      return clib_error_return (0, "unknown interface");
+    default:
+      return clib_error_return (0, "error %d", rv);
+    }
+
+  /* never reached */
+  return 0;
+}
+
+/*?
+ * Add Group Based Interface as anonymous L3out interface
+ *
+ * @cliexpar
+ * @cliexstart{gbp interface [del] anon-l3out <interface> bd <ID>}
+ * @cliexend
+ ?*/
+/* *INDENT-OFF* */
+VLIB_CLI_COMMAND (gbp_itf_anon_l3out_add_del_node, static) = {
+  .path = "gbp ext-itf",
+  .short_help = "gbp ext-itf [del] <interface> bd <ID> rd <ID> [anon-l3-out]\n",
+  .function = gbp_ext_itf_add_del_cli,
+};
+/* *INDENT-ON* */
+
 void
 gbp_ext_itf_walk (gbp_ext_itf_cb_t cb, void *ctx)
 {