summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTobias Klauser <tklauser@distanz.ch>2015-10-13 11:53:36 +0200
committerTobias Klauser <tklauser@distanz.ch>2015-10-13 11:53:36 +0200
commit19c15748cb0eb431ef20f32ff629a82a6c2b3635 (patch)
treee17c95afa3c51cdf51c562bbc8abab46d994aa69
parentaa43ee0ad84a65efd0415621d5234cfcadf9bed3 (diff)
trafgen: Add checksum helpers for TCP/UDP over IPv6
Add the csumudp6 and csumtcp6 helper functions in order to simplify checksum generation for TCP/UDP packets sent over IPv6. trafgen example for TCP over IPv6: { /* MAC Destination */ fill(0xff, 6), /* MAC Source */ 0x00, 0x02, 0xb3, drnd(3), /* IPv6 Protocol */ c16(0x86DD), /* Version, Traffic Class, Flow Label */ 0b01100000, c8(0), c16(0), /* Payload Length */ c16(54), /* Next Header (TCP) */ c8(6), /* Hop Limit */ c8(64), /* Source IPv6 */ 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xba, 0xac, 0x6f, 0xff, 0xfe, 0xa4, 0x12, 0xe3, /* Destination IPv6 */ 0xfe, 0x80, 0x82, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xde, 0xff, 0xfe, 0x00, 0x06, 0xde, /* TCP Source Port */ c16(55042), /* TCP Destination Port */ c16(55043), /* TCP Sequence Number */ drnd(4), /* TCP Ackn. Number */ c32(0), /* TCP Header length + TCP SYN/ECN Flag */ c16((8 << 12) | (1 << 1) | (1 << 6)) /* Window Size */ c16(16), /* TCP Checksum (offset IPv6, offset TCP) */ csumtcp6(14, 54), /* TCP Options */ 0x00, 0x00, 0x01, 0x01, 0x08, 0x0a, 0x06, 0x91, 0x68, 0x7d, 0x06, 0x91, 0x68, 0x6f, /* Data blob */ "foobar!", } Suggested-by: Eric Dumazet <eric.dumazet@gmail.com> Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
-rw-r--r--csum.h28
-rw-r--r--trafgen.82
-rw-r--r--trafgen.c12
-rw-r--r--trafgen_conf.h2
-rw-r--r--trafgen_lexer.l2
-rw-r--r--trafgen_parser.y25
-rw-r--r--trafgen_stddef.h6
7 files changed, 71 insertions, 6 deletions
diff --git a/csum.h b/csum.h
index ab549f8..19a8bc5 100644
--- a/csum.h
+++ b/csum.h
@@ -3,6 +3,7 @@
#include <netinet/in.h>
#include <netinet/ip.h>
+#include <netinet/ip6.h>
#include "built_in.h"
@@ -171,4 +172,31 @@ static inline uint16_t p4_csum(const struct ip *ip, const uint8_t *data,
return __in_cksum(vec, 2);
}
+static inline uint16_t p6_csum(const struct ip6_hdr *ip6, const uint8_t *data,
+ uint32_t len, uint8_t next_proto)
+{
+ struct cksum_vec vec[2];
+ struct pseudo_hdr {
+ uint8_t src[16];
+ uint8_t dst[16];
+ uint32_t len;
+ uint8_t mbz[3];
+ uint8_t proto;
+ } __packed ph;
+
+ memcpy(&ph.src, ip6->ip6_src.s6_addr, sizeof(ph.src));
+ memcpy(&ph.dst, ip6->ip6_dst.s6_addr, sizeof(ph.dst));
+ ph.len = htons(len);
+ memset(&ph.mbz, 0, sizeof(ph.mbz));
+ ph.proto = next_proto;
+
+ vec[0].ptr = (const uint8_t *) (void *) &ph;
+ vec[0].len = sizeof(ph);
+
+ vec[1].ptr = data;
+ vec[1].len = len;
+
+ return __in_cksum(vec, 2);
+}
+
#endif /* CSUM_H */
diff --git a/trafgen.8 b/trafgen.8
index 31c2f52..84ef518 100644
--- a/trafgen.8
+++ b/trafgen.8
@@ -247,6 +247,8 @@ ii) Checksum helper functions (packet offsets start with 0):
IP/ICMP checksum: csumip/csumicmp(<off-from>, <off-to>)
UDP checksum: csumudp(<off-iphdr>, <off-udpdr>)
TCP checksum: csumtcp(<off-iphdr>, <off-tcphdr>)
+ UDP checksum (IPv6): csumudp6(<off-ip6hdr>, <off-udpdr>)
+ TCP checksum (IPv6): csumtcp6(<off-ip6hdr>, <off-tcphdr>)
.PP
iii) Multibyte functions, compile-time expression evaluation:
.PP
diff --git a/trafgen.c b/trafgen.c
index 93bb1b4..71e4f3a 100644
--- a/trafgen.c
+++ b/trafgen.c
@@ -345,6 +345,18 @@ static void apply_csum16(int id)
(packets[id].len - csum->to),
IPPROTO_TCP);
break;
+ case CSUM_UDP6:
+ sum = p6_csum((void *) packets[id].payload + csum->from,
+ packets[id].payload + csum->to,
+ (packets[id].len - csum->to),
+ IPPROTO_UDP);
+ break;
+ case CSUM_TCP6:
+ sum = p6_csum((void *) packets[id].payload + csum->from,
+ packets[id].payload + csum->to,
+ (packets[id].len - csum->to),
+ IPPROTO_TCP);
+ break;
default:
bug();
break;
diff --git a/trafgen_conf.h b/trafgen_conf.h
index f92e14c..3922d15 100644
--- a/trafgen_conf.h
+++ b/trafgen_conf.h
@@ -12,6 +12,8 @@ enum csum {
CSUM_IP,
CSUM_UDP,
CSUM_TCP,
+ CSUM_UDP6,
+ CSUM_TCP6,
};
struct counter {
diff --git a/trafgen_lexer.l b/trafgen_lexer.l
index a361bfc..6c27b0c 100644
--- a/trafgen_lexer.l
+++ b/trafgen_lexer.l
@@ -87,6 +87,8 @@ number_ascii ([a-zA-Z])
"csumicmp4" { return K_CSUMIP; }
"csumudp" { return K_CSUMUDP; }
"csumtcp" { return K_CSUMTCP; }
+"csumudp6" { return K_CSUMUDP6; }
+"csumtcp6" { return K_CSUMTCP6; }
"drnd" { return K_DRND; }
"dinc" { return K_DINC; }
"ddec" { return K_DDEC; }
diff --git a/trafgen_parser.y b/trafgen_parser.y
index df234f4..f934baa 100644
--- a/trafgen_parser.y
+++ b/trafgen_parser.y
@@ -200,9 +200,21 @@ static void __set_csum16_static(size_t from, size_t to, enum csum which __maybe_
set_byte(psum[1]);
}
+static inline bool is_dynamic_csum(enum csum which)
+{
+ switch (which) {
+ case CSUM_UDP:
+ case CSUM_TCP:
+ case CSUM_UDP6:
+ case CSUM_TCP6:
+ return true;
+ default:
+ return false;
+ }
+}
+
static void set_csum16(size_t from, size_t to, enum csum which)
{
- int make_it_dynamic = 0;
struct packet *pkt = &packets[packet_last];
struct packet_dyn *pktd = &packet_dyn[packetd_last];
@@ -218,10 +230,7 @@ static void set_csum16(size_t from, size_t to, enum csum which)
bug_on(!(from < to));
- if (to >= pkt->len || which == CSUM_TCP || which == CSUM_UDP)
- make_it_dynamic = 1;
-
- if (has_dynamic_elems(pktd) || make_it_dynamic)
+ if (has_dynamic_elems(pktd) || to >= pkt->len || is_dynamic_csum(which))
__set_csum16_dynamic(from, to, which);
else
__set_csum16_static(from, to, which);
@@ -320,7 +329,7 @@ static void set_dynamic_incdec(uint8_t start, uint8_t stop, uint8_t stepping,
}
%token K_COMMENT K_FILL K_RND K_SEQINC K_SEQDEC K_DRND K_DINC K_DDEC K_WHITE
-%token K_CPU K_CSUMIP K_CSUMUDP K_CSUMTCP K_CONST8 K_CONST16 K_CONST32 K_CONST64
+%token K_CPU K_CSUMIP K_CSUMUDP K_CSUMTCP K_CSUMUDP6 K_CSUMTCP6 K_CONST8 K_CONST16 K_CONST32 K_CONST64
%token ',' '{' '}' '(' ')' '[' ']' ':' '-' '+' '*' '/' '%' '&' '|' '<' '>' '^'
@@ -479,6 +488,10 @@ csum
{ set_csum16($3, $5, CSUM_TCP); }
| K_CSUMUDP '(' number delimiter number ')'
{ set_csum16($3, $5, CSUM_UDP); }
+ | K_CSUMTCP6 '(' number delimiter number ')'
+ { set_csum16($3, $5, CSUM_TCP6); }
+ | K_CSUMUDP6 '(' number delimiter number ')'
+ { set_csum16($3, $5, CSUM_UDP6); }
;
seqinc
diff --git a/trafgen_stddef.h b/trafgen_stddef.h
index 13688a6..a02c817 100644
--- a/trafgen_stddef.h
+++ b/trafgen_stddef.h
@@ -120,6 +120,12 @@
#define IP_ID_RAND drnd(2)
#define IP_CSUM_DEFAULT csumip(IP_HDR_OFF_DEFAULT, 33) /* IP-hdr offset from, to */
+#define IPV6_ALEN 16
+#define IPV6_VERSION 6
+#define IPV6_HDR_OFF_DEFAULT 14
+#define IPV6_SRC_RAND drnd(IPV6_ALEN)
+#define IPV6_DST_RAND drnd(IPV6_ALEN)
+
#define ICMP_ECHOREPLY 0 /* Echo Reply */
#define ICMP_DEST_UNREACH 3 /* Destination Unreachable */
#define ICMP_SOURCE_QUENCH 4 /* Source Quench */