Commit ab3b4656 authored by Andy Ross's avatar Andy Ross Committed by Jukka Rissanen
Browse files

net: tcp: Handle received ACK packets correctly



Retain transmitted packets in the queue, and remove them only when a
matching ACK arrives.

Change-Id: I76d6586879dc0499371c52979128bd47e1204132
Signed-off-by: default avatarAndy Ross <andrew.j.ross@intel.com>
Signed-off-by: default avatarLeandro Pereira <leandro.pereira@intel.com>
parent 1ddb9f94
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -743,6 +743,10 @@ static enum net_verdict tcp_established(struct net_conn *conn,

	net_tcp_print_recv_info("DATA", buf, NET_TCP_BUF(buf)->src_port);

	if (NET_TCP_FLAGS(buf) & NET_TCP_ACK) {
		net_tcp_ack_received(context,
				     sys_get_be32(NET_TCP_BUF(buf)->ack));
	}
	if (NET_TCP_FLAGS(buf) & NET_TCP_FIN) {
		/* Sending an ACK in the CLOSE_WAIT state will transition to
		 * LAST_ACK state
+26 −4
Original line number Diff line number Diff line
@@ -614,15 +614,37 @@ int tcp_send_data(struct net_context *context)
	 */
	SYS_SLIST_FOR_EACH_NODE(&context->tcp->sent_list, node) {
		buf = CONTAINER_OF(node, struct net_buf, sent_list);
		net_send_data(buf);
		net_nbuf_unref(buf);
		net_tcp_send_buf(buf);
	}

	sys_slist_init(&context->tcp->sent_list);

	return 0;
}

void net_tcp_ack_received(struct net_context *ctx, uint32_t ack)
{
	sys_slist_t *list = &ctx->tcp->sent_list;
	sys_snode_t *head;
	struct net_buf *buf;
	struct net_tcp_hdr *tcphdr;
	uint32_t seq;

	while (!sys_slist_is_empty(list)) {
		head = sys_slist_peek_head(list);
		buf = CONTAINER_OF(head, struct net_buf, sent_list);
		tcphdr = NET_TCP_BUF(buf);

		seq = sys_get_be32(tcphdr->seq)
			+ net_buf_frags_len(buf) - 1;

		if (seq_greater(ack, seq)) {
			sys_slist_remove(list, NULL, head);
			net_nbuf_unref(buf);
		} else {
			break;
		}
	}
}

void net_tcp_init(void)
{
	k_sem_init(&tcp_lock, 0, UINT_MAX);
+8 −0
Original line number Diff line number Diff line
@@ -294,6 +294,14 @@ int tcp_queue_data(struct net_context *context, struct net_buf *buf);
 */
int net_tcp_send_buf(struct net_buf *buf);

/**
 * @brief Handle a received TCP ACK
 *
 * @param cts Context
 * @param seq Received ACK sequence number
 */
void net_tcp_ack_received(struct net_context *ctx, uint32_t ack);

#if defined(CONFIG_NET_TCP)
void net_tcp_init(void);
#else