[netsniff-ng] [PATCH] build: configure: Add option to enable debug symbols

2016-08-12 Thread Vadim Kochan
Add '--enable-debug' option to enable debugging symbols,
the reason is to simplify it by ./configure it once and
do not execute 'make DEBUG=1 ...' each time for a long
debug session.

Signed-off-by: Vadim Kochan 
---
 Makefile  | 6 +-
 configure | 6 ++
 2 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/Makefile b/Makefile
index 83454e2..ad1c1fc 100644
--- a/Makefile
+++ b/Makefile
@@ -49,7 +49,11 @@ MAKEFLAGS += --jobs=$(shell grep "^processor" /proc/cpuinfo 
| wc -l)
 ifeq ("$(origin DEBUG)", "command line")
   DEBUG := 1
 else
-  DEBUG := 0
+  ifeq ($(CONFIG_DEBUG), 1)
+DEBUG := 1
+  else
+DEBUG := 0
+  endif
 endif
 
 # Compiler detection
diff --git a/configure b/configure
index 399733f..f7be751 100755
--- a/configure
+++ b/configure
@@ -22,6 +22,7 @@ HAVE_TPACKET3=0
 DISABLE_LIBNL=0
 DISABLE_GEOIP=0
 DISABLE_ZLIB=0
+ENABLE_DEBUG=0
 
 usage()
 {
@@ -33,6 +34,7 @@ usage()
echo "  --disable-libnl  Disable libnl support"
echo "  --disable-geoip  Disable geoip support"
echo "  --disable-zlib   Disable zlib support"
+   echo "  --enable-debug   Enable debug symbols"
echo ""
echo "Some influential environment variables:"
echo "  CC   C compiler command"
@@ -55,6 +57,9 @@ while [ $# -gt 0 ] ; do
--disable-zlib)
DISABLE_ZLIB=1
;;
+   --enable-debug)
+   ENABLE_DEBUG=1
+   ;;
*)
echo "[!] Unrecognized option: '$1'. Try './configure --help' 
for more information"
exit 1
@@ -789,6 +794,7 @@ else
echo "CONFIG_GEOIP=0" >> Config
 fi
 
+echo "CONFIG_DEBUG=$ENABLE_DEBUG" >> Config
 echo "CONFIG_TOOLS=$TOOLS" >> Config
 echo "CONFIG_OK=1" >> Config
 
-- 
2.9.2

-- 
You received this message because you are subscribed to the Google Groups 
"netsniff-ng" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to netsniff-ng+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[netsniff-ng] [PATCH v3 02/15] trafgen: proto: Increment proto field at runtime

2016-08-12 Thread Vadim Kochan
Implement incrementing of proto field at runtime with min & max
parameters, by default if the 'min' parameter is not specified
then original value is used. For fields which len is greater
than 4 - last 4 bytes are incremented as 4 byte value (this
trick is used for increment MAC/IPv6 addresses).

Signed-off-by: Vadim Kochan 
---
 trafgen_proto.c | 54 ++
 trafgen_proto.h | 11 +++
 2 files changed, 65 insertions(+)

diff --git a/trafgen_proto.c b/trafgen_proto.c
index 96fd6da..6c37b21 100644
--- a/trafgen_proto.c
+++ b/trafgen_proto.c
@@ -438,6 +438,37 @@ void proto_packet_finish(void)
}
 }
 
+static inline uint32_t field_inc(struct proto_field *field)
+{
+   uint32_t min = field->func.min;
+   uint32_t max = field->func.max;
+   uint32_t val = field->func.val;
+   uint32_t inc = field->func.inc;
+   uint32_t next;
+
+   next = (val + inc) % (max + 1);
+   field->func.val = max(next, min);
+
+   return val;
+}
+
+static void field_inc_func(struct proto_field *field)
+{
+   if (field->len == 1) {
+   proto_field_set_u8(field->hdr, field->id, field_inc(field));
+   } else if (field->len == 2) {
+   proto_field_set_be16(field->hdr, field->id, field_inc(field));
+   } else if (field->len == 4) {
+   proto_field_set_be32(field->hdr, field->id, field_inc(field));
+   } else if (field->len > 4) {
+   uint8_t *bytes = __proto_field_get_bytes(field);
+
+   bytes += field->len - 4;
+
+   *(uint32_t *)bytes = bswap_32(field_inc(field));
+   }
+}
+
 void proto_field_func_add(struct proto_hdr *hdr, uint32_t fid,
  struct proto_field_func *func)
 {
@@ -446,6 +477,29 @@ void proto_field_func_add(struct proto_hdr *hdr, uint32_t 
fid,
bug_on(!func);
 
field->func.update_field = func->update_field;
+   field->func.type = func->type;
+   field->func.max = func->max ?: UINT32_MAX - 1;
+   field->func.min = func->min;
+   field->func.inc = func->inc;
+
+   if (func->type & PROTO_FIELD_FUNC_INC) {
+   if (func->type & PROTO_FIELD_FUNC_MIN)
+   field->func.val = func->min;
+   else if (field->len == 1)
+   field->func.val = proto_field_get_u8(hdr, fid);
+   else if (field->len == 2)
+   field->func.val = proto_field_get_u16(hdr, fid);
+   else if (field->len == 4)
+   field->func.val = proto_field_get_u32(hdr, fid);
+   else if (field->len > 4) {
+   uint8_t *bytes = __proto_field_get_bytes(field);
+
+   bytes += field->len - 4;
+   field->func.val = bswap_32(*(uint32_t *)bytes);
+   }
+
+   field->func.update_field = field_inc_func;
+   }
 }
 
 void proto_field_dyn_apply(struct proto_field *field)
diff --git a/trafgen_proto.h b/trafgen_proto.h
index 0a53ead..911062a 100644
--- a/trafgen_proto.h
+++ b/trafgen_proto.h
@@ -51,7 +51,18 @@ struct proto_hdr {
size_t len;
 };
 
+enum proto_field_func_t {
+   PROTO_FIELD_FUNC_INC = 1 << 0,
+   PROTO_FIELD_FUNC_MIN = 1 << 1,
+};
+
 struct proto_field_func {
+   enum proto_field_func_t type;
+   uint32_t min;
+   uint32_t max;
+   int32_t inc;
+   uint32_t val;
+
void (* update_field)(struct proto_field *field);
 };
 
-- 
2.9.2

-- 
You received this message because you are subscribed to the Google Groups 
"netsniff-ng" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to netsniff-ng+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[netsniff-ng] [PATCH v3 14/15] trafgen: man: Add description for 'dinc' and 'drnd' field functions

2016-08-12 Thread Vadim Kochan
Add explanation about 'drnd' and 'dinc' functions which might
be used for proto field functions.

Signed-off-by: Vadim Kochan 
---
 trafgen.8 | 43 +++
 1 file changed, 43 insertions(+)

diff --git a/trafgen.8 b/trafgen.8
index c958794..d8ff36f 100644
--- a/trafgen.8
+++ b/trafgen.8
@@ -284,6 +284,49 @@ If a field is not specified, then a default value will be 
used (usually 0).
 Protocol fields might be set in any order. However, the offset of the fields in
 the resulting packet is according to the respective protocol.
 .sp
+Each field might be set with a function which generates field value at runtime 
by
+increment or randomize it. For L3/L4 protocols the checksum is calculated 
automatically
+if the field was changed dynamically by specified function.  The following 
field
+functions are supported:
+.in +4
+.sp
+.B dinc
+- increment field value at runtime. By default increment step is '1'.
+.B min
+and
+.B max
+parameters are used to increment field only in the specified range, by default 
original
+field value is used. If the field length is greater than 4 then last 4 bytes 
are
+incremented only (useful for MAC and IPv6 addresses):
+.in +4
+.sp
+ = dinc() | dinc(min, max) | dinc(min, max, step)
+.in -4
+.sp
+.B drnd
+- randomize field value at runtime.
+.B min
+and
+.B max
+parameters are used to randomize field only in the specified range:
+.in +4
+.sp
+ = drnd() | drnd(min, max)
+.in -4
+.sp
+Example of using dynamic functions:
+.sp
+{
+.in +2
+eth(saddr=aa:bb:cc:dd:ee:ff, saddr=dinc()),
+ipv4(saddr=dinc()),
+udp(sport=dinc(1, 13, 2), dport=drnd(80, 100))
+.in -2
+}
+
+.in -4
+
+.sp
 All required lower layer headers will be filled automatically if they were not
 specified by the user. The headers will be filled in the order they were
 specified. Each header will be filled with some mimimum required set of fields.
-- 
2.9.2

-- 
You received this message because you are subscribed to the Google Groups 
"netsniff-ng" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to netsniff-ng+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[netsniff-ng] [PATCH v3 04/15] trafgen: ipv4: Update csum at runtime if needed

2016-08-12 Thread Vadim Kochan
Handle 'field_changed' callback to check if IPv4 csum is needed
to be recalculated, if so - update it on 'packet_update' event.

Added 'is_csum_valid' to proto_hdr struct to check if csum needs to
be updated.

Signed-off-by: Vadim Kochan 
---
 trafgen_l3.c| 33 +++--
 trafgen_proto.h |  1 +
 2 files changed, 28 insertions(+), 6 deletions(-)

diff --git a/trafgen_l3.c b/trafgen_l3.c
index 2eabef1..9bb0de9 100644
--- a/trafgen_l3.c
+++ b/trafgen_l3.c
@@ -43,6 +43,30 @@ static void ipv4_header_init(struct proto_hdr *hdr)
proto_field_set_default_dev_ipv4(hdr, IP4_SADDR);
 }
 
+static void ipv4_field_changed(struct proto_field *field)
+{
+   field->hdr->is_csum_valid = false;
+}
+
+static void ipv4_csum_update(struct proto_hdr *hdr)
+{
+   struct packet *pkt;
+   uint16_t csum;
+
+   if (hdr->is_csum_valid)
+   return;
+   if (proto_field_is_set(hdr, IP4_CSUM))
+   return;
+
+   pkt = packet_get(hdr->pkt_id);
+
+   proto_field_set_default_u16(hdr, IP4_CSUM, 0);
+   csum = htons(calc_csum(&pkt->payload[hdr->pkt_offset], hdr->len));
+   proto_field_set_default_u16(hdr, IP4_CSUM, bswap_16(csum));
+
+   hdr->is_csum_valid = true;
+}
+
 static void ipv4_packet_finish(struct proto_hdr *hdr)
 {
struct packet *pkt = current_packet();
@@ -51,12 +75,7 @@ static void ipv4_packet_finish(struct proto_hdr *hdr)
total_len = pkt->len - hdr->pkt_offset;
proto_field_set_default_be16(hdr, IP4_LEN, total_len);
 
-   if (!proto_field_is_set(hdr, IP4_CSUM)) {
-   uint16_t csum;
-
-   csum = htons(calc_csum(&pkt->payload[hdr->pkt_offset], 
hdr->len));
-   proto_field_set_u16(hdr, IP4_CSUM, bswap_16(csum));
-   }
+   ipv4_csum_update(hdr);
 }
 
 static void ipv4_set_next_proto(struct proto_hdr *hdr, enum proto_id pid)
@@ -90,6 +109,8 @@ static const struct proto_ops ipv4_proto_ops = {
.id = PROTO_IP4,
.layer  = PROTO_L3,
.header_init= ipv4_header_init,
+   .packet_update  = ipv4_csum_update,
+   .field_changed  = ipv4_field_changed,
.packet_finish  = ipv4_packet_finish,
.set_next_proto = ipv4_set_next_proto,
 };
diff --git a/trafgen_proto.h b/trafgen_proto.h
index 389c714..ab294df 100644
--- a/trafgen_proto.h
+++ b/trafgen_proto.h
@@ -48,6 +48,7 @@ struct proto_hdr {
uint32_t pkt_id;
struct proto_field *fields;
size_t fields_count;
+   bool is_csum_valid;
size_t len;
 };
 
-- 
2.9.2

-- 
You received this message because you are subscribed to the Google Groups 
"netsniff-ng" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to netsniff-ng+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[netsniff-ng] [PATCH v3 13/15] trafgen: parser: Add 'drnd()' function for proto fields

2016-08-12 Thread Vadim Kochan
Add syntax for specify dynamic random function for proto field:

drnd() | drnd(min, max)

EXAMPLE:

{ udp(sport=drnd()) }
{ udp(sport=drnd(1000, 2000)) }

Signed-off-by: Vadim Kochan 
---
 trafgen_parser.y | 9 +
 1 file changed, 9 insertions(+)

diff --git a/trafgen_parser.y b/trafgen_parser.y
index 9b313d1..7e41bff 100644
--- a/trafgen_parser.y
+++ b/trafgen_parser.y
@@ -76,6 +76,7 @@ enum field_expr_type_t {
FIELD_EXPR_IP4_ADDR,
FIELD_EXPR_IP6_ADDR,
FIELD_EXPR_INC,
+   FIELD_EXPR_RND,
 };
 
 struct proto_field_expr {
@@ -429,6 +430,7 @@ static void proto_field_expr_eval(void)
break;
 
case FIELD_EXPR_INC:
+   case FIELD_EXPR_RND:
if (field_expr.val.func.min
&& field_expr.val.func.min >= field_expr.val.func.max)
panic("dinc(): min(%u) can't be >= max(%u)\n",
@@ -738,6 +740,13 @@ field_expr
  field_expr.val.func.min = $3;
  field_expr.val.func.max = $5;
  field_expr.val.func.inc = $7; }
+   | K_DRND '(' ')' { field_expr.type = FIELD_EXPR_RND;
+ field_expr.val.func.type = PROTO_FIELD_FUNC_RND; }
+   | K_DRND '(' number delimiter number ')'
+   { field_expr.type = FIELD_EXPR_RND;
+ field_expr.val.func.type = PROTO_FIELD_FUNC_RND;
+ field_expr.val.func.min = $3;
+ field_expr.val.func.max = $5; }
;
 
 eth_proto
-- 
2.9.2

-- 
You received this message because you are subscribed to the Google Groups 
"netsniff-ng" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to netsniff-ng+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[netsniff-ng] [PATCH v3 06/15] trafgen: icmpv6: Update csum at runtime if needed

2016-08-12 Thread Vadim Kochan
Use same function to calculate csum for packet_update
and for packet_finish events.

Allow update csum if one of the ICMPv6 fields was changed.

Signed-off-by: Vadim Kochan 
---
 trafgen_l4.c | 32 +++-
 1 file changed, 19 insertions(+), 13 deletions(-)

diff --git a/trafgen_l4.c b/trafgen_l4.c
index 89bb252..7ec017e 100644
--- a/trafgen_l4.c
+++ b/trafgen_l4.c
@@ -202,39 +202,45 @@ static void icmpv6_header_init(struct proto_hdr *hdr)
proto_header_fields_add(hdr, icmpv6_fields, array_size(icmpv6_fields));
 }
 
-static void icmpv6_packet_finish(struct proto_hdr *hdr)
+static void icmpv6_csum_update(struct proto_hdr *hdr)
 {
struct proto_hdr *lower = proto_lower_header(hdr);
-   struct packet *pkt = current_packet();
+   struct packet *pkt = packet_get(hdr->pkt_id);
uint16_t total_len;
uint16_t csum;
 
-   if (proto_field_is_set(hdr, ICMPV6_CSUM))
+   if (unlikely(!lower))
return;
-
-   if (!lower)
+   if (hdr->is_csum_valid)
+   return;
+   if (proto_field_is_set(hdr, ICMPV6_CSUM))
return;
 
total_len = pkt->len - hdr->pkt_offset;
 
-   switch (lower->ops->id) {
-   case PROTO_IP6:
+   proto_field_set_be16(hdr, ICMPV6_CSUM, 0);
+
+   if (likely(lower->ops->id == PROTO_IP6)) {
csum = p6_csum((void *) proto_header_ptr(lower), 
proto_header_ptr(hdr),
total_len, IPPROTO_ICMPV6);
-   break;
-   default:
-   csum = 0;
-   break;
+
+   proto_field_set_be16(hdr, ICMPV6_CSUM, bswap_16(csum));
+   hdr->is_csum_valid = true;
}
+}
 
-   proto_field_set_be16(hdr, ICMPV6_CSUM, bswap_16(csum));
+static void icmpv6_field_changed(struct proto_field *field)
+{
+   field->hdr->is_csum_valid = false;
 }
 
 static struct proto_ops icmpv6_proto_ops = {
.id = PROTO_ICMP6,
.layer  = PROTO_L4,
.header_init= icmpv6_header_init,
-   .packet_finish  = icmpv6_packet_finish,
+   .packet_finish  = icmpv6_csum_update,
+   .packet_update  = icmpv6_csum_update,
+   .field_changed  = icmpv6_field_changed,
 };
 
 void protos_l4_init(void)
-- 
2.9.2

-- 
You received this message because you are subscribed to the Google Groups 
"netsniff-ng" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to netsniff-ng+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[netsniff-ng] [PATCH v3 09/15] trafgen: udp: Update csum at runtime if needed

2016-08-12 Thread Vadim Kochan
Update UDP csum field at runtime if:

1) UDP field was changed.

2) IPv4/6 source/destination addresses were changed
   (which is a part of UDP pseudo header), this is
   handled by IPv4/6 protocols.

Signed-off-by: Vadim Kochan 
---
 trafgen_l3.c | 18 ++
 trafgen_l4.c | 37 +
 2 files changed, 47 insertions(+), 8 deletions(-)

diff --git a/trafgen_l3.c b/trafgen_l3.c
index 9bb0de9..91052a0 100644
--- a/trafgen_l3.c
+++ b/trafgen_l3.c
@@ -46,6 +46,13 @@ static void ipv4_header_init(struct proto_hdr *hdr)
 static void ipv4_field_changed(struct proto_field *field)
 {
field->hdr->is_csum_valid = false;
+
+   if (field->id == IP4_SADDR || field->id == IP4_DADDR) {
+   struct proto_hdr *upper = proto_upper_header(field->hdr);
+
+   if (upper && upper->ops->id == PROTO_UDP)
+   upper->is_csum_valid = false;
+   }
 }
 
 static void ipv4_csum_update(struct proto_hdr *hdr)
@@ -136,6 +143,16 @@ static void ipv6_header_init(struct proto_hdr *hdr)
proto_field_set_default_dev_ipv6(hdr, IP6_SADDR);
 }
 
+static void ipv6_field_changed(struct proto_field *field)
+{
+   if (field->id == IP6_SADDR || field->id == IP6_DADDR) {
+   struct proto_hdr *upper = proto_upper_header(field->hdr);
+
+   if (upper && upper->ops->id == PROTO_UDP)
+   upper->is_csum_valid = false;
+   }
+}
+
 #define IPV6_HDR_LEN 40
 
 static void ipv6_packet_finish(struct proto_hdr *hdr)
@@ -171,6 +188,7 @@ static const struct proto_ops ipv6_proto_ops = {
.id = PROTO_IP6,
.layer  = PROTO_L3,
.header_init= ipv6_header_init,
+   .field_changed  = ipv6_field_changed,
.packet_finish  = ipv6_packet_finish,
.set_next_proto = ipv6_set_next_proto,
 };
diff --git a/trafgen_l4.c b/trafgen_l4.c
index 7ec017e..ee8deb4 100644
--- a/trafgen_l4.c
+++ b/trafgen_l4.c
@@ -28,22 +28,29 @@ static void udp_header_init(struct proto_hdr *hdr)
proto_header_fields_add(hdr, udp_fields, array_size(udp_fields));
 }
 
-static void udp_packet_finish(struct proto_hdr *hdr)
+static void udp_field_changed(struct proto_field *field)
 {
-   struct proto_hdr *lower = proto_lower_header(hdr);
-   struct packet *pkt = current_packet();
+   field->hdr->is_csum_valid = false;
+}
+
+static void udp_csum_update(struct proto_hdr *hdr)
+{
+   struct proto_hdr *lower;
uint16_t total_len;
uint16_t csum;
 
-   total_len = pkt->len - hdr->pkt_offset;
-   proto_field_set_default_be16(hdr, UDP_LEN, total_len);
-
+   if (hdr->is_csum_valid)
+   return;
if (proto_field_is_set(hdr, UDP_CSUM))
return;
-
+   lower = proto_lower_header(hdr);
if (!lower)
return;
 
+   total_len = packet_get(hdr->pkt_id)->len - hdr->pkt_offset;
+
+   proto_field_set_default_be16(hdr, UDP_CSUM, 0);
+
switch (lower->ops->id) {
case PROTO_IP4:
csum = p4_csum((void *) proto_header_ptr(lower), 
proto_header_ptr(hdr),
@@ -58,14 +65,28 @@ static void udp_packet_finish(struct proto_hdr *hdr)
break;
}
 
-   proto_field_set_be16(hdr, UDP_CSUM, bswap_16(csum));
+   proto_field_set_default_be16(hdr, UDP_CSUM, bswap_16(csum));
+   hdr->is_csum_valid = true;
+}
+
+static void udp_packet_finish(struct proto_hdr *hdr)
+{
+   struct packet *pkt = current_packet();
+   uint16_t total_len;
+
+   total_len = pkt->len - hdr->pkt_offset;
+   proto_field_set_default_be16(hdr, UDP_LEN, total_len);
+
+   udp_csum_update(hdr);
 }
 
 static const struct proto_ops udp_proto_ops = {
.id = PROTO_UDP,
.layer  = PROTO_L4,
.header_init= udp_header_init,
+   .packet_update  = udp_csum_update,
.packet_finish  = udp_packet_finish,
+   .field_changed  = udp_field_changed,
 };
 
 static struct proto_field tcp_fields[] = {
-- 
2.9.2

-- 
You received this message because you are subscribed to the Google Groups 
"netsniff-ng" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to netsniff-ng+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[netsniff-ng] [PATCH v3 00/15] trafgen: Support dinc & drnd for proto fields

2016-08-12 Thread Vadim Kochan
Implemented 'dinc' and 'drnd' functions to be used for proto fields,
and generate values at runtime. Parsing of proto field values
for unified to make extending of field functions more easier w/o
copy/paste similar rules for each proto field. Instead of that
the field_expr struct is used to keep specified field and value which
might be a func in the following form:

(=())

Fields which has dynamic functions are stored in packet_dyn structure and
generated after each packet run. After fields are updated the L3/L4 headers
updates its csum if it is needed.

Changed field lookup logic to make field set/get operations a little bit faster 
by
using field id as index in the array, as usually fields are defined regarding
its index.

Example:

{ eth(sa=11:22:33:44:55:66, sa=dinc()), udp(sp=drnd(), dp=drnd()) }

v2:
1) Removed cast to (struct proto_field **) in proto_field_func_setup(...)
   when add dynamic field to packet_dyn.

2) Fixed order or parameters of dinc(min, max, step) to look like low level
   dinc function.

3) Replace ~0 by UINT32_MAX.

4) Calculate new random value in field_rnd_func(...) in 'for' body instead 
of increment
   statement.

5) Assign 'val' variable on declaration in field_inc_func(...).

6) Simplify & fix value incrementing between specified interval in 
field_inc(...).

7) Use local 'max, val, min, inc' variables instead of pointers in 
field_inc(...).

8) Add separate commit to add new proto_upper_header(...) function.

9) Add separate commit to use index for get lower/upper header

10) Add new commit to simplify Jasper's UDP example with proto functions.

v3:
1) Add new commit to introduce logic for update proto fields at runtime.

2) Use size_t for fields_count in packet_dyn struct.

3) Get rid of "!!" in packet_dyn_has_fields(...) function.

4) Change "unsigned int" to uint32_t

5) Change signature of (* field_changed) callback in proto_ops struct to 
pass
   struct proto_field * only.

6) Check first on is_csum_valid in ipv4_csum_update(...) function.

7) Add missed is_csum_valid check in icmpv6_csum_update(...) function.

8) Fixed missed 'field_expr' rule for icmpv4 field

9) Rebased on "proto ops" changes

Vadim Kochan (15):
  trafgen: proto: Update field value at runtime
  trafgen: proto: Increment proto field at runtime
  trafgen: proto: Randomize proto field at runtime
  trafgen: ipv4: Update csum at runtime if needed
  trafgen: icmpv4: Update csum at runtime if needed
  trafgen: icmpv6: Update csum at runtime if needed
  trafgen: proto: Improve to find lower header by index
  trafgen: proto: Introduce proto_upper_header() function
  trafgen: udp: Update csum at runtime if needed
  trafgen: tcp: Update csum at runtime if it needed
  trafgen: parser: Unify proto field value parsing
  trafgen: parser: Add support of 'dinc' function for proto fields
  trafgen: parser: Add 'drnd()' function for proto fields
  trafgen: man: Add description for 'dinc' and 'drnd' field functions
  trafgen: man: Simplify example of Jasper's UDP packet by proto
functions

 trafgen.8|  49 ++-
 trafgen.c|   9 ++
 trafgen_conf.h   |   7 +
 trafgen_l3.c |  51 ++-
 trafgen_l4.c | 107 ++
 trafgen_parser.y | 423 ---
 trafgen_proto.c  | 150 ++--
 trafgen_proto.h  |  32 +
 8 files changed, 631 insertions(+), 197 deletions(-)

-- 
2.9.2

-- 
You received this message because you are subscribed to the Google Groups 
"netsniff-ng" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to netsniff-ng+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[netsniff-ng] [PATCH v3 03/15] trafgen: proto: Randomize proto field at runtime

2016-08-12 Thread Vadim Kochan
Add dynamic proto field function which can generate
random value in specified range (default 0 - MAX_UINT32).

Signed-off-by: Vadim Kochan 
---
 trafgen_proto.c | 27 +++
 trafgen_proto.h |  1 +
 2 files changed, 28 insertions(+)

diff --git a/trafgen_proto.c b/trafgen_proto.c
index 6c37b21..8c316b1 100644
--- a/trafgen_proto.c
+++ b/trafgen_proto.c
@@ -469,6 +469,31 @@ static void field_inc_func(struct proto_field *field)
}
 }
 
+static inline uint32_t field_rand(struct proto_field *field)
+{
+   return field->func.min + (rand() % ((field->func.max - field->func.min) 
+ 1));
+}
+
+static void field_rnd_func(struct proto_field *field)
+{
+   if (field->len == 1) {
+   proto_field_set_u8(field->hdr, field->id,
+   (uint8_t) field_rand(field));
+   } else if (field->len == 2) {
+   proto_field_set_be16(field->hdr, field->id,
+   (uint16_t) field_rand(field));
+   } else if (field->len == 4) {
+   proto_field_set_be32(field->hdr, field->id,
+   (uint32_t) field_rand(field));
+   } else if (field->len > 4) {
+   uint8_t *bytes = __proto_field_get_bytes(field);
+   uint32_t i;
+
+   for (i = 0; i < field->len; i++)
+   bytes[i] = (uint8_t) field_rand(field);
+   }
+}
+
 void proto_field_func_add(struct proto_hdr *hdr, uint32_t fid,
  struct proto_field_func *func)
 {
@@ -499,6 +524,8 @@ void proto_field_func_add(struct proto_hdr *hdr, uint32_t 
fid,
}
 
field->func.update_field = field_inc_func;
+   } else if (func->type & PROTO_FIELD_FUNC_RND) {
+   field->func.update_field = field_rnd_func;
}
 }
 
diff --git a/trafgen_proto.h b/trafgen_proto.h
index 911062a..389c714 100644
--- a/trafgen_proto.h
+++ b/trafgen_proto.h
@@ -54,6 +54,7 @@ struct proto_hdr {
 enum proto_field_func_t {
PROTO_FIELD_FUNC_INC = 1 << 0,
PROTO_FIELD_FUNC_MIN = 1 << 1,
+   PROTO_FIELD_FUNC_RND = 1 << 2,
 };
 
 struct proto_field_func {
-- 
2.9.2

-- 
You received this message because you are subscribed to the Google Groups 
"netsniff-ng" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to netsniff-ng+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[netsniff-ng] [PATCH v3 05/15] trafgen: icmpv4: Update csum at runtime if needed

2016-08-12 Thread Vadim Kochan
Update csum if any of ICMPv4 field was chaned.

Signed-off-by: Vadim Kochan 
---
 trafgen_l4.c | 20 
 1 file changed, 16 insertions(+), 4 deletions(-)

diff --git a/trafgen_l4.c b/trafgen_l4.c
index 16346db..89bb252 100644
--- a/trafgen_l4.c
+++ b/trafgen_l4.c
@@ -156,25 +156,37 @@ static void icmpv4_header_init(struct proto_hdr *hdr)
proto_header_fields_add(hdr, icmpv4_fields, array_size(icmpv4_fields));
 }
 
-static void icmpv4_packet_finish(struct proto_hdr *hdr)
+static void icmpv4_csum_update(struct proto_hdr *hdr)
 {
struct packet *pkt;
uint16_t csum;
 
+   if (hdr->is_csum_valid)
+   return;
if (proto_field_is_set(hdr, ICMPV4_CSUM))
return;
 
-   pkt = current_packet();
+   pkt = packet_get(hdr->pkt_id);
 
+   proto_field_set_default_u16(hdr, ICMPV4_CSUM, 0);
csum = htons(calc_csum(proto_header_ptr(hdr), pkt->len - 
hdr->pkt_offset));
-   proto_field_set_u16(hdr, ICMPV4_CSUM, bswap_16(csum));
+   proto_field_set_default_u16(hdr, ICMPV4_CSUM, bswap_16(csum));
+
+   hdr->is_csum_valid = true;
+}
+
+static void icmpv4_field_changed(struct proto_field *field)
+{
+   field->hdr->is_csum_valid = false;
 }
 
 static const struct proto_ops icmpv4_proto_ops = {
.id = PROTO_ICMP4,
.layer  = PROTO_L4,
.header_init= icmpv4_header_init,
-   .packet_finish  = icmpv4_packet_finish,
+   .packet_update  = icmpv4_csum_update,
+   .packet_finish  = icmpv4_csum_update,
+   .field_changed  = icmpv4_field_changed,
 };
 
 static struct proto_field icmpv6_fields[] = {
-- 
2.9.2

-- 
You received this message because you are subscribed to the Google Groups 
"netsniff-ng" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to netsniff-ng+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[netsniff-ng] [PATCH v3 15/15] trafgen: man: Simplify example of Jasper's UDP packet by proto functions

2016-08-12 Thread Vadim Kochan
Removed unneeded fields which are calcuated by default:





Fixed  field by changing drnd(2) -> drnd() as proto field
 function does not support bytes length value but randomizes
specified field by its length.

Signed-off-by: Vadim Kochan 
---
 trafgen.8 | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/trafgen.8 b/trafgen.8
index d8ff36f..a4339ca 100644
--- a/trafgen.8
+++ b/trafgen.8
@@ -796,11 +796,11 @@ The above example rewritten using the header generation 
functions:
 .PP
{
  # --- ethernet header ---
- eth(da=00:1b:21:3c:9d:f8, da=90:e2:ba:0a:56:b4, proto=0x0800)
+ eth(da=00:1b:21:3c:9d:f8, da=90:e2:ba:0a:56:b4)
  # --- ip header ---
- ipv4(len=40, id=drnd(2), mf, ttl=64, proto=17, sa=192.168.51.1, 
da=192.168.51.2)
+ ipv4(id=drnd(), mf, ttl=64, sa=192.168.51.1, da=192.168.51.2)
  # --- udp header ---
- udp(sport=48054, dport=43514, len=20, csum=0)
+ udp(sport=48054, dport=43514, csum=0)
  # payload
  'A',  fill(0x41, 11),
}
-- 
2.9.2

-- 
You received this message because you are subscribed to the Google Groups 
"netsniff-ng" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to netsniff-ng+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[netsniff-ng] [PATCH v3 11/15] trafgen: parser: Unify proto field value parsing

2016-08-12 Thread Vadim Kochan
Changed parsing logic of field value expression to
be more generic. Such approach will allow to easy
extend field value expression to support dynamic field functions.

Signed-off-by: Vadim Kochan 
---
 trafgen_parser.y | 361 +--
 trafgen_proto.c  |   2 +-
 trafgen_proto.h  |   2 +
 3 files changed, 218 insertions(+), 147 deletions(-)

diff --git a/trafgen_parser.y b/trafgen_parser.y
index d643ad2..1e7bd5c 100644
--- a/trafgen_parser.y
+++ b/trafgen_parser.y
@@ -69,6 +69,27 @@ extern size_t dlen;
 
 static int our_cpu, min_cpu = -1, max_cpu = -1;
 
+enum field_expr_type_t {
+   FIELD_EXPR_UNKNOWN,
+   FIELD_EXPR_NUMB,
+   FIELD_EXPR_MAC,
+   FIELD_EXPR_IP4_ADDR,
+   FIELD_EXPR_IP6_ADDR,
+};
+
+struct proto_field_expr {
+   enum field_expr_type_t type;
+   struct proto_field *field;
+
+   union {
+   struct in_addr ip4_addr;
+   struct in6_addr ip6_addr;
+   long long int number;
+   uint8_t bytes[256];
+   } val;
+};
+
+static struct proto_field_expr field_expr;
 static struct proto_hdr *hdr;
 
 static inline int test_ignore(void)
@@ -351,6 +372,48 @@ static void proto_add(enum proto_id pid)
hdr = proto_header_push(pid);
 }
 
+static void proto_field_set(uint32_t fid)
+{
+   field_expr.field = proto_field_by_id(hdr, fid);
+}
+
+static void proto_field_expr_eval(void)
+{
+   struct proto_field *field = field_expr.field;
+
+   switch (field_expr.type) {
+   case FIELD_EXPR_NUMB:
+   if (field->len == 1)
+   proto_field_set_u8(hdr, field->id, 
field_expr.val.number);
+   else if (field->len == 2)
+   proto_field_set_be16(hdr, field->id, 
field_expr.val.number);
+   else if (field->len == 4)
+   proto_field_set_be32(hdr, field->id, 
field_expr.val.number);
+   else
+   bug();
+   break;
+
+   case FIELD_EXPR_MAC:
+   proto_field_set_bytes(hdr, field->id, field_expr.val.bytes);
+   break;
+
+   case FIELD_EXPR_IP4_ADDR:
+   proto_field_set_u32(hdr, field->id, 
field_expr.val.ip4_addr.s_addr);
+   break;
+
+   case FIELD_EXPR_IP6_ADDR:
+   proto_field_set_bytes(hdr, field->id,
+   (uint8_t *)&field_expr.val.ip6_addr.s6_addr);
+   break;
+
+   case FIELD_EXPR_UNKNOWN:
+   default:
+   bug();
+   }
+
+   memset(&field_expr, 0, sizeof(field_expr));
+}
+
 %}
 
 %union {
@@ -614,6 +677,17 @@ proto
| tcp_proto { }
;
 
+field_expr
+   : number { field_expr.type = FIELD_EXPR_NUMB;
+  field_expr.val.number = $1; }
+   | mac { field_expr.type = FIELD_EXPR_MAC;
+   memcpy(field_expr.val.bytes, $1, sizeof(field_expr.val.bytes)); 
}
+   | ip4_addr { field_expr.type = FIELD_EXPR_IP4_ADDR;
+field_expr.val.ip4_addr = $1; }
+   | ip6_addr { field_expr.type = FIELD_EXPR_IP6_ADDR;
+field_expr.val.ip6_addr = $1; }
+   ;
+
 eth_proto
: eth '(' eth_param_list ')' { }
;
@@ -624,8 +698,8 @@ eth
 
 eth_param_list
: { }
-   | eth_field { }
-   | eth_field delimiter eth_param_list { }
+   | eth_expr { }
+   | eth_expr delimiter eth_param_list { }
;
 
 eth_type
@@ -635,12 +709,13 @@ eth_type
;
 
 eth_field
-   : K_DADDR skip_white '=' skip_white mac
-   { proto_field_set_bytes(hdr, ETH_DST_ADDR, $5); }
-   | K_SADDR skip_white '=' skip_white mac
-   { proto_field_set_bytes(hdr, ETH_SRC_ADDR, $5); }
-   | eth_type skip_white '=' skip_white number
-   { proto_field_set_be16(hdr, ETH_TYPE, $5); }
+   : K_DADDR { proto_field_set(ETH_DST_ADDR); }
+   | K_SADDR { proto_field_set(ETH_SRC_ADDR); }
+   | eth_type { proto_field_set(ETH_TYPE); }
+
+eth_expr
+   : eth_field skip_white '=' skip_white field_expr
+   { proto_field_expr_eval(); }
;
 
 vlan_proto
@@ -653,8 +728,8 @@ vlan
 
 vlan_param_list
: { }
-   | vlan_field { }
-   | vlan_field delimiter vlan_param_list { }
+   | vlan_expr { }
+   | vlan_expr delimiter vlan_param_list { }
;
 
 vlan_type
@@ -663,20 +738,20 @@ vlan_type
;
 
 vlan_field
-   : vlan_type skip_white '=' skip_white number
-   { proto_field_set_be16(hdr, VLAN_TPID, $5); }
+   : vlan_type { proto_field_set(VLAN_TPID); }
+   | K_TCI { proto_field_set(VLAN_TCI); }
+   | K_PCP { proto_field_set(VLAN_PCP); }
+   | K_DEI { proto_field_set(VLAN_DEI); }
+   | K_ID { proto_field_set(VLAN_VID); }
+   ;
+
+vlan_expr
+   : vlan_field skip_white '=' skip_white field_expr
+   { proto_field_expr_eval(); }
| K_1Q
{ proto_field_set_be16(hdr, VLAN_TPID, ETH_P_8021

[netsniff-ng] [PATCH v3 12/15] trafgen: parser: Add support of 'dinc' function for proto fields

2016-08-12 Thread Vadim Kochan
Add 'dinc()' function in 'field_expr' rules to be used for dynamically
incrementing of any specified field:

SYNTAX := dinc() | dinc(step) | dinc(min, max) | dinc(min, max, step)

EXAMPLES:
{ udp(sport=dinc() }
{ udp(sport=dinc(1) }
{ udp(sport=dinc(100, 125, 5) }

Signed-off-by: Vadim Kochan 
---
 trafgen_parser.y | 53 +
 1 file changed, 53 insertions(+)

diff --git a/trafgen_parser.y b/trafgen_parser.y
index 1e7bd5c..9b313d1 100644
--- a/trafgen_parser.y
+++ b/trafgen_parser.y
@@ -75,6 +75,7 @@ enum field_expr_type_t {
FIELD_EXPR_MAC,
FIELD_EXPR_IP4_ADDR,
FIELD_EXPR_IP6_ADDR,
+   FIELD_EXPR_INC,
 };
 
 struct proto_field_expr {
@@ -86,6 +87,7 @@ struct proto_field_expr {
struct in6_addr ip6_addr;
long long int number;
uint8_t bytes[256];
+   struct proto_field_func func;
} val;
 };
 
@@ -126,6 +128,12 @@ static inline void __init_new_csum_slot(struct packet_dyn 
*slot)
slot->slen = 0;
 }
 
+static inline void __init_new_fields_slot(struct packet_dyn *slot)
+{
+   slot->fields = NULL;
+   slot->flen = 0;
+}
+
 static inline void __setup_new_counter(struct counter *c, uint8_t start,
   uint8_t stop, uint8_t stepping,
   int type)
@@ -168,6 +176,7 @@ static void realloc_packet(void)
__init_new_counter_slot(&packet_dyn[packetd_last]);
__init_new_randomizer_slot(&packet_dyn[packetd_last]);
__init_new_csum_slot(&packet_dyn[packetd_last]);
+   __init_new_fields_slot(&packet_dyn[packetd_last]);
 }
 
 struct packet *current_packet(void)
@@ -377,6 +386,19 @@ static void proto_field_set(uint32_t fid)
field_expr.field = proto_field_by_id(hdr, fid);
 }
 
+static void proto_field_func_setup(struct proto_field *field, struct 
proto_field_func *func)
+{
+   struct packet_dyn *pkt_dyn;
+
+   proto_field_func_add(field->hdr, field->id, func);
+
+   pkt_dyn = &packet_dyn[packetd_last];
+   pkt_dyn->flen++;
+   pkt_dyn->fields = xrealloc(pkt_dyn->fields, pkt_dyn->flen *
+  sizeof(struct proto_field *));
+   pkt_dyn->fields[pkt_dyn->flen - 1] = field;
+}
+
 static void proto_field_expr_eval(void)
 {
struct proto_field *field = field_expr.field;
@@ -406,6 +428,15 @@ static void proto_field_expr_eval(void)
(uint8_t *)&field_expr.val.ip6_addr.s6_addr);
break;
 
+   case FIELD_EXPR_INC:
+   if (field_expr.val.func.min
+   && field_expr.val.func.min >= field_expr.val.func.max)
+   panic("dinc(): min(%u) can't be >= max(%u)\n",
+   field_expr.val.func.min, 
field_expr.val.func.max);
+
+   proto_field_func_setup(field, &field_expr.val.func);
+   break;
+
case FIELD_EXPR_UNKNOWN:
default:
bug();
@@ -686,6 +717,27 @@ field_expr
 field_expr.val.ip4_addr = $1; }
| ip6_addr { field_expr.type = FIELD_EXPR_IP6_ADDR;
 field_expr.val.ip6_addr = $1; }
+   | K_DINC '(' ')' { field_expr.type = FIELD_EXPR_INC;
+  field_expr.val.func.type = PROTO_FIELD_FUNC_INC;
+  field_expr.val.func.inc = 1; }
+   | K_DINC '(' number ')'
+   { field_expr.type = FIELD_EXPR_INC;
+ field_expr.val.func.type = PROTO_FIELD_FUNC_INC;
+ field_expr.val.func.inc = $3; }
+   | K_DINC '(' number delimiter number ')'
+   { field_expr.type = FIELD_EXPR_INC;
+ field_expr.val.func.type  = PROTO_FIELD_FUNC_INC;
+ field_expr.val.func.type |= PROTO_FIELD_FUNC_MIN;
+ field_expr.val.func.min = $3;
+ field_expr.val.func.max = $5;
+ field_expr.val.func.inc = 1; }
+   | K_DINC '(' number delimiter number delimiter number ')'
+   { field_expr.type = FIELD_EXPR_INC;
+ field_expr.val.func.type  = PROTO_FIELD_FUNC_INC;
+ field_expr.val.func.type |= PROTO_FIELD_FUNC_MIN;
+ field_expr.val.func.min = $3;
+ field_expr.val.func.max = $5;
+ field_expr.val.func.inc = $7; }
;
 
 eth_proto
@@ -1096,6 +1148,7 @@ void cleanup_packets(void)
for (i = 0; i < dlen; ++i) {
free(packet_dyn[i].cnt);
free(packet_dyn[i].rnd);
+   free(packet_dyn[i].fields);
}
 
free(packet_dyn);
-- 
2.9.2

-- 
You received this message because you are subscribed to the Google Groups 
"netsniff-ng" group.
To unsubscribe from this group and stop receiving emails from it, send an ema

[netsniff-ng] [PATCH v3 01/15] trafgen: proto: Update field value at runtime

2016-08-12 Thread Vadim Kochan
Add basic infrastructure for update proto field value at runtime
by dynamic field function.

Extended 'struct packet_dyn' with proto fields which has
dynamically changing values at runtime.

Added 'field_changed' callback for proto header which
may be used for check if csum updating is needed. This callback
is called after field was changed at runtime.

Added 'packet_update' callback to let proto header know
when to apply final proto header changes at runtime (e.g. - csum update).

Signed-off-by: Vadim Kochan 
---
 trafgen.c   |  9 +
 trafgen_conf.h  |  7 +++
 trafgen_proto.c | 32 
 trafgen_proto.h | 15 +++
 4 files changed, 63 insertions(+)

diff --git a/trafgen.c b/trafgen.c
index b76b5d7..553dfa5 100644
--- a/trafgen.c
+++ b/trafgen.c
@@ -619,6 +619,15 @@ static inline void packet_apply_dyn_elements(int idx)
apply_randomizer(idx);
apply_csum16(idx);
}
+
+   if (packet_dyn_has_fields(&packet_dyn[idx])) {
+   uint32_t i;
+
+   for (i = 0; i < packet_dyn[idx].flen; i++)
+   proto_field_dyn_apply(packet_dyn[idx].fields[i]);
+
+   proto_packet_update(idx);
+   }
 }
 
 static void xmit_slowpath_or_die(struct ctx *ctx, unsigned int cpu, unsigned 
long orig_num)
diff --git a/trafgen_conf.h b/trafgen_conf.h
index 934f8fe..61da012 100644
--- a/trafgen_conf.h
+++ b/trafgen_conf.h
@@ -49,6 +49,8 @@ struct packet_dyn {
size_t rlen;
struct csum16 *csum;
size_t slen;
+   struct proto_field **fields;
+   size_t flen;
 };
 
 static inline bool packet_dyn_has_elems(struct packet_dyn *p)
@@ -61,6 +63,11 @@ static inline bool packet_dyn_has_only_csums(struct 
packet_dyn *p)
return (p->clen == 0 && p->rlen == 0 && p->slen);
 }
 
+static inline bool packet_dyn_has_fields(struct packet_dyn *p)
+{
+   return p->flen;
+}
+
 extern void compile_packets_str(char *str, bool verbose, unsigned int cpu);
 extern void compile_packets(char *file, bool verbose, unsigned int cpu,
bool invoke_cpp, char *const cpp_argv[]);
diff --git a/trafgen_proto.c b/trafgen_proto.c
index d976c14..96fd6da 100644
--- a/trafgen_proto.c
+++ b/trafgen_proto.c
@@ -409,6 +409,19 @@ void protos_init(const char *dev)
protos_l4_init();
 }
 
+void proto_packet_update(uint32_t idx)
+{
+   struct packet *pkt = packet_get(idx);
+   ssize_t i;
+
+   for (i = pkt->headers_count - 1; i >= 0; i--) {
+   struct proto_hdr *hdr = pkt->headers[i];
+
+   if (hdr->ops->packet_update)
+   hdr->ops->packet_update(hdr);
+   }
+}
+
 void proto_packet_finish(void)
 {
struct proto_hdr **headers = current_packet()->headers;
@@ -424,3 +437,22 @@ void proto_packet_finish(void)
ops->packet_finish(hdr);
}
 }
+
+void proto_field_func_add(struct proto_hdr *hdr, uint32_t fid,
+ struct proto_field_func *func)
+{
+   struct proto_field *field = proto_field_by_id(hdr, fid);
+
+   bug_on(!func);
+
+   field->func.update_field = func->update_field;
+}
+
+void proto_field_dyn_apply(struct proto_field *field)
+{
+   if (field->func.update_field)
+   field->func.update_field(field);
+
+   if (field->hdr->ops->field_changed)
+   field->hdr->ops->field_changed(field);
+}
diff --git a/trafgen_proto.h b/trafgen_proto.h
index 9716aa2..0a53ead 100644
--- a/trafgen_proto.h
+++ b/trafgen_proto.h
@@ -27,6 +27,7 @@ enum proto_layer {
PROTO_L4,
 };
 
+struct proto_field;
 struct proto_hdr;
 
 struct proto_ops {
@@ -35,7 +36,9 @@ struct proto_ops {
 
void (*header_init)(struct proto_hdr *hdr);
void (*header_finish)(struct proto_hdr *hdr);
+   void (*field_changed)(struct proto_field *field);
void (*packet_finish)(struct proto_hdr *hdr);
+   void (*packet_update)(struct proto_hdr *hdr);
void (*set_next_proto)(struct proto_hdr *hdr, enum proto_id pid);
 };
 
@@ -48,6 +51,10 @@ struct proto_hdr {
size_t len;
 };
 
+struct proto_field_func {
+   void (* update_field)(struct proto_field *field);
+};
+
 struct proto_field {
uint32_t id;
size_t len;
@@ -56,6 +63,7 @@ struct proto_field {
/* might be negative (e.g. VLAN TPID field) */
int16_t offset;
 
+   struct proto_field_func func;
bool is_set;
uint16_t pkt_offset;
struct proto_hdr *hdr;
@@ -67,6 +75,8 @@ extern void proto_ops_register(const struct proto_ops *ops);
 extern struct proto_hdr *proto_header_push(enum proto_id pid);
 extern void proto_header_finish(struct proto_hdr *hdr);
 extern void proto_packet_finish(void);
+extern void proto_packet_update(uint32_t idx);
+
 extern struct proto_hdr *proto_lower_default_add(struct proto_hdr *hdr,
 enum proto_id pid);
 
@@ -113,4 +123,9 @@ extern v

[netsniff-ng] [PATCH v3 08/15] trafgen: proto: Introduce proto_upper_header() function

2016-08-12 Thread Vadim Kochan
Added proto_upper_header() function to fetch upper proto header.

It will be used by IPv4/IPv6 proto header to notify UDP/TCP proto
headers to invalidate L4 csum when L3 pseudo header field was changed.

Signed-off-by: Vadim Kochan 
---
 trafgen_proto.c | 12 
 trafgen_proto.h |  1 +
 2 files changed, 13 insertions(+)

diff --git a/trafgen_proto.c b/trafgen_proto.c
index b0a198f..f4b2828 100644
--- a/trafgen_proto.c
+++ b/trafgen_proto.c
@@ -40,6 +40,18 @@ struct proto_hdr *proto_lower_header(struct proto_hdr *hdr)
return headers[hdr->index - 1];
 }
 
+struct proto_hdr *proto_upper_header(struct proto_hdr *hdr)
+{
+   struct packet *pkt = packet_get(hdr->pkt_id);
+   struct proto_hdr **headers = &pkt->headers[0];
+   size_t headers_count = pkt->headers_count;
+
+   if (hdr->index == headers_count - 1)
+   return NULL;
+
+   return headers[hdr->index + 1];
+}
+
 uint8_t *proto_header_ptr(struct proto_hdr *hdr)
 {
return &packet_get(hdr->pkt_id)->payload[hdr->pkt_offset];
diff --git a/trafgen_proto.h b/trafgen_proto.h
index f9f4e13..577a230 100644
--- a/trafgen_proto.h
+++ b/trafgen_proto.h
@@ -95,6 +95,7 @@ extern struct proto_hdr *proto_lower_default_add(struct 
proto_hdr *hdr,
 enum proto_id pid);
 
 extern struct proto_hdr *proto_lower_header(struct proto_hdr *hdr);
+extern struct proto_hdr *proto_upper_header(struct proto_hdr *hdr);
 extern uint8_t *proto_header_ptr(struct proto_hdr *hdr);
 
 extern void proto_header_fields_add(struct proto_hdr *hdr,
-- 
2.9.2

-- 
You received this message because you are subscribed to the Google Groups 
"netsniff-ng" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to netsniff-ng+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[netsniff-ng] [PATCH v3 10/15] trafgen: tcp: Update csum at runtime if it needed

2016-08-12 Thread Vadim Kochan
Update TCP checksum field if any TCP of fields was changed.
Use same checksum update function on 'packet_finish' and 'header update'.

Set 'is_csum_valid = false' if lower IPv4/IPv6 pseudo header was changed.

Signed-off-by: Vadim Kochan 
---
 trafgen_l3.c |  4 ++--
 trafgen_l4.c | 18 +++---
 2 files changed, 17 insertions(+), 5 deletions(-)

diff --git a/trafgen_l3.c b/trafgen_l3.c
index 91052a0..e6aa516 100644
--- a/trafgen_l3.c
+++ b/trafgen_l3.c
@@ -50,7 +50,7 @@ static void ipv4_field_changed(struct proto_field *field)
if (field->id == IP4_SADDR || field->id == IP4_DADDR) {
struct proto_hdr *upper = proto_upper_header(field->hdr);
 
-   if (upper && upper->ops->id == PROTO_UDP)
+   if (upper && (upper->ops->id == PROTO_UDP || upper->ops->id == 
PROTO_TCP))
upper->is_csum_valid = false;
}
 }
@@ -148,7 +148,7 @@ static void ipv6_field_changed(struct proto_field *field)
if (field->id == IP6_SADDR || field->id == IP6_DADDR) {
struct proto_hdr *upper = proto_upper_header(field->hdr);
 
-   if (upper && upper->ops->id == PROTO_UDP)
+   if (upper && (upper->ops->id == PROTO_UDP || upper->ops->id == 
PROTO_TCP))
upper->is_csum_valid = false;
}
 }
diff --git a/trafgen_l4.c b/trafgen_l4.c
index ee8deb4..b3b0775 100644
--- a/trafgen_l4.c
+++ b/trafgen_l4.c
@@ -118,13 +118,20 @@ static void tcp_header_init(struct proto_hdr *hdr)
proto_field_set_default_be16(hdr, TCP_DOFF, 5);
 }
 
-static void tcp_packet_finish(struct proto_hdr *hdr)
+static void tcp_field_changed(struct proto_field *field)
+{
+   field->hdr->is_csum_valid = false;
+}
+
+static void tcp_csum_update(struct proto_hdr *hdr)
 {
struct proto_hdr *lower = proto_lower_header(hdr);
struct packet *pkt = current_packet();
uint16_t total_len;
uint16_t csum;
 
+   if (hdr->is_csum_valid)
+   return;
if (proto_field_is_set(hdr, TCP_CSUM))
return;
 
@@ -133,6 +140,8 @@ static void tcp_packet_finish(struct proto_hdr *hdr)
 
total_len = pkt->len - hdr->pkt_offset;
 
+   proto_field_set_default_be16(hdr, TCP_CSUM, 0);
+
switch (lower->ops->id) {
case PROTO_IP4:
csum = p4_csum((void *) proto_header_ptr(lower), 
proto_header_ptr(hdr),
@@ -147,14 +156,17 @@ static void tcp_packet_finish(struct proto_hdr *hdr)
break;
}
 
-   proto_field_set_be16(hdr, TCP_CSUM, bswap_16(csum));
+   proto_field_set_default_be16(hdr, TCP_CSUM, bswap_16(csum));
+   hdr->is_csum_valid = true;
 }
 
 static const struct proto_ops tcp_proto_ops = {
.id = PROTO_TCP,
.layer  = PROTO_L4,
.header_init= tcp_header_init,
-   .packet_finish  = tcp_packet_finish,
+   .packet_update  = tcp_csum_update,
+   .packet_finish  = tcp_csum_update,
+   .field_changed  = tcp_field_changed,
 };
 
 static struct proto_field icmpv4_fields[] = {
-- 
2.9.2

-- 
You received this message because you are subscribed to the Google Groups 
"netsniff-ng" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to netsniff-ng+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[netsniff-ng] [PATCH v3 07/15] trafgen: proto: Improve to find lower header by index

2016-08-12 Thread Vadim Kochan
Extended struct proto_hdr with 'index' field which is used for
faster lookup of lower header w/o doing a loop.

Signed-off-by: Vadim Kochan 
---
 trafgen_proto.c | 25 +++--
 trafgen_proto.h |  1 +
 2 files changed, 12 insertions(+), 14 deletions(-)

diff --git a/trafgen_proto.c b/trafgen_proto.c
index 8c316b1..b0a198f 100644
--- a/trafgen_proto.c
+++ b/trafgen_proto.c
@@ -31,20 +31,13 @@ static const struct proto_ops *registered_ops[__PROTO_MAX];
 
 struct proto_hdr *proto_lower_header(struct proto_hdr *hdr)
 {
-   struct proto_hdr **headers = current_packet()->headers;
-   size_t headers_count = current_packet()->headers_count;
-   struct proto_hdr *lower = NULL;
-   size_t i;
+   struct packet *pkt = packet_get(hdr->pkt_id);
+   struct proto_hdr **headers = &pkt->headers[0];
 
-   if (headers_count == 0)
+   if (hdr->index == 0)
return NULL;
 
-   for (i = 1, lower = headers[0]; i < headers_count; i++) {
-   if (headers[i] == hdr)
-   return headers[i - 1];
-   }
-
-   return lower;
+   return headers[hdr->index - 1];
 }
 
 uint8_t *proto_header_ptr(struct proto_hdr *hdr)
@@ -121,11 +114,12 @@ bool proto_field_is_set(struct proto_hdr *hdr, uint32_t 
fid)
 
 struct proto_hdr *proto_header_push(enum proto_id pid)
 {
-   struct proto_hdr **headers = current_packet()->headers;
+   struct packet *pkt = current_packet();
+   struct proto_hdr **headers = &pkt->headers[0];
const struct proto_ops *ops = proto_ops_by_id(pid);
struct proto_hdr *hdr;
 
-   bug_on(current_packet()->headers_count >= PROTO_MAX_LAYERS);
+   bug_on(pkt->headers_count >= PROTO_MAX_LAYERS);
 
hdr = xzmalloc(sizeof(*hdr));
hdr->ops = ops;
@@ -134,8 +128,11 @@ struct proto_hdr *proto_header_push(enum proto_id pid)
if (ops && ops->header_init)
ops->header_init(hdr);
 
-   headers[current_packet()->headers_count++] = hdr;
+   /* This is very important to have it after header_init as
+* pkt->headers_count might be changed by adding default lower headers 
*/
+   hdr->index = pkt->headers_count;
 
+   headers[pkt->headers_count++] = hdr;
return hdr;
 }
 
diff --git a/trafgen_proto.h b/trafgen_proto.h
index ab294df..f9f4e13 100644
--- a/trafgen_proto.h
+++ b/trafgen_proto.h
@@ -46,6 +46,7 @@ struct proto_hdr {
const struct proto_ops *ops;
uint16_t pkt_offset;
uint32_t pkt_id;
+   uint32_t index;
struct proto_field *fields;
size_t fields_count;
bool is_csum_valid;
-- 
2.9.2

-- 
You received this message because you are subscribed to the Google Groups 
"netsniff-ng" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to netsniff-ng+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[netsniff-ng] [PATCH] tstamping: Move code to the sock.c

2016-08-12 Thread Vadim Kochan
Move hw timestamp enable/disable code to sock.c as
it is a socket related functionality, and it makes
have less files in source tree.

Move tstamping related includes under HAVE_TSTAMPING config
to compile them only if hw timestamping is suported.

Signed-off-by: Vadim Kochan 
---
 netsniff-ng.c|  1 -
 netsniff-ng/Makefile |  3 ---
 sock.c   | 39 +++
 sock.h   |  1 +
 tstamping.c  | 38 --
 tstamping.h  | 15 ---
 6 files changed, 40 insertions(+), 57 deletions(-)
 delete mode 100644 tstamping.c
 delete mode 100644 tstamping.h

diff --git a/netsniff-ng.c b/netsniff-ng.c
index ce37e10..ec060f8 100644
--- a/netsniff-ng.c
+++ b/netsniff-ng.c
@@ -44,7 +44,6 @@
 #include "lockme.h"
 #include "tprintf.h"
 #include "timer.h"
-#include "tstamping.h"
 #include "dissector.h"
 #include "xmalloc.h"
 
diff --git a/netsniff-ng/Makefile b/netsniff-ng/Makefile
index d1d8a85..c6a531f 100644
--- a/netsniff-ng/Makefile
+++ b/netsniff-ng/Makefile
@@ -74,9 +74,6 @@ endif
 ifeq ($(CONFIG_GEOIP), 1)
 netsniff-ng-objs +=geoip.o
 endif
-ifeq ($(CONFIG_HWTSTAMP), 1)
-netsniff-ng-objs +=tstamping.o
-endif
 ifeq ($(CONFIG_LIBNL), 1)
 netsniff-ng-objs +=mac80211.o \
proto_nlmsg.o
diff --git a/sock.c b/sock.c
index a84796c..a4ec434 100644
--- a/sock.c
+++ b/sock.c
@@ -1,7 +1,15 @@
+#include "config.h"
+
 #include 
 #include 
 #include 
 #include 
+#ifdef HAVE_HARDWARE_TIMESTAMPING
+#include 
+#include 
+#include 
+#include 
+#endif
 #include 
 #include 
 
@@ -196,3 +204,34 @@ void reset_system_socket_memory(int *vals, size_t len)
set_system_socket_mem(sock_wmem_max, vals[2]);
set_system_socket_mem(sock_wmem_def, vals[3]);
 }
+
+int set_sockopt_hwtimestamp(int sock, const char *dev)
+{
+#ifdef HAVE_HARDWARE_TIMESTAMPING
+   int timesource, ret;
+   struct hwtstamp_config hwconfig;
+   struct ifreq ifr;
+
+   if (!strncmp("any", dev, strlen("any")))
+   return -1;
+
+   memset(&hwconfig, 0, sizeof(hwconfig));
+   hwconfig.tx_type = HWTSTAMP_TX_OFF;
+   hwconfig.rx_filter = HWTSTAMP_FILTER_ALL;
+
+   memset(&ifr, 0, sizeof(ifr));
+   strlcpy(ifr.ifr_name, dev, sizeof(ifr.ifr_name));
+   ifr.ifr_data = &hwconfig;
+
+   ret = ioctl(sock, SIOCSHWTSTAMP, &ifr);
+   if (ret < 0)
+   return -1;
+
+   timesource = SOF_TIMESTAMPING_RAW_HARDWARE;
+
+   return setsockopt(sock, SOL_PACKET, PACKET_TIMESTAMP, ×ource,
+ sizeof(timesource));
+#else
+   return -1;
+#endif
+}
diff --git a/sock.h b/sock.h
index 8f68d42..bac27ac 100644
--- a/sock.h
+++ b/sock.h
@@ -15,5 +15,6 @@ extern int set_ipv6_only(int fd);
 extern void set_mtu_disc_dont(int fd);
 extern void set_system_socket_memory(int *vals, size_t len);
 extern void reset_system_socket_memory(int *vals, size_t len);
+extern int set_sockopt_hwtimestamp(int sock, const char *dev);
 
 #endif /* SOCK_H */
diff --git a/tstamping.c b/tstamping.c
deleted file mode 100644
index 860b7a0..000
--- a/tstamping.c
+++ /dev/null
@@ -1,38 +0,0 @@
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include "str.h"
-#include "tstamping.h"
-
-int set_sockopt_hwtimestamp(int sock, const char *dev)
-{
-   int timesource, ret;
-   struct hwtstamp_config hwconfig;
-   struct ifreq ifr;
-
-   if (!strncmp("any", dev, strlen("any")))
-   return -1;
-
-   memset(&hwconfig, 0, sizeof(hwconfig));
-   hwconfig.tx_type = HWTSTAMP_TX_OFF;
-   hwconfig.rx_filter = HWTSTAMP_FILTER_ALL;
-
-   memset(&ifr, 0, sizeof(ifr));
-   strlcpy(ifr.ifr_name, dev, sizeof(ifr.ifr_name));
-   ifr.ifr_data = &hwconfig;
-
-   ret = ioctl(sock, SIOCSHWTSTAMP, &ifr);
-   if (ret < 0)
-   return -1;
-
-   timesource = SOF_TIMESTAMPING_RAW_HARDWARE;
-
-   return setsockopt(sock, SOL_PACKET, PACKET_TIMESTAMP, ×ource,
- sizeof(timesource));
-}
diff --git a/tstamping.h b/tstamping.h
deleted file mode 100644
index ccc642e..000
--- a/tstamping.h
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifndef TSTAMPING_H
-#define TSTAMPING_H
-
-#include "config.h"
-
-#ifdef HAVE_HARDWARE_TIMESTAMPING
-extern int set_sockopt_hwtimestamp(int sock, const char *dev);
-#else
-static inline int set_sockopt_hwtimestamp(int sock, const char *dev)
-{
-   return -1;
-}
-#endif
-
-#endif /* TSTAMPING_H */
-- 
2.9.2

-- 
You received this message because you are subscribed to the Google Groups 
"netsniff-ng" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to netsniff-ng+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[netsniff-ng] Re: [RFC PATCH] trafgen: proto: Split static protocol definition out of struct proto_hdr

2016-08-12 Thread Tobias Klauser
On 2016-08-11 at 20:11:02 +0200, Vadim Kochan  wrote:
> On Thu, Aug 11, 2016 at 06:16:27PM +0200, Tobias Klauser wrote:
> > Currently struct proto_hdr is used twofold:
> > 
> >   1) Statically define protocol behavior, i.e. all the *_hdr definitions in
> >  trafgen_l{2,3,4}.c which map a protocol id/layer to a set of callback
> >  functions.
> > 
> >   2) For each packet created at parse time the struct is memcpy()'ed
> >  (including all the static information from 1) and then used to store
> >  dynamic information at parse/run time.
> > 
> > Thus, struct proto_hdr members such as the proto id, layer and the
> > pointers callback functions get copied for each created packet (in
> > addition to the other fields which get changed during parsing). Also,
> > static/dynamic information get mixed and we e.g. can't make the protocol
> > definitions const to ensure they'll not get changed by mistake.
> > 
> > Rather than copying the struct proto_hdr for every packet, clearly
> > separate the two purposes defined above by splitting struct proto_hdr
> > into two structs:
> > 
> >   1) struct proto_ops for the static (const) protocol behavior definition
> > 
> >   2) struct proto_hdr (reduced) for dynamic information
> > 
> > struct proto_hdr keeps a pointer to the corresponding proto_ops instance
> > and uses it to execute the corresponding callbacks.
> 
> You can add my "Acked-by" if it is needed.

Thanks, will add it to the final patch.

> > 
> > Reference: 
> > https://groups.google.com/forum/#!msg/netsniff-ng/20RvwJdh50Y/eMkbmKSaBgAJ
> > Signed-off-by: Tobias Klauser 
> > ---
> >  trafgen_l2.c | 24 ++---
> >  trafgen_l3.c |  8 +++
> >  trafgen_l4.c | 22 +--
> >  trafgen_parser.y |  2 +-
> >  trafgen_proto.c  | 65 
> > +---
> >  trafgen_proto.h  | 40 +-
> >  6 files changed, 83 insertions(+), 78 deletions(-)
> > 
> > diff --git a/trafgen_l2.c b/trafgen_l2.c
> > index 1863332b3543..f09b2a61cacc 100644
> > --- a/trafgen_l2.c
> > +++ b/trafgen_l2.c
> > @@ -47,7 +47,7 @@ static void eth_header_init(struct proto_hdr *hdr)
> > proto_field_set_default_dev_mac(hdr, ETH_SRC_ADDR);
> >  }
> >  
> >  
> > -struct proto_hdr *proto_header_init(enum proto_id pid)
> > +struct proto_hdr *proto_header_new(enum proto_id pid)
> 
> The old name was really bad by may be something like:
> 
> {proto,packet}_header_{add,push}
> 
> might be better ?

I agree, renamed it to proto_header_push.

-- 
You received this message because you are subscribed to the Google Groups 
"netsniff-ng" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to netsniff-ng+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[netsniff-ng] Re: [PATCH] colorize: Squash into colors.h

2016-08-12 Thread Tobias Klauser
On 2016-08-12 at 00:42:24 +0200, Vadim Kochan  wrote:
> Move colorize_xxx macroses to colors.h, the reason
> is to have one file for coloring stuff and have less
> files as possible in the source tree.
> 
> Signed-off-by: Vadim Kochan 

Applied, thanks!

-- 
You received this message because you are subscribed to the Google Groups 
"netsniff-ng" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to netsniff-ng+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.