Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

net: tcp: Fix tcp passive close #5030

Merged
merged 1 commit into from
Nov 20, 2017

Conversation

askawu
Copy link

@askawu askawu commented Nov 17, 2017

Previously, if passive close is peformed, the net context is released
after FIN is received and FIN,ACK is sent. The following last ack from
the peer will be treated as an improper packet, RST is sent to the peer.

This patch refines tcp_established() by centralizing the tcp state
transition and releases the net context only if NET_TCP_CLOSED is
reached.

Besides, the logic that releases the net pkt without appdata (i.e. ACK
or FIN) is moved from packet_received() to tcp_established(). This makes
packet_received() less dependent on the protocol and make the usage of
net pkt more clear in tcp_established().

Fixes: #4901

Signed-off-by: Aska Wu aska.wu@linaro.org

context->tcp->send_ack += 1;
clean_up:
if (net_pkt_appdatalen(pkt) == 0) {
net_pkt_unref(pkt);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This unref is a bit problematic as I am seeing warnings about double unref. Application will release the net_pkt when it receives it, and if the tcp_established() returns NET_DROP, then the packet is also freed in net_core.c:processing_data().
Was this unref here so that if we receive final ack, we return NET_OK and there would be memory leak otherwise?
If so, then better would be to put the net_pkt_unref() where you call clean_up.

In order to avoid the double unref, I used if (net_pkt_appdatalen(pkt) == 0 && ret == NET_OK) { here but there were still some unref warnings as the application might have released the net_pkt already.

I tested this with echo-client with CONFIG_NET_DEBUG_NET_PKT=y (in order to see memory allocations), and #4972 applied. It seemed to work but at some point the echo-client hang and stopped responding, I am trying to find out is this patch causing that or is there some unrelated issue.

If I remove this unref in this line, then echo-server runs out of memory, but with this unref in place, the echo-server runs just fine and I do not see any issues.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed....it will cause double unref because the pkt is released by the application and appdata len is unpredictable. I will try to reproduce the issue by echo client as you mentioned.

Is it a good idea to copy the appdata len to data_len at the begining of tcp_establish()? So we can use data len to decide whether we should unref the pkt in tcp_establish() or not.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Btw, echo_server crash I quote in #5015 (comment) happens in net_context_unref(), so is likely the same issue.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was this unref here so that if we receive final ack, we return NET_OK and there would be memory leak otherwise?

@jukkar, Yes. I also want to put the pkt unref together for clearness since it was hard for me to trace the pkt lifecycle.
However, to prevent double unref, I decide to remove pkt unref from clean_up.

@pfalcon pfalcon self-requested a review November 17, 2017 09:54
Previously, if passive close is peformed, the net context is released
after FIN is received and FIN,ACK is sent. The following last ack from
the peer will be treated as an improper packet, RST is sent to the peer.

This patch refines tcp_established() by centralizing the tcp state
transition and releases the net context only if NET_TCP_CLOSED is
reached.

Besides, the logic that releases the net pkt without appdata (i.e. ACK
or FIN) is moved from packet_received() to tcp_established(). This makes
packet_received() less dependent on the protocol and make the usage of
net pkt more clear in tcp_established().

Fixes: zephyrproject-rtos#4901

Signed-off-by: Aska Wu <aska.wu@linaro.org>
@askawu
Copy link
Author

askawu commented Nov 20, 2017

Update:

Copy link
Member

@jukkar jukkar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was testing this and did not see any issues so far.

@jukkar jukkar merged commit b6c8c2d into zephyrproject-rtos:master Nov 20, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

net: tcp: RST is sent after last ack is received
3 participants