[netsniff-ng] [PATCH v2] trafgen: Allow to generate packets to output pcap file

2017-06-07 Thread Vadim Kochan
Add trafgen_dev.c module which provides generic way of
reading and writing packets to/from networking device or a pcap file.

Also allow to handle output pcap file via '-o, --out, --dev' option.

It might be useful in future for testing some link protocols which is
not easy to capture (e.g. wlan packets) w/o having some special setup.

Signed-off-by: Vadim Kochan 
---
v2:
1) Fixed "Failed ..." -> "Failed to ..." error messages
2) Fixed indentation in dev_io struct at pcap_magic field
3) Removed not needed dev_net_close function
4) Removed spaces in dev_io_ops functions fields

 trafgen.8|   5 +-
 trafgen.c| 102 +-
 trafgen/Makefile |   1 +
 trafgen_dev.c| 258 +++
 trafgen_dev.h|  49 +++
 trafgen_l2.c |   4 +
 trafgen_l3.c |   8 +-
 trafgen_proto.c  |  50 ++-
 trafgen_proto.h  |   6 +-
 9 files changed, 391 insertions(+), 92 deletions(-)
 create mode 100644 trafgen_dev.c
 create mode 100644 trafgen_dev.h

diff --git a/trafgen.8 b/trafgen.8
index fd9788a..50deacf 100644
--- a/trafgen.8
+++ b/trafgen.8
@@ -74,8 +74,9 @@ It is also possible to specify PCAP file with .pcap extension 
via -i,--in option
 by default packets will be sent at rate considering timestamp from PCAP file 
which
 might be reset via -b/-t options.
 .PP
-.SS -o , -d , --out , --dev 
-Defines the outgoing networking device such as eth0, wlan0 and others.
+.SS -o , -d , --out , --dev 
+Defines the outgoing networking device such as eth0, wlan0 and others or
+a pcap file.
 .PP
 .SS -p, --cpp
 Pass the packet configuration to the C preprocessor before reading it into
diff --git a/trafgen.c b/trafgen.c
index b25760f..ecc7d02 100644
--- a/trafgen.c
+++ b/trafgen.c
@@ -57,6 +57,7 @@
 #include "csum.h"
 #include "trafgen_proto.h"
 #include "pcap_io.h"
+#include "trafgen_dev.h"
 
 enum shaper_type {
SHAPER_NONE,
@@ -79,6 +80,8 @@ struct shaper {
 struct ctx {
bool rand, rfraw, jumbo_support, verbose, smoke_test, enforce, 
qdisc_path;
size_t reserve_size;
+   struct dev_io *dev_out;
+   struct dev_io *dev_in;
unsigned long num;
unsigned int cpus;
uid_t uid; gid_t gid;
@@ -145,7 +148,6 @@ static const char *copyright = "Please report bugs to 
device),
-   };
 
if (ctx->num > 0)
num = ctx->num;
@@ -688,8 +685,7 @@ static void xmit_slowpath_or_die(struct ctx *ctx, unsigned 
int cpu, unsigned lon
while (likely(sigint == 0 && num > 0 && plen > 0)) {
packet_apply_dyn_elements(i);
 retry:
-   ret = sendto(sock, packets[i].payload, packets[i].len, 0,
-(struct sockaddr *) &saddr, sizeof(saddr));
+   ret = dev_io_write(ctx->dev_out, packets[i].payload, 
packets[i].len);
if (unlikely(ret < 0)) {
if (errno == ENOBUFS) {
sched_yield();
@@ -745,15 +741,16 @@ retry:
 
 static void xmit_fastpath_or_die(struct ctx *ctx, unsigned int cpu, unsigned 
long orig_num)
 {
-   int ifindex = device_ifindex(ctx->device);
+   int ifindex = dev_io_ifindex_get(ctx->dev_out);
uint8_t *out = NULL;
unsigned int it = 0;
unsigned long num = 1, i = 0;
-   size_t size = ring_size(ctx->device, ctx->reserve_size);
+   size_t size = ring_size(dev_io_name_get(ctx->dev_out), 
ctx->reserve_size);
struct ring tx_ring;
struct frame_map *hdr;
struct timeval start, end, diff;
unsigned long long tx_bytes = 0, tx_packets = 0;
+   int sock = dev_io_fd_get(ctx->dev_out);
 
set_sock_prio(sock, 512);
 
@@ -938,69 +935,37 @@ static void xmit_packet_precheck(struct ctx *ctx, 
unsigned int cpu)
}
 }
 
-static void pcap_load_packets(const char *path)
+static void pcap_load_packets(struct dev_io *dev)
 {
-   const struct pcap_file_ops *pcap_io = pcap_ops[PCAP_OPS_SG];
-   uint32_t link_type, magic;
-   pcap_pkthdr_t phdr;
+   struct timespec tstamp;
size_t buf_len;
uint8_t *buf;
-   int ret;
-   int fd;
-
-   fd = open(path, O_RDONLY | O_LARGEFILE | O_NOATIME);
-   if (fd < 0 && errno == EPERM)
-   fd = open_or_die(path, O_RDONLY | O_LARGEFILE);
-   if (fd < 0)
-   panic("Cannot open file %s! %s.\n", path, strerror(errno));
-
-   if (pcap_io->init_once_pcap)
-   pcap_io->init_once_pcap(false);
-
-   ret = pcap_io->pull_fhdr_pcap(fd, &magic, &link_type);
-   if (ret)
-   panic("Error reading pcap header!\n");
-
-   if (pcap_io->prepare_access_pcap) {
-   ret = pcap_io->prepare_access_pcap(fd, PCAP_MODE_RD, false);
-   if (ret)
-   panic("Error prepare reading pcap!\n");
-   }
+   int pkt_len;
 
buf_len = round_up(1024 * 1024, RUNTIME_PAGE_SIZE);
buf = xmalloc_aligned(buf_len,

[netsniff-ng] Re: [PATCH] trafgen: Allow to generate packets to output pcap file

2017-06-07 Thread Tobias Klauser
On 2017-06-06 at 22:30:36 +0200, Vadim Kochan  wrote:
> Add trafgen_dev.c module which provides generic way of
> reading and writing packets to/from networking device or a pcap file.
> 
> Also allow to handle output pcap file via '-o, --out, --dev' option.
> 
> It might be useful in future for testing some link protocols which is
> not easy to capture (e.g. wlan packets) w/o having some special setup.

Looks good in general, a few minor nits below.

> Signed-off-by: Vadim Kochan 
> ---
>  trafgen.8|   5 +-
>  trafgen.c| 102 +
>  trafgen/Makefile |   1 +
>  trafgen_dev.c| 263 
> +++
>  trafgen_dev.h|  49 +++
>  trafgen_l2.c |   4 +
>  trafgen_l3.c |   8 +-
>  trafgen_proto.c  |  50 ++-
>  trafgen_proto.h  |   6 +-
>  9 files changed, 396 insertions(+), 92 deletions(-)
>  create mode 100644 trafgen_dev.c
>  create mode 100644 trafgen_dev.h
> 
> diff --git a/trafgen.8 b/trafgen.8
> index fd9788a..50deacf 100644
> --- a/trafgen.8
> +++ b/trafgen.8
> @@ -74,8 +74,9 @@ It is also possible to specify PCAP file with .pcap 
> extension via -i,--in option
>  by default packets will be sent at rate considering timestamp from PCAP file 
> which
>  might be reset via -b/-t options.
>  .PP
> -.SS -o , -d , --out , --dev 
> -Defines the outgoing networking device such as eth0, wlan0 and others.
> +.SS -o , -d , --out , --dev 
> +Defines the outgoing networking device such as eth0, wlan0 and others or
> +a pcap file.
>  .PP
>  .SS -p, --cpp
>  Pass the packet configuration to the C preprocessor before reading it into
> diff --git a/trafgen.c b/trafgen.c
> index b25760f..cc54f9e 100644
> --- a/trafgen.c
> +++ b/trafgen.c
> @@ -57,6 +57,7 @@
>  #include "csum.h"
>  #include "trafgen_proto.h"
>  #include "pcap_io.h"
> +#include "trafgen_dev.h"
>  
>  enum shaper_type {
>   SHAPER_NONE,
> @@ -79,6 +80,8 @@ struct shaper {
>  struct ctx {
>   bool rand, rfraw, jumbo_support, verbose, smoke_test, enforce, 
> qdisc_path;
>   size_t reserve_size;
> + struct dev_io *dev_out;
> + struct dev_io *dev_in;
>   unsigned long num;
>   unsigned int cpus;
>   uid_t uid; gid_t gid;
> @@ -145,7 +148,6 @@ static const char *copyright = "Please report bugs to 
>"This is free software: you are free to change and redistribute it.\n"
>   "There is NO WARRANTY, to the extent permitted by law.";
>  
> -static int sock;
>  static struct cpu_stats *stats;
>  static unsigned int seed;
>  
> @@ -664,11 +666,6 @@ static void xmit_slowpath_or_die(struct ctx *ctx, 
> unsigned int cpu, unsigned lon
>   unsigned long num = 1, i = 0;
>   struct timeval start, end, diff;
>   unsigned long long tx_bytes = 0, tx_packets = 0;
> - struct sockaddr_ll saddr = {
> - .sll_family = PF_PACKET,
> - .sll_halen = ETH_ALEN,
> - .sll_ifindex = device_ifindex(ctx->device),
> - };
>  
>   if (ctx->num > 0)
>   num = ctx->num;
> @@ -688,8 +685,7 @@ static void xmit_slowpath_or_die(struct ctx *ctx, 
> unsigned int cpu, unsigned lon
>   while (likely(sigint == 0 && num > 0 && plen > 0)) {
>   packet_apply_dyn_elements(i);
>  retry:
> - ret = sendto(sock, packets[i].payload, packets[i].len, 0,
> -  (struct sockaddr *) &saddr, sizeof(saddr));
> + ret = dev_io_write(ctx->dev_out, packets[i].payload, 
> packets[i].len);
>   if (unlikely(ret < 0)) {
>   if (errno == ENOBUFS) {
>   sched_yield();
> @@ -745,15 +741,16 @@ retry:
>  
>  static void xmit_fastpath_or_die(struct ctx *ctx, unsigned int cpu, unsigned 
> long orig_num)
>  {
> - int ifindex = device_ifindex(ctx->device);
> + int ifindex = dev_io_ifindex_get(ctx->dev_out);
>   uint8_t *out = NULL;
>   unsigned int it = 0;
>   unsigned long num = 1, i = 0;
> - size_t size = ring_size(ctx->device, ctx->reserve_size);
> + size_t size = ring_size(dev_io_name_get(ctx->dev_out), 
> ctx->reserve_size);
>   struct ring tx_ring;
>   struct frame_map *hdr;
>   struct timeval start, end, diff;
>   unsigned long long tx_bytes = 0, tx_packets = 0;
> + int sock = dev_io_fd_get(ctx->dev_out);
>  
>   set_sock_prio(sock, 512);
>  
> @@ -938,69 +935,37 @@ static void xmit_packet_precheck(struct ctx *ctx, 
> unsigned int cpu)
>   }
>  }
>  
> -static void pcap_load_packets(const char *path)
> +static void pcap_load_packets(struct dev_io *dev)
>  {
> - const struct pcap_file_ops *pcap_io = pcap_ops[PCAP_OPS_SG];
> - uint32_t link_type, magic;
> - pcap_pkthdr_t phdr;
> + struct timespec tstamp;
>   size_t buf_len;
>   uint8_t *buf;
> - int ret;
> - int fd;
> -
> - fd = open(path, O_RDONLY | O_LARGEFILE | O_NOATIME);
> - if (fd < 0 && errno == EPERM)
> - fd = open_or_die(path, O_RDONLY | O_