On Fri, May 24, 2024 at 01:26:54PM -0400, Jon Maloy wrote: > commit a469fc393fa1 ("tcp, tap: Don't increase tap-side sequence counter for dropped frames") > delayed update of conn->seq_to_tap until the moment the corresponding > frame has been successfully pushed out. This has the advantage that we > immediately can make a new attempt to transmit a frame after a failed > trasnmit, rather than waiting for the peer to later discover a gap and > trigger the fast retransmit mechanism to solve the problem. > > This approach has turned out to cause a problem with spurious sequence > number updates during peer-initiated retransmits, and we have realized > it may not be the best way to solve the above issue. > > We now restore the previous method, by updating the said field at the > moment a frame is added to the outqueue. To retain the advantage of > having a quick re-attempt based on local failure detection, we now scan > through the part of the outqueue that had do be dropped, and restore the > sequence counter for each affected connection to the most appropriate > value. > > Signed-off-by: Jon Maloy This still has the issues I pointed out on the last revision... [snip] > +/** > + * tcp_revert_seq() - Revert affected conn->seq_to_tap after failed transmission > + * @conns: Array of connection pointers corresponding to queued frames > + * @frames: Two-dimensional array containing queued frames with sub-iovs > + * @num_frames: Number of entries in the two arrays to be compared > + */ > +static void tcp_revert_seq(struct tcp_tap_conn **conns, struct iovec (*frames)[TCP_NUM_IOVS], > + int num_frames) > +{ > + int i; > + > + for (i = 0; i < num_frames; i++) { > + struct tcp_tap_conn *conn = conns[i]; > + struct tcphdr *th = frames[i][TCP_IOV_PAYLOAD].iov_base; > + uint32_t seq = ntohl(th->seq); > + > + if (SEQ_LE(conn->seq_to_tap, seq)) > + continue; > + > + conn->seq_to_tap = seq; ...one trivial - this would be clearer without the continue - ... > + } > +} > + > /** > * tcp_payload_flush() - Send out buffers for segments with data > * @c: Execution context > */ > static void tcp_payload_flush(const struct ctx *c) > { > - unsigned i; > size_t m; > > m = tap_send_frames(c, &tcp6_l2_iov[0][0], TCP_NUM_IOVS, > tcp6_payload_used); > - for (i = 0; i < m; i++) > - *tcp6_seq_update[i].seq += tcp6_seq_update[i].len; > + if (m != tcp6_payload_used) { > + tcp_revert_seq(tcp6_frame_conns, &tcp6_l2_iov[m], > + tcp6_payload_used - m); .. and one fatal - you're calling this with non-matching entries from frame_conns[] and l2_iov[]. -- David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson