diff --git a/gtests/net/packetdrill/packet.h b/gtests/net/packetdrill/packet.h index 3d7de771dc8fe05ba098f31dacd6b8c01a793c7a..eb1ab64c46156d64cb32dc9073aedc2b21ca727c 100644 --- a/gtests/net/packetdrill/packet.h +++ b/gtests/net/packetdrill/packet.h @@ -114,6 +114,8 @@ struct packet { #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 */ +#define FLAG_IGNORE_TS_VAL 0x100 /* set to ignore processing of TS val */ +#define FLAG_IGNORE_SEQ 0x200 /* set to ignore processing of sequence numbers */ 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 a25ffb5b994d6488f27dd643c59a565a4bc7a649..794f87a37c95095d3e30370a527fa3fb176bac49 100644 --- a/gtests/net/packetdrill/parser.y +++ b/gtests/net/packetdrill/parser.y @@ -152,10 +152,11 @@ 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 +/* Temporary variables to allow passing absolute or ignore 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 ignore_ts_val = false; bool absolute_ts_ecr = false; /* Copy the script contents into our single linear buffer. */ @@ -446,6 +447,7 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string, %union { s64 integer; struct abs_integer abs_integer; + struct ignore_integer ignore_integer; double floating; char *string; char *reserved; @@ -461,6 +463,7 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string, u32 start_sequence; u16 payload_bytes; bool absolute; + bool ignore; } tcp_sequence_info; struct { int protocol; @@ -607,6 +610,7 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string, %token <integer> INTEGER HEX_INTEGER %token <string> WORD STRING BACK_QUOTED CODE IPV4_ADDR IPV6_ADDR %type <abs_integer> abs_integer +%type <ignore_integer> ignore_integer %type <direction> direction %type <ip_ecn> opt_ip_info %type <ip_ecn> ip_ecn @@ -2337,10 +2341,13 @@ tcp_packet_spec direction, $2, $3, $4.start_sequence, $4.payload_bytes, $5, $6, $7, + ignore_ts_val, absolute_ts_ecr, $4.absolute, + $4.ignore, $8.udp_src_port, $8.udp_dst_port, &error); + ignore_ts_val = false; absolute_ts_ecr = false; free($3); free($7); @@ -2622,6 +2629,14 @@ seq $$.payload_bytes = $5; $$.absolute = true; } +| ELLIPSIS '(' INTEGER ')' { + if (!is_valid_u16($3)) { + semantic_error("TCP payload size out of range"); + } + $$.start_sequence = 0; + $$.payload_bytes = $3; + $$.ignore = true; +} ; opt_ack @@ -2699,11 +2714,12 @@ tcp_option | SACK sack_block_list { $$ = $2; } -| TIMESTAMP VAL INTEGER ECR abs_integer { +| TIMESTAMP VAL ignore_integer ECR abs_integer { u32 val, ecr; + ignore_ts_val = $3.ignore; absolute_ts_ecr = $5.absolute; $$ = tcp_option_new(TCPOPT_TIMESTAMP, TCPOLEN_TIMESTAMP); - val = $3; + val = $3.integer; ecr = $5.integer; if (!is_valid_u32(val)) { semantic_error("ts val out of range"); @@ -2731,6 +2747,11 @@ abs_integer | INTEGER '!' { $$.integer = $1; $$.absolute = true; } ; +ignore_integer +: INTEGER { $$.integer = $1; $$.ignore = false; } +| ELLIPSIS { $$.integer = 0; $$.ignore = 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 3debc5d7c29d03251c35e1bb857dd1cb88c3f9db..7bb90459bd3e09bc65172edd1c402091593b4977 100644 --- a/gtests/net/packetdrill/run_packet.c +++ b/gtests/net/packetdrill/run_packet.c @@ -1215,9 +1215,11 @@ static int map_outbound_live_packet( u32 actual_ts_val = packet_tcp_ts_val(actual_packet); /* Remember script->actual TS val mapping for later. */ - set_outbound_ts_val_mapping(socket, - script_ts_val, - actual_ts_val); + if (!(script_packet->flags & FLAG_IGNORE_TS_VAL)) { + set_outbound_ts_val_mapping(socket, + script_ts_val, + actual_ts_val); + } /* Find baseline for socket's live->script TS val mapping. */ if (!socket->found_first_tcp_ts) { @@ -2566,9 +2568,10 @@ static int verify_tcp( check_field("tcp_reserved_bits", script_tcp->res1, actual_tcp->res1, error) || - check_field("tcp_seq", - ntohl(script_tcp->seq), - ntohl(actual_tcp->seq), error) || + (script_packet->flags & FLAG_IGNORE_SEQ ? STATUS_OK : + check_field("tcp_seq", + ntohl(script_tcp->seq), + ntohl(actual_tcp->seq), error)) || check_field("tcp_ack_seq", ntohl(script_tcp->ack_seq), ntohl(actual_tcp->ack_seq), error) || @@ -3039,7 +3042,7 @@ static int do_outbound_script_packet( } if (socket->state == SOCKET_PASSIVE_PACKET_RECEIVED) { - if (packet->tcp && packet->tcp->syn && packet->tcp->ack) { + if (packet->tcp && packet->tcp->syn && packet->tcp->ack && !(packet->flags & FLAG_IGNORE_SEQ)) { /* Script says we should see an outbound server SYNACK. */ socket->script.local_isn = ntohl(packet->tcp->seq); DEBUGP("SYNACK script.local_isn: %u\n", @@ -3526,8 +3529,8 @@ 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, - false, udp_src_port, udp_dst_port, &error); + "R.", seq, 0, ack_seq, window, NULL, false, false, + false, 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 2bbe13f89fcd4cff4522b27350a0279583087651..62b6070a722db901ea10f8d9523a8d75ce355f51 100644 --- a/gtests/net/packetdrill/tcp_packet.c +++ b/gtests/net/packetdrill/tcp_packet.c @@ -59,8 +59,10 @@ struct packet *new_tcp_packet(int address_family, u32 ack_sequence, s32 window, const struct tcp_options *tcp_options, + bool ignore_ts_val, bool abs_ts_ecr, bool abs_seq, + bool ignore_seq, u16 udp_src_port, u16 udp_dst_port, char **error) @@ -181,12 +183,18 @@ struct packet *new_tcp_packet(int address_family, tcp_options->length); } + if (ignore_ts_val) { + packet->flags |= FLAG_IGNORE_TS_VAL; + } if (abs_ts_ecr) { packet->flags |= FLAG_ABSOLUTE_TS_ECR; } if (abs_seq) { packet->flags |= FLAG_ABSOLUTE_SEQ; } + if (ignore_seq) { + packet->flags |= FLAG_IGNORE_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 deacd96f98bd65f40ea9597ff1c2749de079d70e..1a9115cd5750c453d1927725fbd10ea07394e70c 100644 --- a/gtests/net/packetdrill/tcp_packet.h +++ b/gtests/net/packetdrill/tcp_packet.h @@ -44,8 +44,10 @@ extern struct packet *new_tcp_packet(int address_family, u32 ack_sequence, s32 window, const struct tcp_options *tcp_options, + bool ignore_ts_val, bool abs_ts_ecr, bool abs_seq, + bool ignore_seq, u16 udp_src_port, u16 udp_dst_port, char **error); diff --git a/gtests/net/packetdrill/types.h b/gtests/net/packetdrill/types.h index c6cc344d3dee2515b64ff34a5ded8eeb7766baa6..21b124ac2df279085fd436777084a64d209213ae 100644 --- a/gtests/net/packetdrill/types.h +++ b/gtests/net/packetdrill/types.h @@ -141,6 +141,12 @@ struct abs_integer { bool absolute; }; +/* Type to handle ... or <integer> for specifying an integer or to ignore one. */ +struct ignore_integer { + s64 integer; + bool ignore; +}; + /* Length of output buffer for inet_ntop, plus prefix length (e.g. "/128"). */ #define ADDR_STR_LEN ((INET_ADDRSTRLEN + INET6_ADDRSTRLEN)+5)