Add iscsi_set_tcp_syncnt function

This patch adds support for setting TCP_SYNCNT to overwrite
the system default values. This allows indirect support
for a configurable connect timeout.

Linux uses a exponential backoff for SYN retries starting
with 1 second.

This means for a value n for TCP_SYNCNT, the connect will
effectively timeout after 2^(n+1)-1 seconds.
This commit is contained in:
Peter Lieven
2012-10-20 18:43:48 +02:00
parent d1110b7515
commit 78a31ad4a1
6 changed files with 52 additions and 4 deletions

View File

@@ -86,6 +86,34 @@ int set_tcp_user_timeout(struct iscsi_context *iscsi)
return 0;
}
#ifndef TCP_SYNCNT
#define TCP_SYNCNT 7
#endif
int set_tcp_syncnt(struct iscsi_context *iscsi)
{
int level, value;
#if defined(__FreeBSD__) || defined(__sun)
struct protoent *buf;
if ((buf = getprotobyname("tcp")) != NULL)
level = buf->p_proto;
else
return -1;
#else
level = SOL_TCP;
#endif
value = iscsi->tcp_syncnt;
if (setsockopt(iscsi->fd, level, TCP_SYNCNT, &value, sizeof(value)) != 0) {
iscsi_set_error(iscsi, "TCP: Failed to set tcp syn retries. Error %s(%d)", strerror(errno), errno);
return -1;
}
DPRINTF(iscsi,3,"TCP_SYNCNT set to %d",value);
return 0;
}
int
iscsi_connect_async(struct iscsi_context *iscsi, const char *portal,
iscsi_command_cb cb, void *private_data)
@@ -194,6 +222,10 @@ iscsi_connect_async(struct iscsi_context *iscsi, const char *portal,
set_tcp_user_timeout(iscsi);
}
if (iscsi->tcp_syncnt > 0) {
set_tcp_syncnt(iscsi);
}
if (connect(iscsi->fd, ai->ai_addr, socksize) != 0
&& errno != EINPROGRESS) {
iscsi_set_error(iscsi, "Connect failed with errno : "
@@ -461,7 +493,7 @@ iscsi_service(struct iscsi_context *iscsi, int revents)
if (iscsi->is_connected == 0 && iscsi->fd != -1 && revents&POLLOUT) {
int err = 0;
socklen_t err_size = sizeof(err);
DPRINTF(iscsi,3,"inside iscsi service is_connected=0");
if (getsockopt(iscsi->fd, SOL_SOCKET, SO_ERROR,
&err, &err_size) != 0 || err != 0) {
if (err == 0) {
@@ -480,6 +512,8 @@ iscsi_service(struct iscsi_context *iscsi, int revents)
return -1;
}
DPRINTF(iscsi,2,"connection to %s established",iscsi->connected_portal);
iscsi->is_connected = 1;
iscsi->socket_status_cb(iscsi, SCSI_STATUS_GOOD, NULL,
iscsi->connect_data);
@@ -557,6 +591,12 @@ iscsi_free_iscsi_inqueue(struct iscsi_in_pdu *inqueue)
}
}
void iscsi_set_tcp_syncnt(struct iscsi_context *iscsi, int value)
{
iscsi->tcp_syncnt=value;
DPRINTF(iscsi,2,"TCP_SYNCNT will be set to %d on next socket creation",value);
}
void iscsi_set_tcp_user_timeout(struct iscsi_context *iscsi, int timeout_ms)
{
iscsi->tcp_user_timeout=timeout_ms;