From d62b288697683b40cffed37fbc9761383be17e0c Mon Sep 17 00:00:00 2001 From: Michael Tuexen <tuexen@fh-muenster.de> Date: Thu, 6 Jul 2017 08:53:14 +0200 Subject: [PATCH] Add support for absolute TCP sequence numbers. Sponsored by: Netflix, Inc. --- gtests/net/packetdrill/packet.h | 9 +++++---- gtests/net/packetdrill/parser.y | 23 ++++++++++++++++++++++- gtests/net/packetdrill/run_packet.c | 17 +++++++++++------ gtests/net/packetdrill/tcp_packet.c | 4 ++++ gtests/net/packetdrill/tcp_packet.h | 1 + 5 files changed, 43 insertions(+), 11 deletions(-) diff --git a/gtests/net/packetdrill/packet.h b/gtests/net/packetdrill/packet.h index fa7416c2..3d7de771 100644 --- a/gtests/net/packetdrill/packet.h +++ b/gtests/net/packetdrill/packet.h @@ -109,10 +109,11 @@ struct packet { #define FLAG_WIN_NOCHECK 0x1 /* don't check TCP receive window */ #define FLAG_OPTIONS_NOCHECK 0x2 /* don't check TCP options */ #define FLAG_ABSOLUTE_TS_ECR 0x4 /* don't adjust TCP TS ecr */ -#define FLAGS_SCTP_BAD_CRC32C 0x8 /* compute bad CRC32C for SCTP packets */ -#define FLAGS_SCTP_EXPLICIT_TAG 0x10 /* verification tag specified */ -#define FLAGS_SCTP_GENERIC_PACKET 0x20 /* set if it is a generic packet */ -#define FLAGS_UDP_ENCAPSULATED 0x40 /* TCP/UDP or SCTP/UDP encapsulated */ +#define FLAG_ABSOLUTE_SEQ 0x8 /* don't adjust TCP.SEQ */ +#define FLAGS_SCTP_BAD_CRC32C 0x10 /* compute bad CRC32C for SCTP packets */ +#define FLAGS_SCTP_EXPLICIT_TAG 0x20 /* verification tag specified */ +#define FLAGS_SCTP_GENERIC_PACKET 0x40 /* set if it is a generic packet */ +#define FLAGS_UDP_ENCAPSULATED 0x80 /* TCP/UDP or SCTP/UDP encapsulated */ enum ip_ecn_t ecn; /* IPv4/IPv6 ECN treatment for packet */ diff --git a/gtests/net/packetdrill/parser.y b/gtests/net/packetdrill/parser.y index 399656cd..715bfd2b 100644 --- a/gtests/net/packetdrill/parser.y +++ b/gtests/net/packetdrill/parser.y @@ -460,6 +460,7 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string, struct { u32 start_sequence; u16 payload_bytes; + bool absolute; } tcp_sequence_info; struct { int protocol; @@ -2319,7 +2320,7 @@ sctp_protocol_violation_cause_spec } tcp_packet_spec -: packet_prefix opt_ip_info flags seq opt_ack opt_window opt_tcp_options opt_udp_encaps_info{ +: packet_prefix opt_ip_info flags seq opt_ack opt_window opt_tcp_options opt_udp_encaps_info { char *error = NULL; struct packet *outer = $1, *inner = NULL; enum direction_t direction = outer->direction; @@ -2335,6 +2336,7 @@ tcp_packet_spec $4.start_sequence, $4.payload_bytes, $5, $6, $7, absolute_ts_ecr, + $4.absolute, $8.udp_src_port, $8.udp_dst_port, &error); absolute_ts_ecr = false; @@ -2598,6 +2600,25 @@ seq } $$.start_sequence = $1; $$.payload_bytes = $5; + $$.absolute = false; +} +| INTEGER ':' INTEGER '(' INTEGER ')' '!' { + if (!is_valid_u32($1)) { + semantic_error("TCP start sequence number out of range"); + } + if (!is_valid_u32($3)) { + semantic_error("TCP end sequence number out of range"); + } + if (!is_valid_u16($5)) { + semantic_error("TCP payload size out of range"); + } + if ($3 != ($1 +$5)) { + semantic_error("inconsistent TCP sequence numbers and " + "payload size"); + } + $$.start_sequence = $1; + $$.payload_bytes = $5; + $$.absolute = true; } ; diff --git a/gtests/net/packetdrill/run_packet.c b/gtests/net/packetdrill/run_packet.c index 350bbe4a..3debc5d7 100644 --- a/gtests/net/packetdrill/run_packet.c +++ b/gtests/net/packetdrill/run_packet.c @@ -940,8 +940,10 @@ static int map_inbound_packet( /* Remap the sequence number from script sequence number to live. */ const bool is_syn = live_packet->tcp->syn; const u32 seq_offset = remote_seq_script_to_live_offset(socket, is_syn); - live_packet->tcp->seq = - htonl(ntohl(live_packet->tcp->seq) + seq_offset); + if ((live_packet->flags & FLAG_ABSOLUTE_SEQ) == 0) { + live_packet->tcp->seq = + htonl(ntohl(live_packet->tcp->seq) + seq_offset); + } /* Remap the ACK and SACKs from script sequence number to live. */ const u32 ack_offset = local_seq_script_to_live_offset(socket, is_syn); @@ -1188,9 +1190,12 @@ static int map_outbound_live_packet( /* Rewrite TCP sequence number from live to script space. */ const bool is_syn = live_packet->tcp->syn; const u32 seq_offset = local_seq_live_to_script_offset(socket, is_syn); - actual_packet->tcp->seq = - htonl(ntohl(live_packet->tcp->seq) + seq_offset); - + if ((script_packet->flags & FLAG_ABSOLUTE_SEQ) == 0) { + actual_packet->tcp->seq = + htonl(ntohl(live_packet->tcp->seq) + seq_offset); + } else { + actual_packet->tcp->seq = live_packet->tcp->seq; + } /* Rewrite ACKs and SACKs from live to script space. */ const u32 ack_offset = remote_seq_live_to_script_offset(socket, is_syn); if (actual_packet->tcp->ack) @@ -3522,7 +3527,7 @@ int reset_connection(struct state *state, struct socket *socket) packet = new_tcp_packet(socket->address_family, DIRECTION_INBOUND, ECN_NONE, "R.", seq, 0, ack_seq, window, NULL, false, - udp_src_port, udp_dst_port, &error); + false, udp_src_port, udp_dst_port, &error); if (packet == NULL) die("%s", error); diff --git a/gtests/net/packetdrill/tcp_packet.c b/gtests/net/packetdrill/tcp_packet.c index e83a8066..2bbe13f8 100644 --- a/gtests/net/packetdrill/tcp_packet.c +++ b/gtests/net/packetdrill/tcp_packet.c @@ -60,6 +60,7 @@ struct packet *new_tcp_packet(int address_family, s32 window, const struct tcp_options *tcp_options, bool abs_ts_ecr, + bool abs_seq, u16 udp_src_port, u16 udp_dst_port, char **error) @@ -183,6 +184,9 @@ struct packet *new_tcp_packet(int address_family, if (abs_ts_ecr) { packet->flags |= FLAG_ABSOLUTE_TS_ECR; } + if (abs_seq) { + packet->flags |= FLAG_ABSOLUTE_SEQ; + } packet->ip_bytes = ip_bytes; return packet; diff --git a/gtests/net/packetdrill/tcp_packet.h b/gtests/net/packetdrill/tcp_packet.h index 415445e9..deacd96f 100644 --- a/gtests/net/packetdrill/tcp_packet.h +++ b/gtests/net/packetdrill/tcp_packet.h @@ -45,6 +45,7 @@ extern struct packet *new_tcp_packet(int address_family, s32 window, const struct tcp_options *tcp_options, bool abs_ts_ecr, + bool abs_seq, u16 udp_src_port, u16 udp_dst_port, char **error); -- GitLab