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/run_system_call.c b/gtests/net/packetdrill/run_system_call.c index 13f0b086ea4213b023360157ef062d6d4e6ffac2..1ec42605b3162431df215656133c05f7d5ccdfad 100644 --- a/gtests/net/packetdrill/run_system_call.c +++ b/gtests/net/packetdrill/run_system_call.c @@ -1565,8 +1565,7 @@ static void begin_syscall(struct state *state, struct syscall_spec *syscall) */ enum result_check_t { CHECK_EXACT, /* check that result matches exactly */ - CHECK_NON_NEGATIVE, /* check that result is non-negative */ - CHECK_ALLOW_MAPPING, /* checks for results after accept-syscall */ + CHECK_FD, /* check that result fd or matching error */ }; static int end_syscall(struct state *state, struct syscall_spec *syscall, enum result_check_t mode, int actual, char **error) @@ -1587,14 +1586,14 @@ static int end_syscall(struct state *state, struct syscall_spec *syscall, /* Compare actual vs expected return value */ if (get_s32(syscall->result, &expected, error)) return STATUS_ERR; - if (mode == CHECK_NON_NEGATIVE) { + if (mode == CHECK_FD && expected >= 0) { if (actual < 0) { asprintf(error, "Expected non-negative result but got %d with errno %d (%s)", actual, actual_errno, strerror(actual_errno)); return STATUS_ERR; } - } else if (mode == CHECK_EXACT) { + } else if (mode == CHECK_FD || mode == CHECK_EXACT) { if (actual != expected) { if (actual < 0) asprintf(error, @@ -1608,18 +1607,6 @@ static int end_syscall(struct state *state, struct syscall_spec *syscall, expected, actual); return STATUS_ERR; } - } else if (mode == CHECK_ALLOW_MAPPING) { - if ((expected >= 0) && (actual < 0)) { - asprintf(error, - "Expected non-negative result but got %d with errno %d (%s)", - actual, actual_errno, strerror(actual_errno)); - return STATUS_ERR; - } else if ((expected < 0) && (actual != expected)) { - asprintf(error, - "Expected result %d but got %d", - expected, actual); - return STATUS_ERR; - } } else { assert(!"bad mode"); } @@ -2005,7 +1992,7 @@ static int syscall_socket(struct state *state, struct syscall_spec *syscall, result = socket(domain, type, protocol); - if (end_syscall(state, syscall, CHECK_NON_NEGATIVE, result, error)) + if (end_syscall(state, syscall, CHECK_FD, result, error)) return STATUS_ERR; if (result >= 0) { @@ -2097,7 +2084,7 @@ static int syscall_accept(struct state *state, struct syscall_spec *syscall, result = accept(live_fd, (struct sockaddr *)&live_addr, &live_addrlen); - if (end_syscall(state, syscall, CHECK_ALLOW_MAPPING, result, error)) + if (end_syscall(state, syscall, CHECK_FD, result, error)) return STATUS_ERR; if (result >= 0) { @@ -4288,7 +4275,7 @@ static int syscall_open(struct state *state, struct syscall_spec *syscall, result = open(name, flags); - if (end_syscall(state, syscall, CHECK_NON_NEGATIVE, result, error)) + if (end_syscall(state, syscall, CHECK_FD, result, error)) return STATUS_ERR; if (result >= 0) { @@ -6107,14 +6094,8 @@ static int syscall_sctp_peeloff(struct state *state, struct syscall_spec *syscal begin_syscall(state, syscall); result = sctp_peeloff(live_fd, assoc_id); - if (result < 0) { - if (end_syscall(state, syscall, CHECK_EXACT, result, error)) - return STATUS_ERR; - return STATUS_OK; - } else { - if (end_syscall(state, syscall, CHECK_NON_NEGATIVE, result, error)) - return STATUS_ERR; - } + if (end_syscall(state, syscall, CHECK_FD, result, error)) + return STATUS_ERR; if (get_s32(syscall->result, &script_new_fd, error)) return STATUS_ERR; if (run_syscall_sctp_peeloff(state, script_fd, script_new_fd, result, error)) { @@ -6124,7 +6105,7 @@ static int syscall_sctp_peeloff(struct state *state, struct syscall_spec *syscal return STATUS_OK; #else - asprintf(error, "sctp_connectx is not supported"); + asprintf(error, "sctp_peeloff is not supported"); return STATUS_ERR; #endif } 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)