diff --git a/gtests/net/packetdrill/packet.h b/gtests/net/packetdrill/packet.h index a51c9e1162421ed59f972a2bec91e86fdda3045c..a7510b34748cb9144996830c0660589aa9780a66 100644 --- a/gtests/net/packetdrill/packet.h +++ b/gtests/net/packetdrill/packet.h @@ -108,9 +108,10 @@ struct packet { u32 flags; /* various meta-flags */ #define FLAG_WIN_NOCHECK 0x1 /* don't check TCP receive window */ #define FLAG_OPTIONS_NOCHECK 0x2 /* don't check TCP options */ -#define FLAGS_SCTP_BAD_CRC32C 0x4 /* compute bad CRC32C for SCTP packets */ -#define FLAGS_SCTP_EXPLICIT_TAG 0x8 /* verification tag specified */ -#define FLAGS_SCTP_GENERIC_PACKET 0x10 /* set if it is a generic packet */ +#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 */ 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 1821ff1dc8e23164e9f4e0ef9c15dee3424d0093..bd598c0fda356bf1456b71622041935f3cb4365d 100644 --- a/gtests/net/packetdrill/parser.y +++ b/gtests/net/packetdrill/parser.y @@ -152,6 +152,12 @@ static struct script *out_script = NULL; /* The test invocation to pass back to parse_and_finalize_config(). */ struct invocation *invocation; +/* Temporary variables to allow passing absolute timestamp flags to + * the tcp_options struct from the timestamp options. Adding fields + * to struct tcp_option, which might be cleaner, affects the on-wire format. + */ +bool absolute_ts_ecr = false; + /* Copy the script contents into our single linear buffer. */ void copy_script(const char *script_buffer, struct script *script) { @@ -439,6 +445,7 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string, */ %union { s64 integer; + struct abs_integer abs_integer; double floating; char *string; char *reserved; @@ -586,6 +593,7 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string, %token <floating> FLOAT %token <integer> INTEGER HEX_INTEGER %token <string> WORD STRING BACK_QUOTED CODE IPV4_ADDR IPV6_ADDR +%type <abs_integer> abs_integer %type <direction> direction %type <ip_ecn> opt_ip_info %type <ip_ecn> ip_ecn @@ -2366,7 +2374,10 @@ tcp_packet_spec inner = new_tcp_packet(in_config->wire_protocol, direction, $2, $3, $4.start_sequence, $4.payload_bytes, - $5, $6, $7, &error); + $5, $6, $7, + absolute_ts_ecr, + &error); + absolute_ts_ecr = false; free($3); free($7); if (inner == NULL) { @@ -2694,17 +2705,18 @@ tcp_option | SACK sack_block_list { $$ = $2; } -| TIMESTAMP VAL INTEGER ECR INTEGER { +| TIMESTAMP VAL INTEGER ECR abs_integer { u32 val, ecr; + absolute_ts_ecr = $5.absolute; $$ = tcp_option_new(TCPOPT_TIMESTAMP, TCPOLEN_TIMESTAMP); - if (!is_valid_u32($3)) { + val = $3; + ecr = $5.integer; + if (!is_valid_u32(val)) { semantic_error("ts val out of range"); } - if (!is_valid_u32($5)) { + if (!is_valid_u32(ecr)) { semantic_error("ecr val out of range"); } - val = $3; - ecr = $5; $$->data.time_stamp.val = htonl(val); $$->data.time_stamp.ecr = htonl(ecr); } @@ -2720,6 +2732,11 @@ tcp_option } ; +abs_integer +: INTEGER { $$.integer = $1; $$.absolute = false; } +| INTEGER '!' { $$.integer = $1; $$.absolute = true; } +; + sack_block_list : sack_block { $$ = $1; } | sack_block_list sack_block { diff --git a/gtests/net/packetdrill/run_packet.c b/gtests/net/packetdrill/run_packet.c index 5a1af9a190b941a1c99be5b0af93b706100b36a7..a1ee8b032639e594c07514199e4e6f6d5555938d 100644 --- a/gtests/net/packetdrill/run_packet.c +++ b/gtests/net/packetdrill/run_packet.c @@ -936,6 +936,10 @@ static int map_inbound_packet( if (find_tcp_timestamp(live_packet, error)) return STATUS_ERR; + /* If we are using absolute ecr values, do not adjust the ecr. */ + if (live_packet->flags & FLAG_ABSOLUTE_TS_ECR) { + return STATUS_OK; + } /* Remap TCP timestamp echo reply from script value to a live * value. We say "a" rather than "the" live value because * there could be multiple live values corresponding to the @@ -3389,7 +3393,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, &error); + "R.", seq, 0, ack_seq, window, NULL, false, &error); if (packet == NULL) die("%s", error); diff --git a/gtests/net/packetdrill/tcp_packet.c b/gtests/net/packetdrill/tcp_packet.c index 03eeda1a8496b6b5edb4c91394324879efabf8ac..de415f9811e2bafe8e7f6ac6325cb1f64145777a 100644 --- a/gtests/net/packetdrill/tcp_packet.c +++ b/gtests/net/packetdrill/tcp_packet.c @@ -59,6 +59,7 @@ struct packet *new_tcp_packet(int address_family, u32 ack_sequence, s32 window, const struct tcp_options *tcp_options, + bool abs_ts_ecr, char **error) { struct packet *packet = NULL; /* the newly-allocated result packet */ @@ -157,6 +158,10 @@ struct packet *new_tcp_packet(int address_family, tcp_options->length); } + if (abs_ts_ecr) { + packet->flags |= FLAG_ABSOLUTE_TS_ECR; + } + packet->ip_bytes = ip_bytes; return packet; } diff --git a/gtests/net/packetdrill/tcp_packet.h b/gtests/net/packetdrill/tcp_packet.h index c5848ca2f014dd7ba9e10dab89a67bc5550583b7..0c065c0e77291df076c950da2456d49486f1d6b3 100644 --- a/gtests/net/packetdrill/tcp_packet.h +++ b/gtests/net/packetdrill/tcp_packet.h @@ -44,5 +44,6 @@ extern struct packet *new_tcp_packet(int address_family, u32 ack_sequence, s32 window, const struct tcp_options *tcp_options, + bool abs_ts_ecr, char **error); #endif /* __TCP_PACKET_H__ */ diff --git a/gtests/net/packetdrill/types.h b/gtests/net/packetdrill/types.h index a9c6055e2e0fb27fbcf8c864ffd3cdeff0b4fefe..c6cc344d3dee2515b64ff34a5ded8eeb7766baa6 100644 --- a/gtests/net/packetdrill/types.h +++ b/gtests/net/packetdrill/types.h @@ -133,6 +133,14 @@ enum ip_ecn_t { ECN_NOCHECK, }; +/* Type to handle <integer>! for specifying absolute vs adjusted values. + * The <integer>! means absolute integer. Just a plain <integer> is relative. + */ +struct abs_integer { + s64 integer; + bool absolute; +}; + /* Length of output buffer for inet_ntop, plus prefix length (e.g. "/128"). */ #define ADDR_STR_LEN ((INET_ADDRSTRLEN + INET6_ADDRSTRLEN)+5)