In the "in-depth understanding of parallel programming" in the group, a Millet brother asked a question, server a contracted to the server b,seq is 1, but in the case of failure to receive Server B message reply, sent a
RST, but in the RST message, the corresponding SEQ is 1461, a bunch of people are guessing, why seq jumps, because at that time only saw half of the picture, so I let him send the complete message out after I
found that the RST seq is not the reason for the 1, not because of the jump, but normal, because the message sent to B, the length of 1460, but this message did not get a reply, so after the timeout, the application closed the connection,
Causes the kernel stack to send an RST message, and the RST message when picking seq, is not selected to determine the SEQ has been sent, but the current connection has been used out of the SEQ, that is, the current SEQ, even if the message did not receive a reply, will also be used.
See the code specifically:
/* We get here if a process closes a file descriptor (either due to * an explicit CL OSE () or as a byproduct of exit () ' ing ' and there * is unread data in the receive queue. This behavior was recommended * by RFC 2525, section 2.17. -davem */void tcp_send_active_reset (struct sock *sk, gfp_t priority) {struct Sk_buff *skb;/* note:no tcp options attached And we never retransmit this. */SKB = ALLOC_SKB (Max_tcp_header, priority); if (!SKB) {net_inc_stats (Sock_net (SK), linux_mib_tcpabortfailed); return;} /* Reserve space for headers and prepare control bits. */skb_reserve (SKB, Max_tcp_header); TCP_INIT_NONDATA_SKB (SKB, Tcp_acceptable_seq (SK), Tcphdr_ack | Tcphdr_rst); Note that the incoming flag is RST, not fin, and can be specifically referenced by the Tcp_send_fin how the parameter is passed
/* Send it off. */if (TCP_TRANSMIT_SKB (SK, SKB, 0, priority)) Net_inc_stats (Sock_net (SK), linux_mib_tcpabortfailed); Tcp_inc_stats (Sock_net (SK), tcp_mib_outrsts);}
Which concerns the INIT process of the message:
/* Constructs common control bits of Non-data SKB. If Syn/fin is present, * Auto Increment end seqno. */static void tcp_init_nondata_skb (struct sk_buff *skb, u32 seq, U8 flags) {struct Skb_shared_info *shinfo = Skb_shinfo (SKB ); skb->ip_summed = Checksum_partial;skb->csum = 0; TCP_SKB_CB (SKB)->tcp_flags = flags; TCP_SKB_CB (SKB)->sacked = 0;shinfo->gso_segs = 1;shinfo->gso_size = 0;shinfo->gso_type = 0; TCP_SKB_CB (SKB)->seq = Seq;if (Flags & (Tcphdr_syn | Tcphdr_fin)//The mark of our article is Tcphdr_ack | Tcphdr_rst,
seq++;//here +1, but can't get in
TCP_SKB_CB (SKB)->end_seq = seq;//So this article should be the number of incoming SEQ to send how many}
So what is the incoming SEQ?
/* SND. NXT, if window is not shrunk. * If window has been shrunk, what should we make? It isn't clear at all. * Using SND. UNA we'll fail to open window, SND. NXT is out of window. :-(* Anything in between SND. UNA ... Snd. Una+snd. WND also can be already * invalid. OK, let's make this for now: */static inline __u32 tcp_acceptable_seq (const struct sock *sk) {const struct Tcp_sock *TP = t Cp_sk (SK); if (!before (Tcp_wnd_end (TP), TP->SND_NXT) return Tp->snd_nxt;elsereturn tcp_wnd_end (TP);}
Note written more clearly, if the window is not shrunk, that is tp->snd_nxt no out of the window, then the acquisition is TP->SND_NXT, and this value is the message length + 1, that is, 1461.
The selection problem of SEQ in the RST message of TCP for Linux protocol stack