net: tcp: Add TCP sequence number comparison compliant with RFC793.
RFC793, "Transmission Control Protocol", defines sequence numbers just as 32-bit numbers without a sign. It doesn't specify any adhoc rules for comparing them, so standard modular arithmetic should be used. Signed-off-by: Paul Sokolovsky <paul.sokolovsky@linaro.org>
This commit is contained in:
parent
3cb13b9687
commit
72a30f3843
2 changed files with 33 additions and 11 deletions
|
@ -863,6 +863,37 @@ int net_addr_pton(sa_family_t family, const char *src, void *dst);
|
|||
char *net_addr_ntop(sa_family_t family, const void *src,
|
||||
char *dst, size_t size);
|
||||
|
||||
/**
|
||||
* @brief Compare TCP sequence numbers.
|
||||
*
|
||||
* @details This function compares TCP sequence numbers,
|
||||
* accounting for wraparound effects.
|
||||
*
|
||||
* @param seq1 First sequence number
|
||||
* @param seq2 Seconds sequence number
|
||||
*
|
||||
* @return < 0 if seq1 < seq2, 0 if seq1 == seq2, > 0 if seq > seq2
|
||||
*/
|
||||
static inline s32_t net_tcp_seq_cmp(u32_t seq1, u32_t seq2)
|
||||
{
|
||||
return (s32_t)(seq1 - seq2);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check that one TCP sequence number is greater.
|
||||
*
|
||||
* @details This is convenience function on top of net_tcp_seq_cmp().
|
||||
*
|
||||
* @param seq1 First sequence number
|
||||
* @param seq2 Seconds sequence number
|
||||
*
|
||||
* @return True if seq > seq2
|
||||
*/
|
||||
static inline bool net_tcp_seq_greater(u32_t seq1, u32_t seq2)
|
||||
{
|
||||
return net_tcp_seq_cmp(seq1, seq2) > 0;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -369,15 +369,6 @@ static inline u32_t get_recv_wnd(struct net_tcp *tcp)
|
|||
return min(NET_TCP_MAX_WIN, NET_TCP_BUF_MAX_LEN);
|
||||
}
|
||||
|
||||
/* True if the (signed!) difference "seq1 - seq2" is positive and less
|
||||
* than 2^29. That is, seq1 is "after" seq2.
|
||||
*/
|
||||
static inline bool seq_greater(u32_t seq1, u32_t seq2)
|
||||
{
|
||||
int d = (int)(seq1 - seq2);
|
||||
return d > 0 && d < 0x20000000;
|
||||
}
|
||||
|
||||
int net_tcp_prepare_segment(struct net_tcp *tcp, u8_t flags,
|
||||
void *options, size_t optlen,
|
||||
const struct sockaddr_ptr *local,
|
||||
|
@ -447,7 +438,7 @@ int net_tcp_prepare_segment(struct net_tcp *tcp, u8_t flags,
|
|||
|
||||
tcp->send_seq = seq;
|
||||
|
||||
if (seq_greater(tcp->send_seq, tcp->recv_max_ack)) {
|
||||
if (net_tcp_seq_greater(tcp->send_seq, tcp->recv_max_ack)) {
|
||||
tcp->recv_max_ack = tcp->send_seq;
|
||||
}
|
||||
|
||||
|
@ -796,7 +787,7 @@ void net_tcp_ack_received(struct net_context *ctx, u32_t ack)
|
|||
|
||||
seq = sys_get_be32(tcphdr->seq) + net_pkt_appdatalen(pkt) - 1;
|
||||
|
||||
if (!seq_greater(ack, seq)) {
|
||||
if (!net_tcp_seq_greater(ack, seq)) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue