diff --git a/code/bngblaster/src/bbl_config.c b/code/bngblaster/src/bbl_config.c index 66cf5cb9..aab25079 100644 --- a/code/bngblaster/src/bbl_config.c +++ b/code/bngblaster/src/bbl_config.c @@ -3358,7 +3358,8 @@ json_parse_config(json_t *root) const char *schema[] = { "autostart", "stop-verified", "max-burst", "stream-rate-calculation", - "stream-delay-calculation" + "stream-delay-calculation", + "udp-checksum" }; if(!schema_validate(section, "traffic", schema, sizeof(schema)/sizeof(schema[0]))) { @@ -3385,6 +3386,10 @@ json_parse_config(json_t *root) if(value) { g_ctx->config.stream_delay_calc = json_boolean_value(value); } + JSON_OBJ_GET_BOOL(section, value, "traffic", "udp-checksum"); + if(value) { + g_ctx->config.stream_udp_checksum = json_boolean_value(value); + } } /* Session Traffic Configuration */ diff --git a/code/bngblaster/src/bbl_ctx.h b/code/bngblaster/src/bbl_ctx.h index 785c2d70..dddecc1d 100644 --- a/code/bngblaster/src/bbl_ctx.h +++ b/code/bngblaster/src/bbl_ctx.h @@ -345,6 +345,7 @@ typedef struct bbl_ctx_ bool traffic_stop_verified; bool stream_rate_calc; /* Enable/disable stream rate calculation */ bool stream_delay_calc; /* Enable/disable stream delay calculation */ + bool stream_udp_checksum; /* Enable/disable stream UDP checksum calculation */ uint8_t stream_max_burst; /* Limit the max packets per TX interval */ diff --git a/code/bngblaster/src/bbl_protocols.c b/code/bngblaster/src/bbl_protocols.c index b47fe537..e16dc483 100644 --- a/code/bngblaster/src/bbl_protocols.c +++ b/code/bngblaster/src/bbl_protocols.c @@ -72,7 +72,7 @@ bbl_checksum(uint8_t *buf, uint16_t len) return ~_fold(_checksum(buf, len)); } -static uint16_t +uint16_t bbl_ipv4_udp_checksum(uint32_t src, uint32_t dst, uint8_t *udp, uint16_t udp_len) { uint32_t result; @@ -97,7 +97,7 @@ bbl_ipv4_tcp_checksum(uint32_t src, uint32_t dst, uint8_t *tcp, uint16_t tcp_len return ~_fold(result); } -static uint16_t +uint16_t bbl_ipv6_udp_checksum(ipv6addr_t src, ipv6addr_t dst, uint8_t *udp, uint16_t udp_len) { uint32_t result; @@ -3254,7 +3254,7 @@ decode_udp(uint8_t *buf, uint16_t len, bbl_udp_s *udp; - if(len < 8 || sp_len < sizeof(bbl_udp_s)) { + if(len < UDP_HDR_LEN || sp_len < sizeof(bbl_udp_s)) { return DECODE_ERROR; } @@ -3266,9 +3266,13 @@ decode_udp(uint8_t *buf, uint16_t len, udp->dst = be16toh(*(uint16_t*)buf); BUMP_BUFFER(buf, len, sizeof(uint16_t)); udp->payload_len = be16toh(*(uint16_t*)buf); - udp->payload_len -= 8; BUMP_BUFFER(buf, len, sizeof(uint32_t)); /* len + checksum */ + if(udp->payload_len < UDP_HDR_LEN) { + return DECODE_ERROR; + } + udp->payload_len -= UDP_HDR_LEN; + if(udp->payload_len > len) { return DECODE_ERROR; } diff --git a/code/bngblaster/src/bbl_protocols.h b/code/bngblaster/src/bbl_protocols.h index f5a83fd1..500768fa 100644 --- a/code/bngblaster/src/bbl_protocols.h +++ b/code/bngblaster/src/bbl_protocols.h @@ -270,6 +270,7 @@ #define CMF_MA_NAME_FORMAT_STRING 2 #define TCP_HDR_LEN_MIN 20 +#define UDP_HDR_LEN 8 #define MAX_VLANS 3 @@ -805,10 +806,10 @@ typedef struct bbl_ipv6_ { typedef struct bbl_udp_ { uint16_t src; uint16_t dst; + uint16_t payload_len; /* UDP payload length */ uint8_t protocol; void *next; /* next header */ void *payload; /* UDP payload */ - uint16_t payload_len; /* UDP payload length */ } bbl_udp_s; /* @@ -1026,9 +1027,15 @@ packet_is_bbl(uint8_t *buf, uint16_t len); uint16_t bbl_checksum(uint8_t *buf, uint16_t len); +uint16_t +bbl_ipv4_udp_checksum(uint32_t src, uint32_t dst, uint8_t *udp, uint16_t udp_len); + uint16_t bbl_ipv4_tcp_checksum(uint32_t src, uint32_t dst, uint8_t *tcp, uint16_t tcp_len); +uint16_t +bbl_ipv6_udp_checksum(ipv6addr_t src, ipv6addr_t dst, uint8_t *udp, uint16_t udp_len); + uint16_t bbl_ipv6_tcp_checksum(ipv6addr_t src, ipv6addr_t dst, uint8_t *tcp, uint16_t tcp_len); diff --git a/code/bngblaster/src/bbl_stream.c b/code/bngblaster/src/bbl_stream.c index f4c3e7aa..d72ff71f 100644 --- a/code/bngblaster/src/bbl_stream.c +++ b/code/bngblaster/src/bbl_stream.c @@ -1409,6 +1409,21 @@ bbl_stream_update_tcp(bbl_stream_s *stream) } } +static void +bbl_stream_update_udp(bbl_stream_s *stream) +{ + uint16_t udp_len = stream->tx_bbl_hdr_len + UDP_HDR_LEN; + uint8_t *udp_buf = (uint8_t*)(stream->tx_buf + (stream->tx_len - udp_len)); + uint16_t *checksum = (uint16_t*)(udp_buf+6); + + *checksum = 0; + if(stream->ipv6_src && stream->ipv6_dst) { + *checksum = bbl_ipv6_udp_checksum(stream->ipv6_src, stream->ipv6_dst, udp_buf, udp_len); + } else { + *checksum = bbl_ipv4_udp_checksum(stream->ipv4_src, stream->ipv4_dst, udp_buf, udp_len); + } +} + static bool bbl_stream_lag(bbl_stream_s *stream) { @@ -1544,6 +1559,8 @@ bbl_stream_io_send(io_handle_s *io, bbl_stream_s *stream) *(uint32_t*)(stream->tx_buf + (stream->tx_len - 4)) = io->timestamp.tv_nsec; if(stream->tcp) { bbl_stream_update_tcp(stream); + } else if(g_ctx->config.stream_udp_checksum) { + bbl_stream_update_udp(stream); } if(unlikely(stream->flow_seq == 1)) { stream->tx_first_epoch = io->timestamp.tv_sec;