From 5dc3f8dc3d7503fad9cfe866c6bc97d4a63c2d2d Mon Sep 17 00:00:00 2001 From: Simon Brummer <simon.brummer@posteo.de> Date: Mon, 4 Feb 2019 20:57:30 +0100 Subject: [PATCH] gnrc_tcp: syn_rcvd pkt loss fix --- sys/net/gnrc/transport_layer/tcp/gnrc_tcp.c | 29 +++++++++++++++---- .../gnrc/transport_layer/tcp/gnrc_tcp_fsm.c | 1 + 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/sys/net/gnrc/transport_layer/tcp/gnrc_tcp.c b/sys/net/gnrc/transport_layer/tcp/gnrc_tcp.c index 15a2401250..e972744bc5 100644 --- a/sys/net/gnrc/transport_layer/tcp/gnrc_tcp.c +++ b/sys/net/gnrc/transport_layer/tcp/gnrc_tcp.c @@ -203,14 +203,33 @@ static int _gnrc_tcp_open(gnrc_tcp_tcb_t *tcb, char *target_addr, uint16_t targe tcb->state != FSM_STATE_CLOSE_WAIT) { mbox_get(&(tcb->mbox), &msg); switch (msg.type) { + case MSG_TYPE_NOTIFY_USER: + DEBUG("gnrc_tcp.c : _gnrc_tcp_open() : MSG_TYPE_NOTIFY_USER\n"); + + /* Setup a timeout to be able to revert back to LISTEN state, in case the + * send SYN+ACK we received upon entering SYN_RCVD is never acknowledged + * by the peer. */ + if ((tcb->state == FSM_STATE_SYN_RCVD) && (tcb->status & STATUS_PASSIVE)) { + _setup_timeout(&connection_timeout, GNRC_TCP_CONNECTION_TIMEOUT_DURATION, + _cb_mbox_put_msg, &connection_timeout_arg); + } + break; + case MSG_TYPE_CONNECTION_TIMEOUT: DEBUG("gnrc_tcp.c : _gnrc_tcp_open() : CONNECTION_TIMEOUT\n"); - _fsm(tcb, FSM_EVENT_TIMEOUT_CONNECTION, NULL, NULL, 0); - ret = -ETIMEDOUT; - break; - case MSG_TYPE_NOTIFY_USER: - DEBUG("gnrc_tcp.c : _gnrc_tcp_open() : MSG_TYPE_NOTIFY_USER\n"); + /* The connection establishment attempt timed out: + * 1) Active connections return -ETIMEOUT. + * 2) Passive connections stop the ongoing retransmissions and repeat the + * open call to wait for the next connection attempt. */ + if (tcb->status & STATUS_PASSIVE) { + _fsm(tcb, FSM_EVENT_CLEAR_RETRANSMIT, NULL, NULL, 0); + _fsm(tcb, FSM_EVENT_CALL_OPEN, NULL, NULL, 0); + } + else { + _fsm(tcb, FSM_EVENT_TIMEOUT_CONNECTION, NULL, NULL, 0); + ret = -ETIMEDOUT; + } break; default: diff --git a/sys/net/gnrc/transport_layer/tcp/gnrc_tcp_fsm.c b/sys/net/gnrc/transport_layer/tcp/gnrc_tcp_fsm.c index 3a8ffe3e18..09cbe23d39 100644 --- a/sys/net/gnrc/transport_layer/tcp/gnrc_tcp_fsm.c +++ b/sys/net/gnrc/transport_layer/tcp/gnrc_tcp_fsm.c @@ -191,6 +191,7 @@ static int _transition_to(gnrc_tcp_tcb_t *tcb, fsm_state_t state) mutex_unlock(&_list_tcb_lock); break; + case FSM_STATE_SYN_RCVD: case FSM_STATE_ESTABLISHED: case FSM_STATE_CLOSE_WAIT: tcb->status |= STATUS_NOTIFY_USER; -- GitLab