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

2016-07-26 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 | 358 +--
 trafgen_proto.c  |   2 +-
 trafgen_proto.h  |   2 +
 3 files changed, 217 insertions(+), 145 deletions(-)

diff --git a/trafgen_parser.y b/trafgen_parser.y
index 091dee9..58ac999 100644
--- a/trafgen_parser.y
+++ b/trafgen_parser.y
@@ -68,6 +68,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)
@@ -350,6 +371,48 @@ static void proto_add(enum proto_id pid)
hdr = proto_header_init(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 {
@@ -613,6 +676,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 ')' { }
;
@@ -623,8 +697,8 @@ eth
 
 eth_param_list
: { }
-   | eth_field { }
-   | eth_field delimiter eth_param_list { }
+   | eth_expr { }
+   | eth_expr delimiter eth_param_list { }
;
 
 eth_type
@@ -634,12 +708,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
@@ -652,8 +727,8 @@ vlan
 
 vlan_param_list
: { }
-   | vlan_field { }
-   | vlan_field delimiter vlan_param_list { }
+   | vlan_expr { }
+   | vlan_expr delimiter vlan_param_list { }
;
 
 vlan_type
@@ -662,20 +737,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 07/15] trafgen: ipv4: Update csum at runtime if needed

2016-07-26 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 |  2 ++
 2 files changed, 29 insertions(+), 6 deletions(-)

diff --git a/trafgen_l3.c b/trafgen_l3.c
index ad58270..aaca5a9 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_hdr *hdr, struct proto_field 
*field)
+{
+   hdr->is_csum_valid = false;
+}
+
+static void ipv4_csum_update(struct proto_hdr *hdr)
+{
+   struct packet *pkt;
+   uint16_t csum;
+
+   if (proto_field_is_set(hdr, IP4_CSUM))
+   return;
+   if (hdr->is_csum_valid)
+   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 struct proto_hdr ipv4_hdr = {
.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 40817a8..eb11896 100644
--- a/trafgen_proto.h
+++ b/trafgen_proto.h
@@ -77,6 +77,8 @@ struct proto_hdr {
size_t fields_count;
size_t len;
 
+   bool is_csum_valid;
+
void (*header_init)(struct proto_hdr *hdr);
void (*header_finish)(struct proto_hdr *hdr);
void (*field_changed)(struct proto_hdr *hdr, struct proto_field *field);
-- 
2.6.3

-- 
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 09/15] trafgen: icmpv6: Update csum at runtime if needed

2016-07-26 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 | 26 +++---
 1 file changed, 15 insertions(+), 11 deletions(-)

diff --git a/trafgen_l4.c b/trafgen_l4.c
index 19ebb37..908641c 100644
--- a/trafgen_l4.c
+++ b/trafgen_l4.c
@@ -202,39 +202,43 @@ 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))
return;
-
if (!lower)
return;
 
total_len = pkt->len - hdr->pkt_offset;
 
-   switch (lower->id) {
-   case PROTO_IP6:
+   proto_field_set_be16(hdr, ICMPV6_CSUM, 0);
+
+   if (lower->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_hdr *hdr, struct proto_field 
*field)
+{
+   hdr->is_csum_valid = false;
 }
 
 static struct proto_hdr icmpv6_hdr = {
.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.6.3

-- 
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 15/15] trafgen: man: Add description for 'dinc' and 'drnd' field functions

2016-07-26 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 | 34 +-
 1 file changed, 33 insertions(+), 1 deletion(-)

diff --git a/trafgen.8 b/trafgen.8
index c958794..1a17113 100644
--- a/trafgen.8
+++ b/trafgen.8
@@ -284,6 +284,38 @@ 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 in a 
specific
+way (increment or randomize). 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(step, min, max)
+.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
+.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.
@@ -755,7 +787,7 @@ The above example rewritten using the header generation 
functions:
  # --- ethernet header ---
  eth(da=00:1b:21:3c:9d:f8, da=90:e2:ba:0a:56:b4, proto=0x0800)
  # --- ip header ---
- ipv4(len=40, id=drnd(2), mf, ttl=64, proto=17, sa=192.168.51.1, 
da=192.168.51.2)
+ ipv4(len=40, id=drnd(), mf, ttl=64, proto=17, sa=192.168.51.1, 
da=192.168.51.2)
  # --- udp header ---
  udp(sport=48054, dport=43514, len=20, csum=0)
  # payload
-- 
2.6.3

-- 
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 08/15] trafgen: icmpv4: Update csum at runtime if needed

2016-07-26 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 79c5914..19ebb37 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_hdr *hdr, struct proto_field 
*field)
+{
+   hdr->is_csum_valid = false;
 }
 
 static struct proto_hdr icmpv4_hdr = {
.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.6.3

-- 
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 11/15] trafgen: tcp: Update csum at runtime if it needed

2016-07-26 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 dbfb1fe..9b4bb7f 100644
--- a/trafgen_l3.c
+++ b/trafgen_l3.c
@@ -50,7 +50,7 @@ static void ipv4_field_changed(struct proto_hdr *hdr, struct 
proto_field *field)
if (field->id == IP4_SADDR || field->id == IP4_DADDR) {
struct proto_hdr *upper = proto_upper_header(hdr);
 
-   if (upper && upper->id == PROTO_UDP)
+   if (upper && (upper->id == PROTO_UDP || upper->id == PROTO_TCP))
upper->is_csum_valid = false;
}
 }
@@ -148,7 +148,7 @@ static void ipv6_field_changed(struct proto_hdr *hdr, 
struct proto_field *field)
if (field->id == IP6_SADDR || field->id == IP6_DADDR) {
struct proto_hdr *upper = proto_upper_header(hdr);
 
-   if (upper && upper->id == PROTO_UDP)
+   if (upper && (upper->id == PROTO_UDP || upper->id == PROTO_TCP))
upper->is_csum_valid = false;
}
 }
diff --git a/trafgen_l4.c b/trafgen_l4.c
index 5749a82..3606e0f 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_hdr *hdr, struct proto_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->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 struct proto_hdr tcp_hdr = {
.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.6.3

-- 
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 13/15] trafgen: parser: Add support of 'dinc' function for proto fields

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

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

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

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

diff --git a/trafgen_parser.y b/trafgen_parser.y
index 58ac999..7872b7c 100644
--- a/trafgen_parser.y
+++ b/trafgen_parser.y
@@ -74,6 +74,7 @@ enum field_expr_type_t {
FIELD_EXPR_MAC,
FIELD_EXPR_IP4_ADDR,
FIELD_EXPR_IP6_ADDR,
+   FIELD_EXPR_INC,
 };
 
 struct proto_field_expr {
@@ -85,6 +86,7 @@ struct proto_field_expr {
struct in6_addr ip6_addr;
long long int number;
uint8_t bytes[256];
+   struct proto_field_func func;
} val;
 };
 
@@ -125,6 +127,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)
@@ -167,6 +175,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)
@@ -376,6 +385,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 = (struct proto_field **)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;
@@ -405,6 +427,14 @@ 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.max)
+   panic("dinc(): min(%u) can't be greater than 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();
@@ -685,6 +715,26 @@ 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.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.inc = 1;
+ field_expr.val.func.min = $3;
+ field_expr.val.func.max = $5; }
+   | 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.inc = $3;
+ field_expr.val.func.min = $5;
+ field_expr.val.func.max = $7; }
;
 
 eth_proto
@@ -1097,6 +1147,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.6.3

-- 
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

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

2016-07-26 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 7872b7c..31868ac 100644
--- a/trafgen_parser.y
+++ b/trafgen_parser.y
@@ -75,6 +75,7 @@ enum field_expr_type_t {
FIELD_EXPR_IP4_ADDR,
FIELD_EXPR_IP6_ADDR,
FIELD_EXPR_INC,
+   FIELD_EXPR_RND,
 };
 
 struct proto_field_expr {
@@ -428,6 +429,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.max)
panic("dinc(): min(%u) can't be greater than max(%u)\n",
field_expr.val.func.min, 
field_expr.val.func.max);
@@ -735,6 +737,13 @@ field_expr
  field_expr.val.func.inc = $3;
  field_expr.val.func.min = $5;
  field_expr.val.func.max = $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.6.3

-- 
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 10/15] trafgen: udp: Update csum at runtime if needed

2016-07-26 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.

Also changed proto_lower_header(...) function to use header index
to lookup lower header faster, the reason is that this function
is used for updating UDP csum.

Signed-off-by: Vadim Kochan 
---
 trafgen_l3.c| 18 ++
 trafgen_l4.c| 37 +
 trafgen_proto.c | 36 +++-
 trafgen_proto.h |  2 ++
 4 files changed, 72 insertions(+), 21 deletions(-)

diff --git a/trafgen_l3.c b/trafgen_l3.c
index aaca5a9..dbfb1fe 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_hdr *hdr, struct proto_field 
*field)
 {
hdr->is_csum_valid = false;
+
+   if (field->id == IP4_SADDR || field->id == IP4_DADDR) {
+   struct proto_hdr *upper = proto_upper_header(hdr);
+
+   if (upper && upper->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_hdr *hdr, struct proto_field 
*field)
+{
+   if (field->id == IP6_SADDR || field->id == IP6_DADDR) {
+   struct proto_hdr *upper = proto_upper_header(hdr);
+
+   if (upper && upper->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 struct proto_hdr ipv6_hdr = {
.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 908641c..5749a82 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_hdr *hdr, struct proto_field *field)
 {
-   struct proto_hdr *lower = proto_lower_header(hdr);
-   struct packet *pkt = current_packet();
+   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->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 struct proto_hdr udp_hdr = {
.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[] = {
diff --git a/trafgen_proto.c b/trafgen_proto.c
index f57d390..9a26f04 100644
--- a/trafgen_proto.c
+++ b/trafgen_proto.c
@@ -39,20 +39,25 @@ static inline struct proto_hdr *proto_current_header(void)
 
 struct proto_hdr *proto_lower_header(struct proto_hdr *hdr)
 {
-   struct proto_hdr **headers = ¤t_packet()->headers[0];
-   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 = 

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

2016-07-26 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 | 29 +
 trafgen_proto.h |  1 +
 2 files changed, 30 insertions(+)

diff --git a/trafgen_proto.c b/trafgen_proto.c
index 069aa00..f57d390 100644
--- a/trafgen_proto.c
+++ b/trafgen_proto.c
@@ -486,6 +486,30 @@ static void field_inc_func(struct proto_field *field)
}
 }
 
+static inline unsigned int 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)
+{
+   unsigned int val = field_rand(field);
+
+   if (field->len == 1) {
+   proto_field_set_u8(field->hdr, field->id, (uint8_t) val);
+   } else if (field->len == 2) {
+   proto_field_set_be16(field->hdr, field->id, (uint16_t) val);
+   } else if (field->len == 4) {
+   proto_field_set_be32(field->hdr, field->id, (uint32_t) val);
+   } else if (field->len > 4) {
+   uint8_t *bytes = __proto_field_get_bytes(field);
+   uint32_t i;
+
+   for (i = 0; i < field->len; i++, val = field_rand(field))
+   bytes[i] = (uint8_t) val;
+   }
+}
+
 void proto_field_func_add(struct proto_hdr *hdr, uint32_t fid,
  struct proto_field_func *func)
 {
@@ -522,6 +546,11 @@ void proto_field_func_add(struct proto_hdr *hdr, uint32_t 
fid,
 
field->func.update_field = field_inc_func;
}
+
+   if (func->type & PROTO_FIELD_FUNC_RND) {
+   field->func.max = field->func.max ?: (uint32_t)~0 - 1;
+   field->func.update_field = field_rnd_func;
+   }
 }
 
 void proto_field_dyn_apply(struct proto_field *field)
diff --git a/trafgen_proto.h b/trafgen_proto.h
index 64f4366..40817a8 100644
--- a/trafgen_proto.h
+++ b/trafgen_proto.h
@@ -38,6 +38,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.6.3

-- 
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 03/15] trafgen: proto: Move proto headers into packet

2016-07-26 Thread Vadim Kochan
Till now headers were used only for packet creation at compile time
only, which does not allow to handle dynamic fields update at runtime.
It needs that proto_hdr entries will be not freed after compile is done.

Signed-off-by: Vadim Kochan 
---
 trafgen_conf.h   |  6 ++
 trafgen_parser.y | 17 ++---
 trafgen_proto.c  | 40 +++-
 trafgen_proto.h  |  2 ++
 4 files changed, 41 insertions(+), 24 deletions(-)

diff --git a/trafgen_conf.h b/trafgen_conf.h
index efce29c..934f8fe 100644
--- a/trafgen_conf.h
+++ b/trafgen_conf.h
@@ -5,6 +5,10 @@
 #include 
 #include 
 
+#include "trafgen_proto.h"
+
+#define PROTO_MAX_LAYERS   16
+
 #define TYPE_INC   0
 #define TYPE_DEC   1
 
@@ -34,6 +38,8 @@ struct csum16 {
 struct packet {
uint8_t *payload;
size_t len;
+   struct proto_hdr *headers[PROTO_MAX_LAYERS];
+   size_t headers_count;
 };
 
 struct packet_dyn {
diff --git a/trafgen_parser.y b/trafgen_parser.y
index a286e6b..091dee9 100644
--- a/trafgen_parser.y
+++ b/trafgen_parser.y
@@ -1004,11 +1004,22 @@ static void dump_conf(void)
 
 void cleanup_packets(void)
 {
-   size_t i;
+   size_t i, j;
 
for (i = 0; i < plen; ++i) {
-   if (packets[i].len > 0)
-   xfree(packets[i].payload);
+   struct packet *pkt = &packets[i];
+
+   if (pkt->len > 0)
+   xfree(pkt->payload);
+
+   for (j = 0; j < pkt->headers_count; j++) {
+   struct proto_hdr *hdr = pkt->headers[j];
+
+   if (hdr->fields)
+   xfree(hdr->fields);
+
+   xfree(hdr);
+   }
}
 
free(packets);
diff --git a/trafgen_proto.c b/trafgen_proto.c
index e5b1ad3..a1d56cf 100644
--- a/trafgen_proto.c
+++ b/trafgen_proto.c
@@ -24,15 +24,23 @@
 
 static struct proto_ctx ctx;
 
-#define PROTO_MAX_LAYERS   16
+static struct proto_hdr *registered;
 
-static struct proto_hdr *headers[PROTO_MAX_LAYERS];
-static size_t headers_count;
+static inline struct proto_hdr *proto_current_header(void)
+{
+   struct proto_hdr **headers = ¤t_packet()->headers[0];
+   size_t headers_count = current_packet()->headers_count;
 
-static struct proto_hdr *registered;
+   if (headers_count > 0)
+   return headers[headers_count - 1];
+
+   bug();
+}
 
 struct proto_hdr *proto_lower_header(struct proto_hdr *hdr)
 {
+   struct proto_hdr **headers = ¤t_packet()->headers[0];
+   size_t headers_count = current_packet()->headers_count;
struct proto_hdr *lower = NULL;
size_t i;
 
@@ -128,10 +136,11 @@ bool proto_field_is_set(struct proto_hdr *hdr, uint32_t 
fid)
 
 struct proto_hdr *proto_header_init(enum proto_id pid)
 {
+   struct proto_hdr **headers = ¤t_packet()->headers[0];
struct proto_hdr *hdr = proto_header_by_id(pid);
struct proto_hdr *new_hdr;
 
-   bug_on(headers_count >= PROTO_MAX_LAYERS);
+   bug_on(current_packet()->headers_count >= PROTO_MAX_LAYERS);
 
new_hdr = xmalloc(sizeof(*new_hdr));
memcpy(new_hdr, hdr, sizeof(*new_hdr));
@@ -141,7 +150,7 @@ struct proto_hdr *proto_header_init(enum proto_id pid)
if (new_hdr->header_init)
new_hdr->header_init(new_hdr);
 
-   headers[headers_count++] = new_hdr;
+   headers[current_packet()->headers_count++] = new_hdr;
return new_hdr;
 }
 
@@ -156,8 +165,8 @@ struct proto_hdr *proto_lower_default_add(struct proto_hdr 
*hdr,
 {
struct proto_hdr *current;
 
-   if (headers_count > 0) {
-   current = headers[headers_count - 1];
+   if (current_packet()->headers_count > 0) {
+   current = proto_current_header();
 
if (current->layer >= proto_header_by_id(pid)->layer)
goto set_proto;
@@ -418,6 +427,8 @@ void protos_init(const char *dev)
 
 void proto_packet_finish(void)
 {
+   struct proto_hdr **headers = ¤t_packet()->headers[0];
+   size_t headers_count = current_packet()->headers_count;
ssize_t i;
 
/* Go down from upper layers to do last calculations (checksum) */
@@ -427,17 +438,4 @@ void proto_packet_finish(void)
if (p->packet_finish)
p->packet_finish(p);
}
-
-   for (i = 0; i < headers_count; i++) {
-   struct proto_hdr *p = headers[i];
-
-   if (p->fields) {
-   xfree(p->fields);
-   p->fields_count = 0;
-   }
-
-   xfree(headers[i]);
-   }
-
-   headers_count = 0;
 }
diff --git a/trafgen_proto.h b/trafgen_proto.h
index d2fde62..41e5b76 100644
--- a/trafgen_proto.h
+++ b/trafgen_proto.h
@@ -5,6 +5,8 @@
 #include 
 #include 
 
+#include "trafgen_conf.h"
+
 struct proto_ctx {
const char *dev;
 };
-- 
2.6.3

-- 
You received this message because you are subscribe

[netsniff-ng] [PATCH 02/15] trafgen: proto: Reference to packet from proto_hdr struct

2016-07-26 Thread Vadim Kochan
Using of current_packet() is not relevant for dynamically updated
fields so lets keep packet index in proto_hdr struct.

Signed-off-by: Vadim Kochan 
---
 trafgen_conf.h   |  2 ++
 trafgen_parser.y | 10 ++
 trafgen_proto.c  | 13 +++--
 trafgen_proto.h  |  4 
 4 files changed, 23 insertions(+), 6 deletions(-)

diff --git a/trafgen_conf.h b/trafgen_conf.h
index 50b437b..efce29c 100644
--- a/trafgen_conf.h
+++ b/trafgen_conf.h
@@ -63,5 +63,7 @@ extern void cleanup_packets(void);
 extern void set_fill(uint8_t val, size_t len);
 
 extern struct packet *current_packet(void);
+extern uint32_t current_packet_id(void);
+extern struct packet *packet_get(uint32_t id);
 
 #endif /* TRAFGEN_CONF */
diff --git a/trafgen_parser.y b/trafgen_parser.y
index 0fe8674..a286e6b 100644
--- a/trafgen_parser.y
+++ b/trafgen_parser.y
@@ -153,6 +153,16 @@ struct packet *current_packet(void)
return &packets[packet_last];
 }
 
+uint32_t current_packet_id(void)
+{
+   return packet_last;
+}
+
+struct packet *packet_get(uint32_t id)
+{
+   return &packets[id];
+}
+
 static void set_byte(uint8_t val)
 {
struct packet *pkt = &packets[packet_last];
diff --git a/trafgen_proto.c b/trafgen_proto.c
index cb0c6ae..e5b1ad3 100644
--- a/trafgen_proto.c
+++ b/trafgen_proto.c
@@ -49,7 +49,7 @@ struct proto_hdr *proto_lower_header(struct proto_hdr *hdr)
 
 uint8_t *proto_header_ptr(struct proto_hdr *hdr)
 {
-   return ¤t_packet()->payload[hdr->pkt_offset];
+   return &packet_get(hdr->pkt_id)->payload[hdr->pkt_offset];
 }
 
 static struct proto_hdr *proto_header_by_id(enum proto_id id)
@@ -81,7 +81,7 @@ static void proto_fields_realloc(struct proto_hdr *hdr, 
size_t count)
 void proto_header_fields_add(struct proto_hdr *hdr,
 const struct proto_field *fields, size_t count)
 {
-   struct packet *pkt = current_packet();
+   struct packet *pkt = packet_get(hdr->pkt_id);
struct proto_field *f;
int i;
 
@@ -99,6 +99,7 @@ void proto_header_fields_add(struct proto_hdr *hdr,
f->shift = fields[i].shift;
f->mask = fields[i].mask;
f->pkt_offset = hdr->pkt_offset + fields[i].offset;
+   f->hdr = hdr;
 
if (f->pkt_offset + f->len > pkt->len) {
hdr->len += f->len;
@@ -135,6 +136,8 @@ struct proto_hdr *proto_header_init(enum proto_id pid)
new_hdr = xmalloc(sizeof(*new_hdr));
memcpy(new_hdr, hdr, sizeof(*new_hdr));
 
+   new_hdr->pkt_id = current_packet_id();
+
if (new_hdr->header_init)
new_hdr->header_init(new_hdr);
 
@@ -187,7 +190,7 @@ static void __proto_field_set_bytes(struct proto_hdr *hdr, 
uint32_t fid,
if (is_default && field->is_set)
return;
 
-   payload = ¤t_packet()->payload[field->pkt_offset];
+   payload = &packet_get(hdr->pkt_id)->payload[field->pkt_offset];
 
if (field->len == 1) {
p8 = payload;
@@ -232,9 +235,7 @@ void proto_field_set_bytes(struct proto_hdr *hdr, uint32_t 
fid, uint8_t *bytes)
 
 static uint8_t *__proto_field_get_bytes(struct proto_field *field)
 {
-   struct packet *pkt = current_packet();
-
-   return &pkt->payload[field->pkt_offset];
+   return &packet_get(field->hdr->pkt_id)->payload[field->pkt_offset];
 }
 
 void proto_field_set_u8(struct proto_hdr *hdr, uint32_t fid, uint8_t val)
diff --git a/trafgen_proto.h b/trafgen_proto.h
index 72cd9f7..d2fde62 100644
--- a/trafgen_proto.h
+++ b/trafgen_proto.h
@@ -30,6 +30,8 @@ enum proto_layer {
PROTO_L4,
 };
 
+struct proto_hdr;
+
 struct proto_field {
uint32_t id;
size_t len;
@@ -40,6 +42,7 @@ struct proto_field {
 
bool is_set;
uint16_t pkt_offset;
+   struct proto_hdr *hdr;
 };
 
 struct proto_hdr {
@@ -49,6 +52,7 @@ struct proto_hdr {
struct proto_hdr *next;
struct proto_ctx *ctx;
uint16_t pkt_offset;
+   uint32_t pkt_id;
struct proto_field *fields;
size_t fields_count;
size_t len;
-- 
2.6.3

-- 
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 01/15] trafgen: Move applying dynamic elements to function

2016-07-26 Thread Vadim Kochan
Same code for applying dynamic elements is used in both places
for slow & fast path modes, lets move them into one inlined function.

Signed-off-by: Vadim Kochan 
---
 trafgen.c | 25 +++--
 1 file changed, 11 insertions(+), 14 deletions(-)

diff --git a/trafgen.c b/trafgen.c
index 002b01a..b76b5d7 100644
--- a/trafgen.c
+++ b/trafgen.c
@@ -612,13 +612,21 @@ static void shaper_delay(struct shaper *sh, unsigned long 
pkt_len)
}
 }
 
+static inline void packet_apply_dyn_elements(int idx)
+{
+   if (packet_dyn_has_elems(&packet_dyn[idx])) {
+   apply_counter(idx);
+   apply_randomizer(idx);
+   apply_csum16(idx);
+   }
+}
+
 static void xmit_slowpath_or_die(struct ctx *ctx, unsigned int cpu, unsigned 
long orig_num)
 {
int ret, icmp_sock = -1;
unsigned long num = 1, i = 0;
struct timeval start, end, diff;
unsigned long long tx_bytes = 0, tx_packets = 0;
-   struct packet_dyn *pktd;
struct sockaddr_ll saddr = {
.sll_family = PF_PACKET,
.sll_halen = ETH_ALEN,
@@ -641,12 +649,7 @@ static void xmit_slowpath_or_die(struct ctx *ctx, unsigned 
int cpu, unsigned lon
shaper_init(&ctx->sh);
 
while (likely(sigint == 0 && num > 0 && plen > 0)) {
-   pktd = &packet_dyn[i];
-   if (packet_dyn_has_elems(pktd)) {
-   apply_counter(i);
-   apply_randomizer(i);
-   apply_csum16(i);
-   }
+   packet_apply_dyn_elements(i);
 retry:
ret = sendto(sock, packets[i].payload, packets[i].len, 0,
 (struct sockaddr *) &saddr, sizeof(saddr));
@@ -713,7 +716,6 @@ static void xmit_fastpath_or_die(struct ctx *ctx, unsigned 
int cpu, unsigned lon
struct ring tx_ring;
struct frame_map *hdr;
struct timeval start, end, diff;
-   struct packet_dyn *pktd;
unsigned long long tx_bytes = 0, tx_packets = 0;
 
set_sock_prio(sock, 512);
@@ -749,12 +751,7 @@ static void xmit_fastpath_or_die(struct ctx *ctx, unsigned 
int cpu, unsigned lon
hdr->tp_h.tp_snaplen = packets[i].len;
hdr->tp_h.tp_len = packets[i].len;
 
-   pktd = &packet_dyn[i];
-   if (packet_dyn_has_elems(pktd)) {
-   apply_counter(i);
-   apply_randomizer(i);
-   apply_csum16(i);
-   }
+   packet_apply_dyn_elements(i);
 
fmemcpy(out, packets[i].payload, packets[i].len);
 
-- 
2.6.3

-- 
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 04/15] trafgen: proto: Force field id to be index in array

2016-07-26 Thread Vadim Kochan
Usually proto fields array is sorted in the same order as related enum,
so id may be used as index for faster lookup, it will make
csum field calculation little faster at runtime.

Signed-off-by: Vadim Kochan 
---
 trafgen_l3.h| 4 ++--
 trafgen_proto.c | 8 +---
 2 files changed, 3 insertions(+), 9 deletions(-)

diff --git a/trafgen_l3.h b/trafgen_l3.h
index a1b1523..e0c9a1c 100644
--- a/trafgen_l3.h
+++ b/trafgen_l3.h
@@ -10,14 +10,14 @@ enum ip4_field {
IP4_LEN,
IP4_ID,
IP4_FLAGS,
+   IP4_MF,
+   IP4_DF,
IP4_FRAG_OFFS,
IP4_TTL,
IP4_PROTO,
IP4_CSUM,
IP4_SADDR,
IP4_DADDR,
-   IP4_DF,
-   IP4_MF,
 };
 
 enum ip6_field {
diff --git a/trafgen_proto.c b/trafgen_proto.c
index a1d56cf..ce389ce 100644
--- a/trafgen_proto.c
+++ b/trafgen_proto.c
@@ -118,13 +118,7 @@ void proto_header_fields_add(struct proto_hdr *hdr,
 
 static struct proto_field *proto_field_by_id(struct proto_hdr *hdr, uint32_t 
fid)
 {
-   int i;
-
-   for (i = 0; i < hdr->fields_count; i++)
-   if (hdr->fields[i].id == fid)
-   return &hdr->fields[i];
-
-   panic("Failed lookup field id %u for proto id %u\n", fid, hdr->id);
+   return &hdr->fields[fid];
 }
 
 bool proto_field_is_set(struct proto_hdr *hdr, uint32_t fid)
-- 
2.6.3

-- 
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 00/15] trafgen: Support dinc & drnd for proto fields

2016-07-26 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()) }

Vadim Kochan (15):
  trafgen: Move applying dynamic elements to function
  trafgen: proto: Reference to packet from proto_hdr struct
  trafgen: proto: Move proto headers into packet
  trafgen: proto: Force field id to be index in array
  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: 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.8|  34 -
 trafgen.c|  34 +++--
 trafgen_conf.h   |  15 ++
 trafgen_l3.c |  51 ++-
 trafgen_l3.h |   4 +-
 trafgen_l4.c | 101 +
 trafgen_parser.y | 445 +--
 trafgen_proto.c  | 205 -
 trafgen_proto.h  |  39 +
 9 files changed, 695 insertions(+), 233 deletions(-)

-- 
2.6.3

-- 
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 05/15] trafgen: proto: Increment proto field at runtime

2016-07-26 Thread Vadim Kochan
Extended 'struct packet_dyn' with proto fields which has
dynamically changing values at runtime.

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 unsigned int value.

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 (csum update).

Signed-off-by: Vadim Kochan 
---
 trafgen.c   |  9 ++
 trafgen_conf.h  |  7 
 trafgen_proto.c | 99 +
 trafgen_proto.h | 26 +++
 4 files changed, 141 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..7f3616c 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;
+   uint32_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 ce389ce..069aa00 100644
--- a/trafgen_proto.c
+++ b/trafgen_proto.c
@@ -419,6 +419,19 @@ void protos_init(const char *dev)
p->ctx = &ctx;
 }
 
+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->packet_update)
+   hdr->packet_update(hdr);
+   }
+}
+
 void proto_packet_finish(void)
 {
struct proto_hdr **headers = ¤t_packet()->headers[0];
@@ -433,3 +446,89 @@ void proto_packet_finish(void)
p->packet_finish(p);
}
 }
+
+static inline unsigned int field_inc(struct proto_field *field)
+{
+   uint32_t val;
+
+   val = field->func.val - field->func.min;
+   val = (val + field->func.inc) % field->func.max;
+   field->func.val = val + field->func.min;
+
+   return field->func.val;
+}
+
+static void field_inc_func(struct proto_field *field)
+{
+   if (field->len == 1) {
+   uint8_t val;
+
+   val = field_inc(field);
+   proto_field_set_u8(field->hdr, field->id, val);
+   } else if (field->len == 2) {
+   uint16_t val;
+
+   val = field_inc(field);
+   proto_field_set_be16(field->hdr, field->id, val);
+   } else if (field->len == 4) {
+   uint32_t val;
+
+   val = field_inc(field);
+   proto_field_set_be32(field->hdr, field->id, val);
+   } else if (field->len > 4) {
+   uint8_t *bytes = __proto_field_get_bytes(field);
+   uint32_t val;
+
+   bytes += field->len - 4;
+   val = field_inc(field);
+
+   *(uint32_t *)bytes = bswap_32(val);
+   }
+}
+
+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);
+
+   memcpy(&field->func, func, sizeof(*func));
+
+   if (func->type & PROTO_FIELD_FUNC_INC) {
+   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