misc: add "maxframe" and "rate" to packet-generator cli.

Allow for setting the maximum number of generated packets to be included
in the frame passed to next nodes. This is very important for testing
code which may be susceptible to multi-frame vs single-frame bugs (e.g.,
code that is doing re-ordering where packets may be buffered between
frames).

Update:
- remove redundant packet "rate" option.
- reduce n_max_frame to u32 as that's what pulled from the CLI.

Type: feature
Signed-off-by: Christian E. Hopps <chopps@chopps.org>
Change-Id: Ie362bbb110b2cf01d9f65c559bbe9101e17b7fdc
Signed-off-by: Christian Hopps <chopps@labn.net>
diff --git a/src/vnet/pg/cli.c b/src/vnet/pg/cli.c
index d7e9ca0..c43ff90 100644
--- a/src/vnet/pg/cli.c
+++ b/src/vnet/pg/cli.c
@@ -336,7 +336,7 @@
 {
   clib_error_t *error = 0;
   u8 *tmp = 0;
-  u32 hw_if_index;
+  u32 maxframe, hw_if_index;
   unformat_input_t sub_input = { 0 };
   int sub_input_given = 0;
   vnet_main_t *vnm = vnet_get_main ();
@@ -349,7 +349,9 @@
   s.max_packet_bytes = s.min_packet_bytes = 64;
   s.buffer_bytes = vlib_buffer_get_default_data_size (vm);
   s.if_id = 0;
+  s.n_max_frame = VLIB_FRAME_SIZE;
   pcap_file_name = 0;
+
   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
     {
       if (unformat (input, "name %v", &tmp))
@@ -374,7 +376,8 @@
       else if (unformat (input, "node %U",
 			 unformat_vlib_node, vm, &s.node_index))
 	;
-
+      else if (unformat (input, "maxframe %u", &maxframe))
+	s.n_max_frame = s.n_max_frame < maxframe ? s.n_max_frame : maxframe;
       else if (unformat (input, "worker %u", &s.worker_index))
 	;
 
@@ -485,7 +488,9 @@
   "interface STRING     interface for stream output \n"
   "node NODE-NAME       node for stream output\n"
   "data STRING          specifies packet data\n"
-  "pcap FILENAME        read packet data from pcap file\n",
+  "pcap FILENAME        read packet data from pcap file\n"
+  "rate PPS             rate to transfer packet data\n"
+  "maxframe NPKTS       maximum number of packets per frame\n",
 };
 /* *INDENT-ON* */
 
diff --git a/src/vnet/pg/input.c b/src/vnet/pg/input.c
index 39aea7c..c47dfe2 100644
--- a/src/vnet/pg/input.c
+++ b/src/vnet/pg/input.c
@@ -1762,8 +1762,8 @@
     n_packets = s->n_packets_limit - s->n_packets_generated;
 
   /* Generate up to one frame's worth of packets. */
-  if (n_packets > VLIB_FRAME_SIZE)
-    n_packets = VLIB_FRAME_SIZE;
+  if (n_packets > s->n_max_frame)
+    n_packets = s->n_max_frame;
 
   if (n_packets > 0)
     n_packets = pg_generate_packets (node, pg, s, n_packets);
diff --git a/src/vnet/pg/pg.h b/src/vnet/pg/pg.h
index aef7a5b..c73634f 100644
--- a/src/vnet/pg/pg.h
+++ b/src/vnet/pg/pg.h
@@ -155,6 +155,9 @@
      Zero means no packet limit. */
   u64 n_packets_limit;
 
+  /* Only generate up to n_max_frame per frame. */
+  u32 n_max_frame;
+
   /* Rate for this stream in packets/second.
      Zero means unlimited rate. */
   f64 rate_packets_per_second;