From 19c15748cb0eb431ef20f32ff629a82a6c2b3635 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Tue, 13 Oct 2015 11:53:36 +0200 Subject: 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 Signed-off-by: Tobias Klauser --- csum.h | 28 ++++++++++++++++++++++++++++ trafgen.8 | 2 ++ trafgen.c | 12 ++++++++++++ trafgen_conf.h | 2 ++ trafgen_lexer.l | 2 ++ trafgen_parser.y | 25 +++++++++++++++++++------ trafgen_stddef.h | 6 ++++++ 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 #include +#include #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(, ) UDP checksum: csumudp(, ) TCP checksum: csumtcp(, ) + UDP checksum (IPv6): csumudp6(, ) + TCP checksum (IPv6): csumtcp6(, ) .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 */ -- cgit v1.2.3-54-g00ecf