LCOV - code coverage report
Current view: top level - vnet/pg - cli.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 197 305 64.6 %
Date: 2023-07-05 22:20:52 Functions: 33 36 91.7 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2015 Cisco and/or its affiliates.
       3             :  * Licensed under the Apache License, Version 2.0 (the "License");
       4             :  * you may not use this file except in compliance with the License.
       5             :  * You may obtain a copy of the License at:
       6             :  *
       7             :  *     http://www.apache.org/licenses/LICENSE-2.0
       8             :  *
       9             :  * Unless required by applicable law or agreed to in writing, software
      10             :  * distributed under the License is distributed on an "AS IS" BASIS,
      11             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      12             :  * See the License for the specific language governing permissions and
      13             :  * limitations under the License.
      14             :  */
      15             : /*
      16             :  * pg_cli.c: packet generator cli
      17             :  *
      18             :  * Copyright (c) 2008 Eliot Dresselhaus
      19             :  *
      20             :  * Permission is hereby granted, free of charge, to any person obtaining
      21             :  * a copy of this software and associated documentation files (the
      22             :  * "Software"), to deal in the Software without restriction, including
      23             :  * without limitation the rights to use, copy, modify, merge, publish,
      24             :  * distribute, sublicense, and/or sell copies of the Software, and to
      25             :  * permit persons to whom the Software is furnished to do so, subject to
      26             :  * the following conditions:
      27             :  *
      28             :  * The above copyright notice and this permission notice shall be
      29             :  * included in all copies or substantial portions of the Software.
      30             :  *
      31             :  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
      32             :  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
      33             :  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
      34             :  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
      35             :  *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
      36             :  *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
      37             :  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      38             :  */
      39             : 
      40             : #include <sys/stat.h>
      41             : 
      42             : #include <vnet/vnet.h>
      43             : #include <vnet/pg/pg.h>
      44             : 
      45             : #include <strings.h>
      46             : #include <vppinfra/pcap.h>
      47             : 
      48             : 
      49             : /* Root of all packet generator cli commands. */
      50             : /* *INDENT-OFF* */
      51      272887 : VLIB_CLI_COMMAND (vlib_cli_pg_command, static) = {
      52             :   .path = "packet-generator",
      53             :   .short_help = "Packet generator commands",
      54             : };
      55             : /* *INDENT-ON* */
      56             : 
      57             : void
      58       14674 : pg_enable_disable (u32 stream_index, int is_enable)
      59             : {
      60       14674 :   pg_main_t *pg = &pg_main;
      61             :   pg_stream_t *s;
      62             : 
      63       14674 :   if (stream_index == ~0)
      64             :     {
      65             :       /* No stream specified: enable/disable all streams. */
      66             :       /* *INDENT-OFF* */
      67       29729 :         pool_foreach (s, pg->streams)  {
      68       15055 :             pg_stream_enable_disable (pg, s, is_enable);
      69             :         }
      70             :         /* *INDENT-ON* */
      71             :     }
      72             :   else
      73             :     {
      74             :       /* enable/disable specified stream. */
      75           0 :       s = pool_elt_at_index (pg->streams, stream_index);
      76           0 :       pg_stream_enable_disable (pg, s, is_enable);
      77             :     }
      78       14674 : }
      79             : 
      80             : clib_error_t *
      81       79628 : pg_capture (pg_capture_args_t * a)
      82             : {
      83       79628 :   pg_main_t *pg = &pg_main;
      84             :   pg_interface_t *pi;
      85             : 
      86       79628 :   if (a->is_enabled == 1)
      87             :     {
      88             :       struct stat sb;
      89       39814 :       if (stat (a->pcap_file_name, &sb) != -1)
      90           0 :         return clib_error_return (0, "pcap file '%s' already exists.",
      91             :                                   a->pcap_file_name);
      92             :     }
      93             : 
      94       79628 :   pi = pool_elt_at_index (pg->interfaces, a->dev_instance);
      95       79628 :   vec_free (pi->pcap_file_name);
      96       79628 :   if ((pi->pcap_main.flags & PCAP_MAIN_INIT_DONE))
      97       13314 :     pcap_close (&pi->pcap_main);
      98       79628 :   clib_memset (&pi->pcap_main, 0, sizeof (pi->pcap_main));
      99       79628 :   pi->pcap_main.file_descriptor = -1;
     100             : 
     101       79628 :   if (a->is_enabled == 0)
     102       39814 :     return 0;
     103             : 
     104       39814 :   pi->pcap_file_name = a->pcap_file_name;
     105       39814 :   pi->pcap_main.file_name = (char *) pi->pcap_file_name;
     106       39814 :   pi->pcap_main.n_packets_to_capture = a->count;
     107       39814 :   pi->pcap_main.packet_type = PCAP_PACKET_TYPE_ethernet;
     108             : 
     109       39814 :   return 0;
     110             : }
     111             : 
     112             : static clib_error_t *
     113       14674 : enable_disable_stream (vlib_main_t * vm,
     114             :                        unformat_input_t * input, vlib_cli_command_t * cmd)
     115             : {
     116       14674 :   unformat_input_t _line_input, *line_input = &_line_input;
     117       14674 :   pg_main_t *pg = &pg_main;
     118       14674 :   int is_enable = cmd->function_arg != 0;
     119       14674 :   u32 stream_index = ~0;
     120             : 
     121       14674 :   if (!unformat_user (input, unformat_line_input, line_input))
     122       14674 :     goto doit;
     123             : 
     124           0 :   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
     125             :     {
     126           0 :       if (unformat (line_input, "%U", unformat_hash_vec_string,
     127             :                     pg->stream_index_by_name, &stream_index))
     128             :         ;
     129             :       else
     130           0 :         return clib_error_create ("unknown input `%U'",
     131             :                                   format_unformat_error, line_input);
     132             :     }
     133           0 :   unformat_free (line_input);
     134             : 
     135       14674 : doit:
     136       14674 :   pg_enable_disable (stream_index, is_enable);
     137             : 
     138       14674 :   return 0;
     139             : }
     140             : 
     141             : /* *INDENT-OFF* */
     142      272887 : VLIB_CLI_COMMAND (enable_streams_cli, static) = {
     143             :   .path = "packet-generator enable-stream",
     144             :   .short_help = "Enable packet generator streams",
     145             :   .function = enable_disable_stream,
     146             :   .function_arg = 1,            /* is_enable */
     147             : };
     148             : /* *INDENT-ON* */
     149             : 
     150             : /* *INDENT-OFF* */
     151      272887 : VLIB_CLI_COMMAND (disable_streams_cli, static) = {
     152             :   .path = "packet-generator disable-stream",
     153             :   .short_help = "Disable packet generator streams",
     154             :   .function = enable_disable_stream,
     155             :   .function_arg = 0,            /* is_enable */
     156             : };
     157             : /* *INDENT-ON* */
     158             : 
     159             : static u8 *
     160           0 : format_pg_edit_group (u8 * s, va_list * va)
     161             : {
     162           0 :   pg_edit_group_t *g = va_arg (*va, pg_edit_group_t *);
     163             : 
     164             :   s =
     165           0 :     format (s, "hdr-size %d, offset %d, ", g->n_packet_bytes,
     166             :             g->start_byte_offset);
     167           0 :   if (g->edit_function)
     168             :     {
     169             :       u8 *function_name;
     170             :       u8 *junk_after_name;
     171           0 :       function_name = format (0, "%U%c", format_clib_elf_symbol_with_address,
     172             :                               g->edit_function, 0);
     173           0 :       junk_after_name = function_name;
     174           0 :       while (*junk_after_name && *junk_after_name != ' ')
     175           0 :         junk_after_name++;
     176           0 :       *junk_after_name = 0;
     177           0 :       s = format (s, "edit-function %s, ", function_name);
     178           0 :       vec_free (function_name);
     179             :     }
     180             : 
     181           0 :   return s;
     182             : }
     183             : 
     184             : static u8 *
     185       29748 : format_pg_stream (u8 * s, va_list * va)
     186             : {
     187       29748 :   pg_stream_t *t = va_arg (*va, pg_stream_t *);
     188       29748 :   int verbose = va_arg (*va, int);
     189             : 
     190       29748 :   if (!t)
     191       14591 :     return format (s, "%-16s%=12s%=16s%s",
     192             :                    "Name", "Enabled", "Count", "Parameters");
     193             : 
     194       15157 :   s = format (s, "%-16v%=12s%=16Ld",
     195             :               t->name,
     196       15157 :               pg_stream_is_enabled (t) ? "Yes" : "No",
     197             :               t->n_packets_generated);
     198             : 
     199       15157 :   int indent = format_get_indent (s);
     200             : 
     201       15157 :   s = format (s, "limit %Ld, ", t->n_packets_limit);
     202       15157 :   s = format (s, "rate %.2e pps, ", t->rate_packets_per_second);
     203       15157 :   s = format (s, "size %d%c%d, ",
     204             :               t->min_packet_bytes,
     205       15157 :               t->packet_size_edit_type == PG_EDIT_RANDOM ? '+' : '-',
     206             :               t->max_packet_bytes);
     207       15157 :   s = format (s, "buffer-size %d, ", t->buffer_bytes);
     208       15157 :   s = format (s, "worker %d, ", t->worker_index);
     209             : 
     210       15157 :   if (verbose)
     211             :     {
     212             :       pg_edit_group_t *g;
     213             :   /* *INDENT-OFF* */
     214           0 :   vec_foreach (g, t->edit_groups)
     215             :     {
     216           0 :       s = format (s, "\n%U%U", format_white_space, indent, format_pg_edit_group, g);
     217             :     }
     218             :   /* *INDENT-ON* */
     219             :     }
     220             : 
     221       15157 :   return s;
     222             : }
     223             : 
     224             : static clib_error_t *
     225       47536 : show_streams (vlib_main_t * vm,
     226             :               unformat_input_t * input, vlib_cli_command_t * cmd)
     227             : {
     228       47536 :   pg_main_t *pg = &pg_main;
     229             :   pg_stream_t *s;
     230       47536 :   int verbose = 0;
     231             : 
     232       47536 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
     233             :     {
     234           0 :       if (unformat (input, "verbose"))
     235           0 :         verbose = 1;
     236             :       else
     237           0 :         break;
     238             :     }
     239             : 
     240       47536 :   if (pool_elts (pg->streams) == 0)
     241             :     {
     242       32945 :       vlib_cli_output (vm, "no streams currently defined");
     243       32945 :       goto done;
     244             :     }
     245             : 
     246       14591 :   vlib_cli_output (vm, "%U", format_pg_stream, 0, 0);
     247             :   /* *INDENT-OFF* */
     248       29748 :   pool_foreach (s, pg->streams)  {
     249       15157 :       vlib_cli_output (vm, "%U", format_pg_stream, s, verbose);
     250             :     }
     251             :   /* *INDENT-ON* */
     252             : 
     253       14591 : done:
     254       47536 :   return 0;
     255             : }
     256             : 
     257             : /* *INDENT-OFF* */
     258      272887 : VLIB_CLI_COMMAND (show_streams_cli, static) = {
     259             :   .path = "show packet-generator ",
     260             :   .short_help = "show packet-generator [verbose]",
     261             :   .function = show_streams,
     262             : };
     263             : /* *INDENT-ON* */
     264             : 
     265             : static clib_error_t *
     266       15047 : pg_pcap_read (pg_stream_t * s, char *file_name)
     267             : {
     268             : #ifndef CLIB_UNIX
     269             :   return clib_error_return (0, "no pcap support");
     270             : #else
     271             :   pcap_main_t pm;
     272             :   clib_error_t *error;
     273       15047 :   clib_memset (&pm, 0, sizeof (pm));
     274       15047 :   pm.file_name = file_name;
     275       15047 :   error = pcap_read (&pm);
     276       15047 :   s->replay_packet_templates = pm.packets_read;
     277       15047 :   s->replay_packet_timestamps = pm.timestamps;
     278       15047 :   s->min_packet_bytes = pm.min_packet_bytes;
     279       15047 :   s->max_packet_bytes = pm.max_packet_bytes;
     280       15047 :   s->buffer_bytes = pm.max_packet_bytes;
     281             : 
     282       15047 :   if (s->n_packets_limit == 0)
     283       15047 :     s->n_packets_limit = vec_len (pm.packets_read);
     284             : 
     285       15047 :   return error;
     286             : #endif /* CLIB_UNIX */
     287             : }
     288             : 
     289             : static uword
     290          15 : unformat_pg_stream_parameter (unformat_input_t * input, va_list * args)
     291             : {
     292          15 :   pg_stream_t *s = va_arg (*args, pg_stream_t *);
     293             :   f64 x;
     294             : 
     295          15 :   if (unformat (input, "limit %f", &x))
     296           6 :     s->n_packets_limit = x;
     297             : 
     298           9 :   else if (unformat (input, "rate %f", &x))
     299           3 :     s->rate_packets_per_second = x;
     300             : 
     301           6 :   else if (unformat (input, "size %d-%d", &s->min_packet_bytes,
     302             :                      &s->max_packet_bytes))
     303           6 :     s->packet_size_edit_type = PG_EDIT_INCREMENT;
     304             : 
     305           0 :   else if (unformat (input, "size %d+%d", &s->min_packet_bytes,
     306             :                      &s->max_packet_bytes))
     307           0 :     s->packet_size_edit_type = PG_EDIT_RANDOM;
     308             : 
     309           0 :   else if (unformat (input, "buffer-size %d", &s->buffer_bytes))
     310             :     ;
     311             : 
     312             :   else
     313           0 :     return 0;
     314             : 
     315          15 :   return 1;
     316             : }
     317             : 
     318             : static clib_error_t *
     319       15053 : validate_stream (pg_stream_t * s)
     320             : {
     321       15053 :   if (s->max_packet_bytes < s->min_packet_bytes)
     322           0 :     return clib_error_create ("max-size < min-size");
     323             : 
     324       15053 :   u32 hdr_size = pg_edit_group_n_bytes (s, 0);
     325       15053 :   if (s->min_packet_bytes < hdr_size)
     326           0 :     return clib_error_create ("min-size < total header size %d", hdr_size);
     327       15053 :   if (s->buffer_bytes == 0)
     328           0 :     return clib_error_create ("buffer-size must be positive");
     329             : 
     330       15053 :   if (s->rate_packets_per_second < 0)
     331           0 :     return clib_error_create ("negative rate");
     332             : 
     333       15053 :   return 0;
     334             : }
     335             : 
     336             : const char *
     337       15047 : pg_interface_get_input_node (pg_interface_t *pi)
     338             : {
     339       15047 :   switch (pi->mode)
     340             :     {
     341       15042 :     case PG_MODE_ETHERNET:
     342       15042 :       return ("ethernet-input");
     343           3 :     case PG_MODE_IP4:
     344           3 :       return ("ip4-input");
     345           2 :     case PG_MODE_IP6:
     346           2 :       return ("ip6-input");
     347             :     }
     348             : 
     349           0 :   ASSERT (0);
     350           0 :   return ("ethernet-input");
     351             : }
     352             : 
     353             : static clib_error_t *
     354       15053 : new_stream (vlib_main_t * vm,
     355             :             unformat_input_t * input, vlib_cli_command_t * cmd)
     356             : {
     357       15053 :   clib_error_t *error = 0;
     358       15053 :   u8 *tmp = 0;
     359             :   u32 maxframe, hw_if_index;
     360       15053 :   unformat_input_t sub_input = { 0 };
     361       15053 :   int sub_input_given = 0;
     362       15053 :   vnet_main_t *vnm = vnet_get_main ();
     363       15053 :   pg_main_t *pg = &pg_main;
     364       15053 :   pg_stream_t s = { 0 };
     365             :   char *pcap_file_name;
     366             : 
     367       15053 :   s.sw_if_index[VLIB_RX] = s.sw_if_index[VLIB_TX] = ~0;
     368       15053 :   s.node_index = ~0;
     369       15053 :   s.max_packet_bytes = s.min_packet_bytes = 64;
     370       15053 :   s.buffer_bytes = vlib_buffer_get_default_data_size (vm);
     371       15053 :   s.if_id = ~0;
     372       15053 :   s.n_max_frame = VLIB_FRAME_SIZE;
     373       15053 :   pcap_file_name = 0;
     374             : 
     375       60391 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
     376             :     {
     377       45338 :       if (unformat (input, "name %v", &tmp))
     378             :         {
     379       15053 :           if (s.name)
     380           0 :             vec_free (s.name);
     381       15053 :           s.name = tmp;
     382             :         }
     383             : 
     384       30285 :       else if (unformat (input, "node %U",
     385             :                          unformat_vnet_hw_interface, vnm, &hw_if_index))
     386             :         {
     387           0 :           vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index);
     388             : 
     389           0 :           s.node_index = hi->output_node_index;
     390           0 :           s.sw_if_index[VLIB_TX] = hi->sw_if_index;
     391             :         }
     392             : 
     393       30285 :       else if (unformat (input, "source pg%u", &s.if_id))
     394             :         ;
     395             : 
     396       15238 :       else if (unformat (input, "buffer-flags %U",
     397             :                          unformat_vnet_buffer_flags, &s.buffer_flags))
     398             :         ;
     399       15236 :       else if (unformat (input, "buffer-offload-flags %U",
     400             :                          unformat_vnet_buffer_offload_flags, &s.buffer_oflags))
     401             :         ;
     402       15234 :       else if (unformat (input, "node %U",
     403             :                          unformat_vlib_node, vm, &s.node_index))
     404             :         ;
     405       15228 :       else if (unformat (input, "maxframe %u", &maxframe))
     406           0 :         s.n_max_frame = s.n_max_frame < maxframe ? s.n_max_frame : maxframe;
     407       15228 :       else if (unformat (input, "worker %u", &s.worker_index))
     408             :         ;
     409             : 
     410       15076 :       else if (unformat (input, "interface %U",
     411             :                          unformat_vnet_sw_interface, vnm,
     412             :                          &s.sw_if_index[VLIB_RX]))
     413             :         ;
     414       15070 :       else if (unformat (input, "tx-interface %U",
     415             :                          unformat_vnet_sw_interface, vnm,
     416             :                          &s.sw_if_index[VLIB_TX]))
     417             :         ;
     418             : 
     419       15068 :       else if (unformat (input, "pcap %s", &pcap_file_name))
     420             :         ;
     421             : 
     422          21 :       else if (!sub_input_given
     423          21 :                && unformat (input, "data %U", unformat_input, &sub_input))
     424           6 :         sub_input_given++;
     425             : 
     426          15 :       else if (unformat_user (input, unformat_pg_stream_parameter, &s))
     427             :         ;
     428             : 
     429             :       else
     430             :         {
     431           0 :           error = clib_error_create ("unknown input `%U'",
     432             :                                      format_unformat_error, input);
     433           0 :           goto done;
     434             :         }
     435             :     }
     436             : 
     437       15053 :   if (!sub_input_given && !pcap_file_name)
     438             :     {
     439           0 :       error = clib_error_create ("no packet data given");
     440           0 :       goto done;
     441             :     }
     442             : 
     443       15053 :   if (s.node_index == ~0)
     444             :     {
     445       15047 :       if (pcap_file_name != 0)
     446             :         {
     447             :           vlib_node_t *n;
     448             : 
     449       15047 :           if (s.if_id != ~0)
     450       15047 :             n = vlib_get_node_by_name (vm, (u8 *) pg_interface_get_input_node (
     451       15047 :                                              &pg->interfaces[s.if_id]));
     452             :           else
     453           0 :             n = vlib_get_node_by_name (vm, (u8 *) "ethernet-input");
     454       15047 :           s.node_index = n->index;
     455             :         }
     456             :       else
     457             :         {
     458           0 :           error = clib_error_create ("output interface or node not given");
     459           0 :           goto done;
     460             :         }
     461             :     }
     462             : 
     463             :   {
     464             :     pg_node_t *n;
     465             : 
     466       15053 :     if (s.node_index < vec_len (pg->nodes))
     467       15053 :       n = pg->nodes + s.node_index;
     468             :     else
     469           0 :       n = 0;
     470             : 
     471       15053 :     if (s.worker_index >= vlib_num_workers ())
     472       14305 :       s.worker_index = 0;
     473             : 
     474       15053 :     if (pcap_file_name != 0)
     475             :       {
     476       15047 :         error = pg_pcap_read (&s, pcap_file_name);
     477       15047 :         if (error)
     478           0 :           goto done;
     479       15047 :         vec_free (pcap_file_name);
     480             :       }
     481             : 
     482           6 :     else if (n && n->unformat_edit
     483           6 :              && unformat_user (&sub_input, n->unformat_edit, &s))
     484             :       ;
     485             : 
     486           0 :     else if (!unformat_user (&sub_input, unformat_pg_payload, &s))
     487             :       {
     488           0 :         error = clib_error_create
     489             :           ("failed to parse packet data from `%U'",
     490             :            format_unformat_error, &sub_input);
     491           0 :         goto done;
     492             :       }
     493             :   }
     494             : 
     495       15053 :   error = validate_stream (&s);
     496       15053 :   if (error)
     497           0 :     return error;
     498             : 
     499       15053 :   pg_stream_add (pg, &s);
     500       15053 :   return 0;
     501             : 
     502           0 : done:
     503           0 :   pg_stream_free (&s);
     504           0 :   unformat_free (&sub_input);
     505           0 :   return error;
     506             : }
     507             : 
     508             : /* *INDENT-OFF* */
     509      272887 : VLIB_CLI_COMMAND (new_stream_cli, static) = {
     510             :   .path = "packet-generator new",
     511             :   .function = new_stream,
     512             :   .short_help = "Create packet generator stream",
     513             :   .long_help =
     514             :   "Create packet generator stream\n"
     515             :   "\n"
     516             :   "Arguments:\n"
     517             :   "\n"
     518             :   "name STRING          sets stream name\n"
     519             :   "interface STRING     interface for stream output \n"
     520             :   "node NODE-NAME       node for stream output\n"
     521             :   "data STRING          specifies packet data\n"
     522             :   "pcap FILENAME        read packet data from pcap file\n"
     523             :   "rate PPS             rate to transfer packet data\n"
     524             :   "maxframe NPKTS       maximum number of packets per frame\n",
     525             : };
     526             : /* *INDENT-ON* */
     527             : 
     528             : static clib_error_t *
     529       15047 : del_stream (vlib_main_t * vm,
     530             :             unformat_input_t * input, vlib_cli_command_t * cmd)
     531             : {
     532       15047 :   pg_main_t *pg = &pg_main;
     533             :   u32 i;
     534             : 
     535       15047 :   if (!unformat (input, "%U",
     536             :                  &unformat_hash_vec_string, pg->stream_index_by_name, &i))
     537           0 :     return clib_error_create ("expected stream name `%U'",
     538             :                               format_unformat_error, input);
     539             : 
     540       15047 :   pg_stream_del (pg, i);
     541       15047 :   return 0;
     542             : }
     543             : 
     544             : /* *INDENT-OFF* */
     545      272887 : VLIB_CLI_COMMAND (del_stream_cli, static) = {
     546             :   .path = "packet-generator delete",
     547             :   .function = del_stream,
     548             :   .short_help = "Delete stream with given name",
     549             : };
     550             : /* *INDENT-ON* */
     551             : 
     552             : static clib_error_t *
     553           0 : change_stream_parameters (vlib_main_t * vm,
     554             :                           unformat_input_t * input, vlib_cli_command_t * cmd)
     555             : {
     556           0 :   pg_main_t *pg = &pg_main;
     557             :   pg_stream_t *s, s_new;
     558           0 :   u32 stream_index = ~0;
     559             :   clib_error_t *error;
     560             : 
     561           0 :   if (unformat (input, "%U", unformat_hash_vec_string,
     562             :                 pg->stream_index_by_name, &stream_index))
     563             :     ;
     564             :   else
     565           0 :     return clib_error_create ("expecting stream name; got `%U'",
     566             :                               format_unformat_error, input);
     567             : 
     568           0 :   s = pool_elt_at_index (pg->streams, stream_index);
     569           0 :   s_new = s[0];
     570             : 
     571           0 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
     572             :     {
     573           0 :       if (unformat_user (input, unformat_pg_stream_parameter, &s_new))
     574             :         ;
     575             : 
     576             :       else
     577           0 :         return clib_error_create ("unknown input `%U'",
     578             :                                   format_unformat_error, input);
     579             :     }
     580             : 
     581           0 :   error = validate_stream (&s_new);
     582           0 :   if (!error)
     583             :     {
     584           0 :       s[0] = s_new;
     585           0 :       pg_stream_change (pg, s);
     586             :     }
     587             : 
     588           0 :   return error;
     589             : }
     590             : 
     591             : /* *INDENT-OFF* */
     592      272887 : VLIB_CLI_COMMAND (change_stream_parameters_cli, static) = {
     593             :   .path = "packet-generator configure",
     594             :   .short_help = "Change packet generator stream parameters",
     595             :   .function = change_stream_parameters,
     596             : };
     597             : /* *INDENT-ON* */
     598             : 
     599             : static clib_error_t *
     600       79628 : pg_capture_cmd_fn (vlib_main_t * vm,
     601             :                    unformat_input_t * input, vlib_cli_command_t * cmd)
     602             : {
     603       79628 :   clib_error_t *error = 0;
     604       79628 :   vnet_main_t *vnm = vnet_get_main ();
     605       79628 :   unformat_input_t _line_input, *line_input = &_line_input;
     606       79628 :   vnet_hw_interface_t *hi = 0;
     607       79628 :   u8 *pcap_file_name = 0;
     608             :   u32 hw_if_index;
     609       79628 :   u32 is_disable = 0;
     610       79628 :   u32 count = ~0;
     611             : 
     612       79628 :   if (!unformat_user (input, unformat_line_input, line_input))
     613           0 :     return 0;
     614             : 
     615      278698 :   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
     616             :     {
     617      199070 :       if (unformat (line_input, "%U",
     618             :                     unformat_vnet_hw_interface, vnm, &hw_if_index))
     619             :         {
     620       79628 :           hi = vnet_get_hw_interface (vnm, hw_if_index);
     621             :         }
     622             : 
     623      119442 :       else if (unformat (line_input, "pcap %s", &pcap_file_name))
     624             :         ;
     625       39814 :       else if (unformat (line_input, "count %u", &count))
     626             :         ;
     627       39814 :       else if (unformat (line_input, "disable"))
     628       39814 :         is_disable = 1;
     629             : 
     630             :       else
     631             :         {
     632           0 :           error = clib_error_create ("unknown input `%U'",
     633             :                                      format_unformat_error, line_input);
     634           0 :           goto done;
     635             :         }
     636             :     }
     637             : 
     638       79628 :   if (!hi)
     639             :     {
     640           0 :       error = clib_error_return (0, "Please specify interface name");
     641           0 :       goto done;
     642             :     }
     643             : 
     644       79628 :   if (hi->dev_class_index != pg_dev_class.index)
     645             :     {
     646             :       error =
     647           0 :         clib_error_return (0, "Please specify packet-generator interface");
     648           0 :       goto done;
     649             :     }
     650             : 
     651       79628 :   if (!pcap_file_name && is_disable == 0)
     652             :     {
     653           0 :       error = clib_error_return (0, "Please specify pcap file name");
     654           0 :       goto done;
     655             :     }
     656             : 
     657             : 
     658       79628 :   pg_capture_args_t _a, *a = &_a;
     659             : 
     660       79628 :   a->hw_if_index = hw_if_index;
     661       79628 :   a->dev_instance = hi->dev_instance;
     662       79628 :   a->is_enabled = !is_disable;
     663       79628 :   a->pcap_file_name = (char *) pcap_file_name;
     664       79628 :   a->count = count;
     665             : 
     666       79628 :   error = pg_capture (a);
     667             : 
     668       79628 : done:
     669       79628 :   unformat_free (line_input);
     670             : 
     671       79628 :   return error;
     672             : }
     673             : 
     674             : /* *INDENT-OFF* */
     675      272887 : VLIB_CLI_COMMAND (pg_capture_cmd, static) = {
     676             :   .path = "packet-generator capture",
     677             :   .short_help = "packet-generator capture <interface name> pcap <filename> [count <n>]",
     678             :   .function = pg_capture_cmd_fn,
     679             : };
     680             : /* *INDENT-ON* */
     681             : 
     682             : static clib_error_t *
     683           0 : create_pg_if_cmd_fn (vlib_main_t * vm,
     684             :                      unformat_input_t * input, vlib_cli_command_t * cmd)
     685             : {
     686           0 :   pg_main_t *pg = &pg_main;
     687           0 :   unformat_input_t _line_input, *line_input = &_line_input;
     688           0 :   u32 if_id, gso_enabled = 0, gso_size = 0, coalesce_enabled = 0;
     689           0 :   clib_error_t *error = NULL;
     690           0 :   pg_interface_mode_t mode = PG_MODE_ETHERNET;
     691             : 
     692           0 :   if (!unformat_user (input, unformat_line_input, line_input))
     693           0 :     return 0;
     694             : 
     695           0 :   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
     696             :     {
     697           0 :       if (unformat (line_input, "interface pg%u", &if_id))
     698             :         ;
     699           0 :       else if (unformat (line_input, "coalesce-enabled"))
     700           0 :         coalesce_enabled = 1;
     701           0 :       else if (unformat (line_input, "gso-enabled"))
     702             :         {
     703           0 :           gso_enabled = 1;
     704           0 :           if (unformat (line_input, "gso-size %u", &gso_size))
     705             :             ;
     706             :           else
     707             :             {
     708           0 :               error = clib_error_create ("gso enabled but gso size missing");
     709           0 :               goto done;
     710             :             }
     711             :         }
     712           0 :       else if (unformat (line_input, "mode ip4"))
     713           0 :         mode = PG_MODE_IP4;
     714           0 :       else if (unformat (line_input, "mode ip6"))
     715           0 :         mode = PG_MODE_IP6;
     716             :       else
     717             :         {
     718           0 :           error = clib_error_create ("unknown input `%U'",
     719             :                                      format_unformat_error, line_input);
     720           0 :           goto done;
     721             :         }
     722             :     }
     723             : 
     724           0 :   pg_interface_add_or_get (pg, if_id, gso_enabled, gso_size, coalesce_enabled,
     725             :                            mode);
     726             : 
     727           0 : done:
     728           0 :   unformat_free (line_input);
     729             : 
     730           0 :   return error;
     731             : }
     732             : 
     733             : /* *INDENT-OFF* */
     734      272887 : VLIB_CLI_COMMAND (create_pg_if_cmd, static) = {
     735             :   .path = "create packet-generator",
     736             :   .short_help = "create packet-generator interface <interface name>"
     737             :                 " [gso-enabled gso-size <size> [coalesce-enabled]]"
     738             :                 " [mode <ethernet | ip4 | ip6>]",
     739             :   .function = create_pg_if_cmd_fn,
     740             : };
     741             : /* *INDENT-ON* */
     742             : 
     743             : /* Dummy init function so that we can be linked in. */
     744             : static clib_error_t *
     745         559 : pg_cli_init (vlib_main_t * vm)
     746             : {
     747         559 :   return 0;
     748             : }
     749             : 
     750       72799 : VLIB_INIT_FUNCTION (pg_cli_init);
     751             : 
     752             : /*
     753             :  * fd.io coding-style-patch-verification: ON
     754             :  *
     755             :  * Local Variables:
     756             :  * eval: (c-set-style "gnu")
     757             :  * End:
     758             :  */

Generated by: LCOV version 1.14