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

Attachment: signature.asc
Description: PGP signature

Reply via email to