net/tcp: Use the relative value for keep alive timer

unify the timer process logic as other tcp state

Signed-off-by: Xiang Xiao <xiaoxiang@xiaomi.com>
This commit is contained in:
Xiang Xiao 2022-05-18 13:32:56 +08:00 committed by Petro Karashchenko
parent 2d3ee157ce
commit d8b97d7ae8
6 changed files with 45 additions and 52 deletions

View File

@ -284,9 +284,7 @@ struct tcp_conn_s
* system clock tick. * system clock tick.
*/ */
clock_t keeptime; /* Last time that the TCP socket was known to be uint32_t keeptimer; /* KeepAlive timer (dsec) */
* alive (ACK or data received) OR time that the
* last probe was sent. */
uint32_t keepidle; /* Elapsed idle time before first probe sent (dsec) */ uint32_t keepidle; /* Elapsed idle time before first probe sent (dsec) */
uint32_t keepintvl; /* Interval between probes (dsec) */ uint32_t keepintvl; /* Interval between probes (dsec) */
bool keepalive; /* True: KeepAlive enabled; false: disabled */ bool keepalive; /* True: KeepAlive enabled; false: disabled */

View File

@ -727,7 +727,6 @@ FAR struct tcp_conn_s *tcp_alloc(uint8_t domain)
conn->domain = domain; conn->domain = domain;
#endif #endif
#ifdef CONFIG_NET_TCP_KEEPALIVE #ifdef CONFIG_NET_TCP_KEEPALIVE
conn->keeptime = clock_systime_ticks();
conn->keepidle = 2 * DSEC_PER_HOUR; conn->keepidle = 2 * DSEC_PER_HOUR;
conn->keepintvl = 2 * DSEC_PER_SEC; conn->keepintvl = 2 * DSEC_PER_SEC;
conn->keepcnt = 3; conn->keepcnt = 3;

View File

@ -132,7 +132,7 @@ int tcp_getsockopt(FAR struct socket *psock, int option,
else else
{ {
FAR int *keepalive = (FAR int *)value; FAR int *keepalive = (FAR int *)value;
*keepalive = (int)conn->keepalive; *keepalive = conn->keepalive;
*value_len = sizeof(int); *value_len = sizeof(int);
ret = OK; ret = OK;
} }
@ -216,7 +216,7 @@ int tcp_getsockopt(FAR struct socket *psock, int option,
else else
{ {
FAR int *keepcnt = (FAR int *)value; FAR int *keepcnt = (FAR int *)value;
*keepcnt = (int)conn->keepcnt; *keepcnt = conn->keepcnt;
*value_len = sizeof(int); *value_len = sizeof(int);
ret = OK; ret = OK;
} }

View File

@ -1143,13 +1143,9 @@ found:
if (conn->keepalive && if (conn->keepalive &&
(dev->d_len > 0 || (tcp->flags & TCP_ACK) != 0)) (dev->d_len > 0 || (tcp->flags & TCP_ACK) != 0))
{ {
/* Reset the last known "alive" time. /* Reset the "alive" timer. */
*
* REVISIT: At this level, we don't actually know if keep-
* alive is enabled for this connection.
*/
conn->keeptime = clock_systime_ticks(); conn->keeptimer = conn->keepidle;
conn->keepretries = 0; conn->keepretries = 0;
} }
#endif #endif

View File

@ -78,7 +78,7 @@ int tcp_setsockopt(FAR struct socket *psock, int option,
*/ */
FAR struct tcp_conn_s *conn; FAR struct tcp_conn_s *conn;
int ret; int ret = OK;
DEBUGASSERT(psock != NULL && value != NULL && psock->s_conn != NULL); DEBUGASSERT(psock != NULL && value != NULL && psock->s_conn != NULL);
conn = (FAR struct tcp_conn_s *)psock->s_conn; conn = (FAR struct tcp_conn_s *)psock->s_conn;
@ -107,8 +107,8 @@ int tcp_setsockopt(FAR struct socket *psock, int option,
* all of the clones that may use the underlying connection. * all of the clones that may use the underlying connection.
*/ */
case SO_KEEPALIVE: /* Verifies TCP connections active by enabling the case SO_KEEPALIVE: /* Verifies TCP connections active by enabling the
* periodic transmission of probes */ * periodic transmission of probes */
if (value_len != sizeof(int)) if (value_len != sizeof(int))
{ {
ret = -EDOM; ret = -EDOM;
@ -125,9 +125,15 @@ int tcp_setsockopt(FAR struct socket *psock, int option,
} }
else else
{ {
conn->keepalive = (bool)keepalive; conn->keepalive = keepalive;
conn->keeptime = clock_systime_ticks(); /* Reset start time */
ret = OK; /* Reset timer */
if (conn->keepalive)
{
conn->keeptimer = conn->keepidle;
conn->keepretries = 0;
}
} }
} }
break; break;
@ -141,11 +147,7 @@ int tcp_setsockopt(FAR struct socket *psock, int option,
{ {
int nodelay = *(FAR int *)value; int nodelay = *(FAR int *)value;
if (nodelay) if (!nodelay)
{
ret = OK;
}
else
{ {
nerr("ERROR: TCP_NODELAY not supported\n"); nerr("ERROR: TCP_NODELAY not supported\n");
ret = -ENOSYS; ret = -ENOSYS;
@ -170,7 +172,7 @@ int tcp_setsockopt(FAR struct socket *psock, int option,
* be forced to the next larger, whole decisecond value. * be forced to the next larger, whole decisecond value.
*/ */
dsecs = (socktimeo_t)net_timeval2dsec(tv, TV2DS_CEIL); dsecs = net_timeval2dsec(tv, TV2DS_CEIL);
} }
else if (value_len == sizeof(int)) else if (value_len == sizeof(int))
{ {
@ -189,20 +191,24 @@ int tcp_setsockopt(FAR struct socket *psock, int option,
if (option == TCP_KEEPIDLE) if (option == TCP_KEEPIDLE)
{ {
conn->keepidle = (uint16_t)dsecs; conn->keepidle = dsecs;
} }
else else
{ {
conn->keepintvl = (uint16_t)dsecs; conn->keepintvl = dsecs;
} }
conn->keeptime = clock_systime_ticks(); /* Reset start time */ /* Reset timer */
ret = OK; if (conn->keepalive)
{
conn->keeptimer = conn->keepidle;
conn->keepretries = 0;
}
} }
break; break;
case TCP_KEEPCNT: /* Number of keepalives before death */ case TCP_KEEPCNT: /* Number of keepalives before death */
if (value_len != sizeof(int)) if (value_len != sizeof(int))
{ {
ret = -EDOM; ret = -EDOM;
@ -218,9 +224,15 @@ int tcp_setsockopt(FAR struct socket *psock, int option,
} }
else else
{ {
conn->keepcnt = (uint8_t)keepcnt; conn->keepcnt = keepcnt;
conn->keeptime = clock_systime_ticks(); /* Reset start time */
ret = OK; /* Reset time */
if (conn->keepalive)
{
conn->keeptimer = conn->keepidle;
conn->keepretries = 0;
}
} }
} }
break; break;

View File

@ -375,31 +375,19 @@ void tcp_timer(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn,
if (conn->keepalive) if (conn->keepalive)
{ {
socktimeo_t timeo;
uint32_t saveseq; uint32_t saveseq;
/* If this is the first probe, then the keepstart time is
* the time that the last ACK or data was received from the
* remote.
*
* On subsequent retries, keepstart is the time that the
* last probe was sent.
*/
if (conn->keepretries > 0)
{
timeo = (socktimeo_t)conn->keepintvl;
}
else
{
timeo = (socktimeo_t)conn->keepidle;
}
/* Yes... has the idle period elapsed with no data or ACK /* Yes... has the idle period elapsed with no data or ACK
* received from the remote peer? * received from the remote peer?
*/ */
if (net_timeo(conn->keeptime, timeo)) if (conn->keeptimer > hsec)
{
/* Will not yet decrement to zero */
conn->keeptimer -= hsec;
}
else
{ {
/* Yes.. Has the retry count expired? */ /* Yes.. Has the retry count expired? */
@ -464,7 +452,7 @@ void tcp_timer(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn,
#endif #endif
/* Update for the next probe */ /* Update for the next probe */
conn->keeptime = clock_systime_ticks(); conn->keeptimer = conn->keepintvl;
conn->keepretries++; conn->keepretries++;
} }