Add configurable duration to pktgen.

Change-Id: Ica376018dd1c7c6b3b6a19ae1fa3e8528a164d1e
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index 1dcb29d..9a2bc00 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -256,6 +256,7 @@
 	u64 delay;		/* nano-seconds */
 
 	__u64 count;		/* Default No packets to send */
+	__u64 duration;		/* Duration to send in microseconds */
 	__u64 sofar;		/* How many pkts we've sent so far */
 	__u64 tx_bytes;		/* How many bytes we've transmitted */
 	__u64 errors;		/* Errors when trying to transmit, */
@@ -551,6 +552,9 @@
 		   pkt_dev->queue_map_min,
 		   pkt_dev->queue_map_max);
 
+	seq_printf(seq, "     duration: %llu\n",
+		   (unsigned long long)pkt_dev->duration);
+
 	if (pkt_dev->skb_priority)
 		seq_printf(seq, "     skb_priority: %u\n",
 			   pkt_dev->skb_priority);
@@ -1090,6 +1094,16 @@
 			(unsigned long long)pkt_dev->count);
 		return count;
 	}
+	if (!strcmp(name, "duration")) {
+		len = num_arg(&user_buffer[i], 10, &value);
+		if (len < 0)
+			return len;
+		i += len;
+		pkt_dev->duration = value;
+		sprintf(pg_result, "OK: duration=%llu",
+			(unsigned long long)pkt_dev->duration);
+		return count;
+	}
 	if (!strcmp(name, "src_mac_count")) {
 		len = num_arg(&user_buffer[i], 10, &value);
 		if (len < 0)
@@ -3382,8 +3396,10 @@
 unlock:
 	__netif_tx_unlock_bh(txq);
 
-	/* If pkt_dev->count is zero, then run forever */
-	if ((pkt_dev->count != 0) && (pkt_dev->sofar >= pkt_dev->count)) {
+	/* If pkt_dev->count and pkt_dev->duration are zero, then run forever */
+	u64 elapsed = ktime_us_delta(ktime_now(), pkt_dev->started_at);
+	if ((pkt_dev->count != 0) && (pkt_dev->sofar >= pkt_dev->count) ||
+	    (pkt_dev->duration != 0) && (elapsed >= pkt_dev->duration)) {
 		pktgen_wait_for_skb(pkt_dev);
 
 		/* Done with this */
@@ -3563,6 +3579,7 @@
 	pkt_dev->nfrags = 0;
 	pkt_dev->delay = pg_delay_d;
 	pkt_dev->count = pg_count_d;
+	pkt_dev->duration = 0;
 	pkt_dev->sofar = 0;
 	pkt_dev->udp_src_min = 9;	/* sink port */
 	pkt_dev->udp_src_max = 9;