Hello, I am having some issues with TCP keep-alive on the W5500-EVB pico. Namely, all the keep-alive socket options can be set nominally, but the connection does not reset after the keep-alive time. I am testing this by setting up a connection successfully between two W5500-EVB Picos, and then turning off the client EVB Pico and waiting for the timeout to occur. The timeout never happens (blocking `recv` should return ECONNRESET as it does on Linux, or at least some error code).
For testing, I am using 2 probes with an interval of 5 seconds.
I was going to raise an issue about this, but wanted to see if anyone could
spot something I'm doing wrong first. I
remember TCP keep-alive not working being mentioned on this forum a few months
ago, but I couldn't find an open issue
about it.
This is the code I am using to setup the TCP socket:
```c
static int controller_init(controller_t *controller, uint16_t port) {
int err;
/* Initialize the socket connection. */
controller->sock = socket(AF_INET, SOCK_STREAM, 0);
if (controller->sock < 0) return errno;
int opt = 1;
err = setsockopt(controller->sock, SOL_SOCKET, SO_REUSEADDR, &opt,
sizeof(opt));
if (err < 0) {
herr("Failed to set option SO_REUSEADDR: %d\n", errno);
return errno;
}
/* Create address */
controller->addr.sin_family = AF_INET;
controller->addr.sin_addr.s_addr = INADDR_ANY;
controller->addr.sin_port = htons(port);
/* Make sure client socket fd is marked as invalid until it gets a
connection */
controller->client = -1;
if (bind(controller->sock, (struct sockaddr *)&controller->addr,
sizeof(controller->addr)) < 0) {
herr("Failed to bind\n");
return errno;
}
/* Set up keep-alive options */
int keepalive = 1;
err = setsockopt(controller->sock, SOL_SOCKET, SO_KEEPALIVE, (void
*)&keepalive, sizeof(keepalive));
if (err < 0) {
herr("Failed to set socket as keep-alive: %d.\n", errno);
return errno;
}
/* Each interval between ACK probes is `int_secs` long */
int int_secs = KEEPALIVE_INTERVAL_SECS;
err = setsockopt(controller->sock, IPPROTO_TCP, TCP_KEEPINTVL, &int_secs,
sizeof(int));
if (err < 0) {
herr("Failed to set keep-alive interval to %d: %d.\n", int_secs, errno);
return errno;
}
hinfo("Set keep-alive interval %d s\n", int_secs);
int count = KEEPALIVE_N_PROBES; /* Gives 10 probes (10 * `int_secs`
seconds) to regain connection */
err = setsockopt(controller->sock, IPPROTO_TCP, TCP_KEEPCNT, &count,
sizeof(int));
if (err < 0) {
herr("Failed to set keep-alive probe count to %d: %d.\n", count, errno);
return errno;
}
hinfo("Set number of keep-alive probes: %d\n", count);
return 0;
}
```
And here is the code where I expect to see the timeout:
```c
// controller->client is the `accept`-ed client connection fd
bread = recv(controller->client, (char *)&hdr + total_read, sizeof(hdr) -
total_read, 0);
if (bread == -1) {
herr("Error reading message header: %s\n", strerror(errno));
if (errno == ECONNRESET) {
// TODO: this should trigger an abort because it happens when TCP
keep-alive is done
herr("Lost connection! ABORT!\n");
}
break;
} else if (bread == 0) {
herr("Control box disconnected.\n");
break;
}
total_read += bread;
```
Does anyone have any suggestions about how to resolve this?
--
Matteo Golin
signature.asc
Description: PGP signature
