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 *net_addr_ntop(sa_family_t family, const void *src,
|
||||||
char *dst, size_t size);
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#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);
|
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,
|
int net_tcp_prepare_segment(struct net_tcp *tcp, u8_t flags,
|
||||||
void *options, size_t optlen,
|
void *options, size_t optlen,
|
||||||
const struct sockaddr_ptr *local,
|
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;
|
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;
|
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;
|
seq = sys_get_be32(tcphdr->seq) + net_pkt_appdatalen(pkt) - 1;
|
||||||
|
|
||||||
if (!seq_greater(ack, seq)) {
|
if (!net_tcp_seq_greater(ack, seq)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue