Skip to content

Commit

Permalink
session UPDATE set keepalives per option
Browse files Browse the repository at this point in the history
Set keepalives per option instead of all at once.
  • Loading branch information
roman committed Apr 18, 2024
1 parent 04b5cce commit 56acd55
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 29 deletions.
12 changes: 4 additions & 8 deletions src/server_config.c
Original file line number Diff line number Diff line change
Expand Up @@ -1434,14 +1434,10 @@ nc_server_config_keepalives(const struct lyd_node *node, NC_OPERATION op)

if (op == NC_OP_CREATE) {
endpt->ka.enabled = 1;
/* set default values */
endpt->ka.idle_time = 7200;
endpt->ka.max_probes = 9;
endpt->ka.probe_interval = 75;
} else {
endpt->ka.enabled = 0;
}
ret = nc_sock_configure_keepalive(bind->sock, &endpt->ka);
ret = nc_sock_configure_ka(bind->sock, endpt->ka.enabled);
if (ret) {
goto cleanup;
}
Expand Down Expand Up @@ -1496,7 +1492,7 @@ nc_server_config_idle_time(const struct lyd_node *node, NC_OPERATION op)
/* delete -> set to default */
endpt->ka.idle_time = 7200;
}
ret = nc_sock_configure_keepalive(bind->sock, &endpt->ka);
ret = nc_sock_configure_ka_idle_time(bind->sock, endpt->ka.idle_time);
if (ret) {
goto cleanup;
}
Expand Down Expand Up @@ -1552,7 +1548,7 @@ nc_server_config_max_probes(const struct lyd_node *node, NC_OPERATION op)
/* delete -> set to default */
endpt->ka.max_probes = 9;
}
ret = nc_sock_configure_keepalive(bind->sock, &endpt->ka);
ret = nc_sock_configure_ka_max_probes(bind->sock, endpt->ka.max_probes);
if (ret) {
goto cleanup;
}
Expand Down Expand Up @@ -1608,7 +1604,7 @@ nc_server_config_probe_interval(const struct lyd_node *node, NC_OPERATION op)
/* delete -> set to default */
endpt->ka.probe_interval = 75;
}
ret = nc_sock_configure_keepalive(bind->sock, &endpt->ka);
ret = nc_sock_configure_ka_probe_interval(bind->sock, endpt->ka.probe_interval);
if (ret) {
goto cleanup;
}
Expand Down
55 changes: 38 additions & 17 deletions src/session.c
Original file line number Diff line number Diff line change
Expand Up @@ -230,39 +230,60 @@ nc_is_pk_subject_public_key_info(const char *b64)
#endif /* NC_ENABLED_SSH_TLS */

int
nc_sock_configure_keepalive(int sock, struct nc_keepalives *ka)
nc_sock_configure_ka(int sock, int enabled)
{
int opt;

opt = ka->enabled;
if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &opt, sizeof opt) == -1) {
ERR(NULL, "Could not set SO_KEEPALIVE option (%s).", strerror(errno));
if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &enabled, sizeof enabled) == -1) {
ERR(NULL, "Failed to set SO_KEEPALIVE (%s).", strerror(errno));
return -1;
}
if (!ka->enabled) {
return 0;

return 0;
}

int
nc_sock_configure_ka_idle_time(int sock, int idle_time)
{
if (idle_time < 1) {
ERRARG(NULL, "idle_time");
}

#ifdef TCP_KEEPIDLE
opt = ka->idle_time;
if (setsockopt(sock, IPPROTO_TCP, TCP_KEEPIDLE, &opt, sizeof opt) == -1) {
ERR(NULL, "Setsockopt failed (%s).", strerror(errno));
if (setsockopt(sock, IPPROTO_TCP, TCP_KEEPIDLE, &idle_time, sizeof idle_time) == -1) {
ERR(NULL, "Failed to set TCP_KEEPIDLE (%s).", strerror(errno));
return -1;
}
#endif

return 0;
}

int
nc_sock_configure_ka_max_probes(int sock, int max_probes)
{
if (max_probes < 1) {
ERRARG(NULL, "max_probes");
}

#ifdef TCP_KEEPCNT
opt = ka->max_probes;
if (setsockopt(sock, IPPROTO_TCP, TCP_KEEPCNT, &opt, sizeof opt) == -1) {
ERR(NULL, "Setsockopt failed (%s).", strerror(errno));
if (setsockopt(sock, IPPROTO_TCP, TCP_KEEPCNT, &max_probes, sizeof max_probes) == -1) {
ERR(NULL, "Failed to set TCP_KEEPCNT (%s).", strerror(errno));
return -1;
}
#endif

return 0;
}

int
nc_sock_configure_ka_probe_interval(int sock, int probe_interval)
{
if (probe_interval < 1) {
ERRARG(NULL, "probe_interval");
}

#ifdef TCP_KEEPINTVL
opt = ka->probe_interval;
if (setsockopt(sock, IPPROTO_TCP, TCP_KEEPINTVL, &opt, sizeof opt) == -1) {
ERR(NULL, "Setsockopt failed (%s).", strerror(errno));
if (setsockopt(sock, IPPROTO_TCP, TCP_KEEPINTVL, &probe_interval, sizeof probe_interval) == -1) {
ERR(NULL, "Failed to set TCP_KEEPINTVL (%s).", strerror(errno));
return -1;
}
#endif
Expand Down
15 changes: 13 additions & 2 deletions src/session_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -1618,10 +1618,21 @@ sock_connect(int timeout_ms, int *sock_pending, struct addrinfo *res, struct nc_
goto cleanup;
}

/* enable keep-alive */
if (nc_sock_configure_keepalive(sock, ka)) {
/* configure keepalives */
if (nc_sock_configure_ka(sock, ka->enabled)) {
goto cleanup;
}
if (ka->enabled) {
if (nc_sock_configure_ka_idle_time(sock, ka->idle_time)) {
goto cleanup;
}
if (nc_sock_configure_ka_max_probes(sock, ka->max_probes)) {
goto cleanup;
}
if (nc_sock_configure_ka_probe_interval(sock, ka->probe_interval)) {
goto cleanup;
}
}

/* connected */
if (sock_pending) {
Expand Down
36 changes: 35 additions & 1 deletion src/session_p.h
Original file line number Diff line number Diff line change
Expand Up @@ -815,7 +815,41 @@ int32_t nc_timeouttime_cur_diff(const struct timespec *ts);
*/
void nc_realtime_get(struct timespec *ts);

int nc_sock_configure_keepalive(int sock, struct nc_keepalives *ka);
/**
* @brief Enables/disables TCP keepalives.
*
* @param[in] sock Socket to set this option for.
* @param[in] enabled 1 to enable, 0 to disable keepalives.
* @return 0 on success, -1 on fail.
*/
int nc_sock_configure_ka(int sock, int enabled);

/**
* @brief Set TCP keepalives idle time.
*
* @param[in] sock Socket to set this option for.
* @param[in] idle_time Time in seconds before keepalive packets are sent.
* @return 0 on success, -1 on fail.
*/
int nc_sock_configure_ka_idle_time(int sock, int idle_time);

/**
* @brief Set TCP keepalives max probes.
*
* @param[in] sock Socket to set this option for.
* @param[in] max_probes Maximum number of probes sent before dropping the connection.
* @return 0 on success, -1 on fail.
*/
int nc_sock_configure_ka_max_probes(int sock, int max_probes);

/**
* @brief Set TCP keepalives probe interval.
*
* @param[in] sock Socket to set this option for.
* @param[in] probe_interval Time in seconds between keepalive probes.
* @return 0 on success, -1 on fail.
*/
int nc_sock_configure_ka_probe_interval(int sock, int probe_interval);

struct nc_session *nc_new_session(NC_SIDE side, int shared_ti);

Expand Down
14 changes: 13 additions & 1 deletion src/session_server.c
Original file line number Diff line number Diff line change
Expand Up @@ -304,9 +304,21 @@ nc_sock_listen_inet(const char *address, uint16_t port, struct nc_keepalives *ka
goto fail;
}

if (nc_sock_configure_keepalive(sock, ka)) {
/* configure keepalives */
if (nc_sock_configure_ka(sock, ka->enabled)) {
goto fail;
}
if (ka->enabled) {
if (nc_sock_configure_ka_idle_time(sock, ka->idle_time)) {
goto fail;
}
if (nc_sock_configure_ka_max_probes(sock, ka->max_probes)) {
goto fail;
}
if (nc_sock_configure_ka_probe_interval(sock, ka->probe_interval)) {
goto fail;
}
}

memset(&saddr, 0, sizeof(struct sockaddr_storage));
if (is_ipv4) {
Expand Down

0 comments on commit 56acd55

Please sign in to comment.