* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
+#include <sys/stat.h>
+
#include <vnet/vnet.h>
#include <vnet/pg/pg.h>
.short_help = "Packet generator commands",
};
+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. */
+ 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);
+ }
+}
+
+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)
{
pg_main_t * pg = &pg_main;
- pg_stream_t * s;
int is_enable = cmd->function_arg != 0;
u32 stream_index = ~0;
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;
}
s->buffer_bytes = pm.max_packet_bytes;
/* For PCAP buffers we never re-use buffers. */
s->flags |= PG_STREAM_FLAGS_DISABLE_BUFFER_RECYCLE;
+
+ if (s->n_packets_limit == 0)
+ s->n_packets_limit = vec_len (pm.packets_read);
+
return error;
#endif /* CLIB_UNIX */
}
s.node_index = ~0;
s.max_packet_bytes = s.min_packet_bytes = 64;
s.buffer_bytes = VLIB_BUFFER_DEFAULT_FREE_LIST_BYTES;
+ s.if_id = 0;
pcap_file_name = 0;
while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
{
s.sw_if_index[VLIB_TX] = hi->sw_if_index;
}
+ else if (unformat (input, "source pg%u",&s.if_id))
+ ;
+
else if (unformat (input, "node %U",
unformat_vlib_node, vm, &s.node_index))
;
if (s.node_index == ~0)
{
- error = clib_error_create ("output interface or node not given");
- goto done;
+ if (pcap_file_name != 0)
+ {
+ vlib_node_t * n = vlib_get_node_by_name(vm, (u8 *) "ethernet-input");
+ s.node_index = n->index;
+ }
+ else
+ {
+ error = clib_error_create ("output interface or node not given");
+ goto done;
+ }
}
{
"name STRING sets stream name\n"
"interface STRING interface for stream output \n"
"node NODE-NAME node for stream output\n"
- "data STRING specifies packet data\n",
+ "data STRING specifies packet data\n"
+ "pcap FILENAME read packet data from pcap file\n",
};
static clib_error_t *
.function = change_stream_parameters,
};
+static clib_error_t *
+pg_capture_cmd_fn (vlib_main_t * vm,
+ unformat_input_t * input,
+ vlib_cli_command_t * cmd)
+{
+ 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))
+ 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))
+ {
+ hi = vnet_get_hw_interface (vnm, hw_if_index);
+ }
+
+ else if (unformat (line_input, "pcap %s", &pcap_file_name))
+ ;
+ else if (unformat (line_input, "count %u", &count))
+ ;
+ else if (unformat (line_input, "disable"))
+ is_disable = 1;
+
+ else
+ {
+ error = clib_error_create ("unknown input `%U'",
+ format_unformat_error, input);
+ return error;
+ }
+ }
+
+ if (!hi)
+ return clib_error_return (0, "Please specify interface name");
+
+ if (hi->dev_class_index != pg_dev_class.index)
+ return clib_error_return (0, "Please specify packet-generator interface");
+
+ if (!pcap_file_name && is_disable == 0)
+ return clib_error_return (0, "Please specify pcap file name");
+
+ unformat_free (line_input);
+
+ pg_capture_args_t _a, *a=&_a;
+
+ 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;
+
+ error = pg_capture (a);
+ return error;
+}
+
+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,
+};
+
+static clib_error_t *
+create_pg_if_cmd_fn (vlib_main_t * vm,
+ unformat_input_t * input,
+ vlib_cli_command_t * cmd)
+{
+ 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))
+ return 0;
+
+ while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (line_input, "interface pg%u", &if_id))
+ ;
+
+ else
+ return clib_error_create ("unknown input `%U'",
+ format_unformat_error, input);
+ }
+
+ unformat_free (line_input);
+
+ pg_interface_add_or_get (pg, if_id);
+ return 0;
+}
+
+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,
+};
+
/* Dummy init function so that we can be linked in. */
static clib_error_t * pg_cli_init (vlib_main_t * vm)
{ return 0; }