span: add tx functionality and support for multiple mirror ports
[vpp.git] / vnet / vnet / pg / cli.c
index d73add1..f5896b4 100644 (file)
 #endif
 
 /* Root of all packet generator cli commands. */
+/* *INDENT-OFF* */
 VLIB_CLI_COMMAND (vlib_cli_pg_command, static) = {
   .path = "packet-generator",
   .short_help = "Packet generator commands",
 };
+/* *INDENT-ON* */
+
+void
+pg_enable_disable (u32 stream_index, int is_enable)
+{
+  pg_main_t *pg = &pg_main;
+  pg_stream_t *s;
+
+  if (stream_index == ~0)
+    {
+      /* No stream specified: enable/disable all streams. */
+      /* *INDENT-OFF* */
+        pool_foreach (s, pg->streams, ({
+            pg_stream_enable_disable (pg, s, is_enable);
+        }));
+       /* *INDENT-ON* */
+    }
+  else
+    {
+      /* enable/disable specified stream. */
+      s = pool_elt_at_index (pg->streams, stream_index);
+      pg_stream_enable_disable (pg, s, is_enable);
+    }
+}
+
+clib_error_t *
+pg_capture (pg_capture_args_t * a)
+{
+  pg_main_t *pg = &pg_main;
+  pg_interface_t *pi;
+
+  if (a->is_enabled == 1)
+    {
+      struct stat sb;
+      if (stat ((char *) a->pcap_file_name, &sb) != -1)
+       return clib_error_return (0, "Cannot create pcap file");
+    }
+
+  pi = pool_elt_at_index (pg->interfaces, a->dev_instance);
+  vec_free (pi->pcap_file_name);
+  memset (&pi->pcap_main, 0, sizeof (pi->pcap_main));
+
+  if (a->is_enabled == 0)
+    return 0;
+
+  pi->pcap_file_name = a->pcap_file_name;
+  pi->pcap_main.file_name = (char *) pi->pcap_file_name;
+  pi->pcap_main.n_packets_to_capture = a->count;
+  pi->pcap_main.packet_type = PCAP_PACKET_TYPE_ethernet;
+
+  return 0;
+}
 
 static clib_error_t *
 enable_disable_stream (vlib_main_t * vm,
-                      unformat_input_t * input,
-                      vlib_cli_command_t * cmd)
+                      unformat_input_t * input, vlib_cli_command_t * cmd)
 {
-  pg_main_t * pg = &pg_main;
-  pg_stream_t * s;
+  pg_main_t *pg = &pg_main;
   int is_enable = cmd->function_arg != 0;
   u32 stream_index = ~0;
 
@@ -71,41 +122,36 @@ enable_disable_stream (vlib_main_t * vm,
     return clib_error_create ("unknown input `%U'",
                              format_unformat_error, input);
 
-  /* No stream specified: enable/disable all streams. */
-  if (stream_index == ~0)
-    pool_foreach (s, pg->streams, ({
-      pg_stream_enable_disable (pg, s, is_enable);
-    }));
-  else
-    {
-      /* enable/disable specified stream. */
-      s = pool_elt_at_index (pg->streams, stream_index);
-      pg_stream_enable_disable (pg, s, is_enable);
-    }
-                     
+  pg_enable_disable (stream_index, is_enable);
+
   return 0;
 }
 
+/* *INDENT-OFF* */
 VLIB_CLI_COMMAND (enable_streams_cli, static) = {
   .path = "packet-generator enable-stream",
   .short_help = "Enable packet generator streams",
   .function = enable_disable_stream,
   .function_arg = 1,           /* is_enable */
 };
+/* *INDENT-ON* */
 
+/* *INDENT-OFF* */
 VLIB_CLI_COMMAND (disable_streams_cli, static) = {
   .path = "packet-generator disable-stream",
   .short_help = "Disable packet generator streams",
   .function = enable_disable_stream,
   .function_arg = 0,           /* is_enable */
 };
+/* *INDENT-ON* */
 
-static u8 * format_pg_stream (u8 * s, va_list * va)
+static u8 *
+format_pg_stream (u8 * s, va_list * va)
 {
-  pg_stream_t * t = va_arg (*va, pg_stream_t *);
-  u8 * v;
+  pg_stream_t *t = va_arg (*va, pg_stream_t *);
+  u8 *v;
 
-  if (! t)
+  if (!t)
     return format (s, "%=16s%=12s%=16s%s",
                   "Name", "Enabled", "Count", "Parameters");
 
@@ -127,6 +173,8 @@ static u8 * format_pg_stream (u8 * s, va_list * va)
 
   v = format (v, "buffer-size %d, ", t->buffer_bytes);
 
+  v = format (v, "worker %d, ", t->worker_index);
+
   if (v)
     {
       s = format (s, "  %v", v);
@@ -138,11 +186,10 @@ static u8 * format_pg_stream (u8 * s, va_list * va)
 
 static clib_error_t *
 show_streams (vlib_main_t * vm,
-             unformat_input_t * input,
-             vlib_cli_command_t * cmd)
+             unformat_input_t * input, vlib_cli_command_t * cmd)
 {
-  pg_main_t * pg = &pg_main;
-  pg_stream_t * s;
+  pg_main_t *pg = &pg_main;
+  pg_stream_t *s;
 
   if (pool_elts (pg->streams) == 0)
     {
@@ -151,28 +198,32 @@ show_streams (vlib_main_t * vm,
     }
 
   vlib_cli_output (vm, "%U", format_pg_stream, 0);
+  /* *INDENT-OFF* */
   pool_foreach (s, pg->streams, ({
       vlib_cli_output (vm, "%U", format_pg_stream, s);
     }));
+  /* *INDENT-ON* */
 
- done:
+done:
   return 0;
 }
 
+/* *INDENT-OFF* */
 VLIB_CLI_COMMAND (show_streams_cli, static) = {
   .path = "show packet-generator",
   .short_help = "Show packet generator streams",
   .function = show_streams,
 };
+/* *INDENT-ON* */
 
 static clib_error_t *
-pg_pcap_read (pg_stream_t * s, char * file_name)
+pg_pcap_read (pg_stream_t * s, char *file_name)
 {
 #ifndef CLIB_UNIX
   return clib_error_return (0, "no pcap support");
 #else
   pcap_main_t pm;
-  clib_error_t * error;
+  clib_error_t *error;
   memset (&pm, 0, sizeof (pm));
   pm.file_name = file_name;
   error = pcap_read (&pm);
@@ -193,7 +244,7 @@ pg_pcap_read (pg_stream_t * s, char * file_name)
 static uword
 unformat_pg_stream_parameter (unformat_input_t * input, va_list * args)
 {
-  pg_stream_t * s = va_arg (*args, pg_stream_t *);
+  pg_stream_t *s = va_arg (*args, pg_stream_t *);
   f64 x;
 
   if (unformat (input, "limit %f", &x))
@@ -226,8 +277,9 @@ validate_stream (pg_stream_t * s)
     return clib_error_create ("max-size < min-size");
 
   if (s->buffer_bytes >= 4096 || s->buffer_bytes == 0)
-    return clib_error_create ("buffer-size must be positive and < 4096, given %d",
-                             s->buffer_bytes);
+    return
+      clib_error_create ("buffer-size must be positive and < 4096, given %d",
+                        s->buffer_bytes);
 
   if (s->rate_packets_per_second < 0)
     return clib_error_create ("negative rate");
@@ -237,19 +289,18 @@ validate_stream (pg_stream_t * s)
 
 static clib_error_t *
 new_stream (vlib_main_t * vm,
-           unformat_input_t * input,
-           vlib_cli_command_t * cmd)
+           unformat_input_t * input, vlib_cli_command_t * cmd)
 {
-  clib_error_t * error = 0;
-  u8 * tmp = 0;
+  clib_error_t *error = 0;
+  u8 *tmp = 0;
   u32 hw_if_index;
-  unformat_input_t sub_input = {0};
+  unformat_input_t sub_input = { 0 };
   int sub_input_given = 0;
-  vnet_main_t * vnm = vnet_get_main();
-  pg_main_t * pg = &pg_main;
-  pg_stream_t s = {0};
-  char * pcap_file_name;
-  
+  vnet_main_t *vnm = vnet_get_main ();
+  pg_main_t *pg = &pg_main;
+  pg_stream_t s = { 0 };
+  char *pcap_file_name;
+
   s.sw_if_index[VLIB_RX] = s.sw_if_index[VLIB_TX] = ~0;
   s.node_index = ~0;
   s.max_packet_bytes = s.min_packet_bytes = 64;
@@ -268,30 +319,34 @@ new_stream (vlib_main_t * vm,
       else if (unformat (input, "node %U",
                         unformat_vnet_hw_interface, vnm, &hw_if_index))
        {
-         vnet_hw_interface_t * hi = vnet_get_hw_interface (vnm, hw_if_index);
+         vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index);
 
          s.node_index = hi->output_node_index;
          s.sw_if_index[VLIB_TX] = hi->sw_if_index;
        }
 
-      else if (unformat (input, "source pg%u",&s.if_id))
+      else if (unformat (input, "source pg%u", &s.if_id))
        ;
 
       else if (unformat (input, "node %U",
                         unformat_vlib_node, vm, &s.node_index))
        ;
-                        
+
+      else if (unformat (input, "worker %u", &s.worker_index))
+       ;
+
       else if (unformat (input, "interface %U",
-                        unformat_vnet_sw_interface, vnm, &s.sw_if_index[VLIB_RX]))
+                        unformat_vnet_sw_interface, vnm,
+                        &s.sw_if_index[VLIB_RX]))
        ;
 
       else if (unformat (input, "pcap %s", &pcap_file_name))
        ;
 
-      else if (! sub_input_given
+      else if (!sub_input_given
               && unformat (input, "data %U", unformat_input, &sub_input))
        sub_input_given++;
-                        
+
       else if (unformat_user (input, unformat_pg_stream_parameter, &s))
        ;
 
@@ -310,7 +365,7 @@ new_stream (vlib_main_t * vm,
   if (error)
     return error;
 
-  if (! sub_input_given && ! pcap_file_name)
+  if (!sub_input_given && !pcap_file_name)
     {
       error = clib_error_create ("no packet data given");
       goto done;
@@ -320,7 +375,8 @@ new_stream (vlib_main_t * vm,
     {
       if (pcap_file_name != 0)
        {
-         vlib_node_t * n = vlib_get_node_by_name(vm, (u8 *) "ethernet-input");
+         vlib_node_t *n =
+           vlib_get_node_by_name (vm, (u8 *) "ethernet-input");
          s.node_index = n->index;
        }
       else
@@ -331,13 +387,16 @@ new_stream (vlib_main_t * vm,
     }
 
   {
-    pg_node_t * n;
+    pg_node_t *n;
 
     if (s.node_index < vec_len (pg->nodes))
       n = pg->nodes + s.node_index;
     else
       n = 0;
 
+    if (s.worker_index >= vlib_num_workers ())
+      s.worker_index = 0;
+
     if (pcap_file_name != 0)
       {
        error = pg_pcap_read (&s, pcap_file_name);
@@ -347,10 +406,10 @@ new_stream (vlib_main_t * vm,
       }
 
     else if (n && n->unformat_edit
-       && unformat_user (&sub_input, n->unformat_edit, &s))
+            && unformat_user (&sub_input, n->unformat_edit, &s))
       ;
 
-    else if (! unformat_user (&sub_input, unformat_pg_payload, &s))
+    else if (!unformat_user (&sub_input, unformat_pg_payload, &s))
       {
        error = clib_error_create
          ("failed to parse packet data from `%U'",
@@ -362,12 +421,13 @@ new_stream (vlib_main_t * vm,
   pg_stream_add (pg, &s);
   return 0;
 
- done:
+done:
   pg_stream_free (&s);
   unformat_free (&sub_input);
   return error;
 }
 
+/* *INDENT-OFF* */
 VLIB_CLI_COMMAND (new_stream_cli, static) = {
   .path = "packet-generator new",
   .function = new_stream,
@@ -383,17 +443,17 @@ VLIB_CLI_COMMAND (new_stream_cli, static) = {
   "data STRING          specifies packet data\n"
   "pcap FILENAME        read packet data from pcap file\n",
 };
+/* *INDENT-ON* */
 
 static clib_error_t *
 del_stream (vlib_main_t * vm,
-           unformat_input_t * input,
-           vlib_cli_command_t * cmd)
+           unformat_input_t * input, vlib_cli_command_t * cmd)
 {
-  pg_main_t * pg = &pg_main;
+  pg_main_t *pg = &pg_main;
   u32 i;
-  
-  if (! unformat (input, "%U",
-                 &unformat_hash_vec_string, pg->stream_index_by_name, &i))
+
+  if (!unformat (input, "%U",
+                &unformat_hash_vec_string, pg->stream_index_by_name, &i))
     return clib_error_create ("expected stream name `%U'",
                              format_unformat_error, input);
 
@@ -401,21 +461,22 @@ del_stream (vlib_main_t * vm,
   return 0;
 }
 
+/* *INDENT-OFF* */
 VLIB_CLI_COMMAND (del_stream_cli, static) = {
   .path = "packet-generator delete",
   .function = del_stream,
   .short_help = "Delete stream with given name",
 };
+/* *INDENT-ON* */
 
 static clib_error_t *
 change_stream_parameters (vlib_main_t * vm,
-                         unformat_input_t * input,
-                         vlib_cli_command_t * cmd)
+                         unformat_input_t * input, vlib_cli_command_t * cmd)
 {
-  pg_main_t * pg = &pg_main;
-  pg_stream_t * s, s_new;
+  pg_main_t *pg = &pg_main;
+  pg_stream_t *s, s_new;
   u32 stream_index = ~0;
-  clib_error_t * error;
+  clib_error_t *error;
 
   if (unformat (input, "%U", unformat_hash_vec_string,
                pg->stream_index_by_name, &stream_index))
@@ -438,41 +499,40 @@ change_stream_parameters (vlib_main_t * vm,
     }
 
   error = validate_stream (&s_new);
-  if (! error)
+  if (!error)
     s[0] = s_new;
 
   return error;
 }
 
+/* *INDENT-OFF* */
 VLIB_CLI_COMMAND (change_stream_parameters_cli, static) = {
   .path = "packet-generator configure",
   .short_help = "Change packet generator stream parameters",
   .function = change_stream_parameters,
 };
+/* *INDENT-ON* */
 
 static clib_error_t *
 pg_capture_cmd_fn (vlib_main_t * vm,
-                 unformat_input_t * input,
-                 vlib_cli_command_t * cmd)
+                  unformat_input_t * input, vlib_cli_command_t * cmd)
 {
-  pg_main_t * pg = &pg_main;
-  clib_error_t * error = 0;
-  vnet_main_t * vnm = vnet_get_main();
-  unformat_input_t _line_input, * line_input = &_line_input;
-  vnet_hw_interface_t * hi = 0;
-  pg_interface_t * pi;
-  u8 * pcap_file_name = 0;
+  clib_error_t *error = 0;
+  vnet_main_t *vnm = vnet_get_main ();
+  unformat_input_t _line_input, *line_input = &_line_input;
+  vnet_hw_interface_t *hi = 0;
+  u8 *pcap_file_name = 0;
   u32 hw_if_index;
   u32 is_disable = 0;
   u32 count = ~0;
 
-  if (! unformat_user (input, unformat_line_input, line_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, "%U",
-                        unformat_vnet_hw_interface, vnm, &hw_if_index))
+                   unformat_vnet_hw_interface, vnm, &hw_if_index))
        {
          hi = vnet_get_hw_interface (vnm, hw_if_index);
        }
@@ -501,46 +561,37 @@ pg_capture_cmd_fn (vlib_main_t * vm,
   if (!pcap_file_name && is_disable == 0)
     return clib_error_return (0, "Please specify pcap file name");
 
-  if (is_disable == 0)
-    {
-      struct stat sb;
-      if (stat ((char *) pcap_file_name, &sb) != -1)
-       return clib_error_return (0, "Cannot create pcap file");
-    }
-
   unformat_free (line_input);
 
-  pi = pool_elt_at_index (pg->interfaces, hi->dev_instance);
-  vec_free (pi->pcap_file_name);
-  memset (&pi->pcap_main, 0, sizeof (pi->pcap_main));
+  pg_capture_args_t _a, *a = &_a;
 
-  if (is_disable)
-    return 0;
+  a->hw_if_index = hw_if_index;
+  a->dev_instance = hi->dev_instance;
+  a->is_enabled = !is_disable;
+  a->pcap_file_name = pcap_file_name;
+  a->count = count;
 
-  pi->pcap_file_name = pcap_file_name;
-  pi->pcap_main.file_name = (char *) pi->pcap_file_name;
-  pi->pcap_main.n_packets_to_capture = count;
-  pi->pcap_main.packet_type = PCAP_PACKET_TYPE_ethernet;
-
-  return 0;
+  error = pg_capture (a);
+  return error;
 }
 
+/* *INDENT-OFF* */
 VLIB_CLI_COMMAND (pg_capture_cmd, static) = {
   .path = "packet-generator capture",
   .short_help = "packet-generator capture <interface name> pcap <filename> [count <n>]",
   .function = pg_capture_cmd_fn,
 };
+/* *INDENT-ON* */
 
 static clib_error_t *
 create_pg_if_cmd_fn (vlib_main_t * vm,
-                    unformat_input_t * input,
-                    vlib_cli_command_t * cmd)
+                    unformat_input_t * input, vlib_cli_command_t * cmd)
 {
-  pg_main_t * pg = &pg_main;
-  unformat_input_t _line_input, * line_input = &_line_input;
+  pg_main_t *pg = &pg_main;
+  unformat_input_t _line_input, *line_input = &_line_input;
   u32 if_id;
 
-  if (! unformat_user (input, unformat_line_input, line_input))
+  if (!unformat_user (input, unformat_line_input, line_input))
     return 0;
 
   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
@@ -559,14 +610,27 @@ create_pg_if_cmd_fn (vlib_main_t * vm,
   return 0;
 }
 
+/* *INDENT-OFF* */
 VLIB_CLI_COMMAND (create_pg_if_cmd, static) = {
   .path = "create packet-generator",
   .short_help = "create packet-generator interface <interface name>",
   .function = create_pg_if_cmd_fn,
 };
+/* *INDENT-ON* */
 
 /* Dummy init function so that we can be linked in. */
-static clib_error_t * pg_cli_init (vlib_main_t * vm)
-{ return 0; }
+static clib_error_t *
+pg_cli_init (vlib_main_t * vm)
+{
+  return 0;
+}
 
 VLIB_INIT_FUNCTION (pg_cli_init);
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */