Skip to content

Commit

Permalink
net: tcp: Revisit implementation of passive close
Browse files Browse the repository at this point in the history
This change moves the handling of passive close to a callback function
that handles the {CLOSE_WAIT, LAST_ACK} states.  This cleans up the
callback that handles the established estate, leaving only the handling
for that specific state in the tcp_established() callback.

Also, send the correct acknowledge number and send only an ACK rather
than a FIN+ACK packet while transitioning from ESTABLISHED to
CLOSE_WAIT.

These changes makes Wireshark happy when the connection is closed.

Change-Id: Ieeced5dff845f53a6b61af973dcf0fe3b7b8601f
Signed-off-by: Leandro Pereira <leandro.pereira@intel.com>
  • Loading branch information
lpereira authored and jukkar committed Dec 2, 2016
1 parent bab9430 commit 564d8cd
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 30 deletions.
79 changes: 51 additions & 28 deletions net/yaip/net_context.c
Original file line number Diff line number Diff line change
Expand Up @@ -626,21 +626,15 @@ static int tcp_hdr_len(struct net_buf *buf)
return 4 * (hdr->offset >> 4);
}

/* This is called when we receive data after the connection has been
* established. The core TCP logic is located here.
*/
static enum net_verdict tcp_established(struct net_conn *conn,
static enum net_verdict tcp_passive_close(struct net_conn *conn,
struct net_buf *buf,
void *user_data)
{
struct net_context *context = (struct net_context *)user_data;
struct net_tcp_hdr *hdr;
enum net_verdict ret;

NET_ASSERT(context && context->tcp);

switch (context->tcp->state) {
case NET_TCP_ESTABLISHED:
case NET_TCP_CLOSE_WAIT:
case NET_TCP_LAST_ACK:
break;
Expand All @@ -650,36 +644,65 @@ static enum net_verdict tcp_established(struct net_conn *conn,
return NET_DROP;
}

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

if (context->tcp->state == NET_TCP_LAST_ACK &&
NET_TCP_FLAGS(buf) & NET_TCP_ACK) {
net_context_put(context);
}

return NET_DROP;
}

hdr = (void *)net_nbuf_tcp_data(buf);
/* This is called when we receive data after the connection has been
* established. The core TCP logic is located here.
*/
static enum net_verdict tcp_established(struct net_conn *conn,
struct net_buf *buf,
void *user_data)
{
struct net_context *context = (struct net_context *)user_data;
enum net_verdict ret;

NET_ASSERT(context && context->tcp);

if (context->tcp->state != NET_TCP_ESTABLISHED) {
NET_DBG("Context %p in wrong state %d",
context, context->tcp->state);
return NET_DROP;
}

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

if (NET_TCP_FLAGS(buf) & NET_TCP_FIN) {
/* Sending a FIN and ACK in the CLOSE_WAIT state will
* transition to LAST_ACK state
/* Sending an ACK in the CLOSE_WAIT state will transition to
* LAST_ACK state
*/
net_tcp_change_state(context->tcp, NET_TCP_CLOSE_WAIT);
send_fin_ack(context, &conn->remote_addr);
return NET_DROP;
}
if (NET_TCP_FLAGS(buf) & NET_TCP_ACK) {
if (context->tcp->state == NET_TCP_LAST_ACK) {
net_context_put(context);
net_conn_change_callback(context->conn_handler,
tcp_passive_close, context);

ret = NET_DROP;

context->tcp->send_ack =
sys_get_be32(NET_TCP_BUF(buf)->seq) + 1;
} else {
struct net_tcp_hdr *hdr = (void *)net_nbuf_tcp_data(buf);

if (sys_get_be32(hdr->seq) - context->tcp->send_ack) {
/* Don't try to reorder packets. If it doesn't
* match the next segment exactly, drop and wait for
* retransmit
*/
return NET_DROP;
}
}
if (sys_get_be32(hdr->seq) - context->tcp->send_ack) {
/* Don't try to reorder packets. If it doesn't match
* the next segment exactly, drop and wait for
* retransmit
*/
return NET_DROP;
}

ret = packet_received(conn, buf, user_data);
ret = packet_received(conn, buf, user_data);

context->tcp->send_ack += net_buf_frags_len(buf)
- net_nbuf_ip_hdr_len(buf) - tcp_hdr_len(buf);
}

context->tcp->send_ack += net_buf_frags_len(buf)
- net_nbuf_ip_hdr_len(buf) - tcp_hdr_len(buf);
send_ack(context, &conn->remote_addr);

return ret;
Expand Down
4 changes: 2 additions & 2 deletions net/yaip/tcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,8 @@ int net_tcp_prepare_segment(struct net_tcp *tcp, uint8_t flags,
}
} else if (tcp->state == NET_TCP_FIN_WAIT_2) {
net_tcp_change_state(tcp, NET_TCP_TIME_WAIT);
} else if (tcp->state == NET_TCP_CLOSE_WAIT) {
net_tcp_change_state(tcp, NET_TCP_LAST_ACK);
}
}

Expand All @@ -345,8 +347,6 @@ int net_tcp_prepare_segment(struct net_tcp *tcp, uint8_t flags,
if (tcp->state == NET_TCP_ESTABLISHED ||
tcp->state == NET_TCP_SYN_RCVD) {
net_tcp_change_state(tcp, NET_TCP_FIN_WAIT_1);
} else if (tcp->state == NET_TCP_CLOSE_WAIT) {
net_tcp_change_state(tcp, NET_TCP_LAST_ACK);
}
}

Expand Down

0 comments on commit 564d8cd

Please sign in to comment.