Skip to content

Commit 9c68dab

Browse files
mctpd: use SO_RCVTIMEO socket timeout
Instead of spawning an sd_event loop to wait for socket timeout, use SO_RCVTIMEO socket option to implement socket timeout. For tests, instead of implementing the timeout in the test runner, I think we could use SO_RCVTIMEO on the control socket itself :^) Signed-off-by: Khang D Nguyen <[email protected]>
1 parent ef0d2dc commit 9c68dab

File tree

2 files changed

+20
-50
lines changed

2 files changed

+20
-50
lines changed

src/mctpd.c

Lines changed: 14 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -471,50 +471,6 @@ static void *dfree(void *ptr)
471471
return ptr;
472472
}
473473

474-
static int cb_exit_loop_io(sd_event_source *s, int fd, uint32_t revents,
475-
void *userdata)
476-
{
477-
sd_event_exit(sd_event_source_get_event(s), 0);
478-
return 0;
479-
}
480-
481-
static int cb_exit_loop_timeout(sd_event_source *s, uint64_t usec,
482-
void *userdata)
483-
{
484-
sd_event_exit(sd_event_source_get_event(s), -ETIMEDOUT);
485-
return 0;
486-
}
487-
488-
/* Events are EPOLLIN, EPOLLOUT etc.
489-
Returns 0 on ready, negative on error. -ETIMEDOUT on timeout */
490-
static int wait_fd_timeout(int fd, short events, uint64_t timeout_usec)
491-
{
492-
int rc;
493-
sd_event *ev = NULL;
494-
495-
// Create a new event loop just for the event+timeout
496-
rc = sd_event_new(&ev);
497-
if (rc < 0)
498-
goto out;
499-
500-
rc = sd_event_add_time_relative(ev, NULL, CLOCK_MONOTONIC, timeout_usec,
501-
0, cb_exit_loop_timeout, NULL);
502-
if (rc < 0)
503-
goto out;
504-
505-
rc = sd_event_add_io(ev, NULL, fd, events, cb_exit_loop_io, NULL);
506-
if (rc < 0)
507-
goto out;
508-
509-
// TODO: maybe need to break the loop on SIGINT event too?
510-
rc = sd_event_loop(ev);
511-
512-
out:
513-
if (ev)
514-
sd_event_unref(ev);
515-
return rc;
516-
}
517-
518474
static const char *path_from_peer(const struct peer *peer)
519475
{
520476
if (!peer->published) {
@@ -1521,6 +1477,7 @@ static int endpoint_query_addr(struct ctx *ctx,
15211477
uint8_t **resp, size_t *resp_len,
15221478
struct sockaddr_mctp_ext *resp_addr)
15231479
{
1480+
struct timeval timeout;
15241481
size_t req_addr_len;
15251482
int sd = -1, val;
15261483
ssize_t rc;
@@ -1538,6 +1495,18 @@ static int endpoint_query_addr(struct ctx *ctx,
15381495
goto out;
15391496
}
15401497

1498+
static const long usec_per_sec = 1000000;
1499+
rc = mctp_ops.mctp.setsockopt(
1500+
sd, SOL_SOCKET, SO_RCVTIMEO,
1501+
&(struct timeval){
1502+
.tv_sec = ctx->mctp_timeout / usec_per_sec,
1503+
.tv_usec = ctx->mctp_timeout % usec_per_sec,
1504+
},
1505+
sizeof(timeout));
1506+
if (rc < 0) {
1507+
warn("Kernel does not support socket receive timeout");
1508+
}
1509+
15411510
// We want extended addressing on all received messages
15421511
val = 1;
15431512
rc = mctp_ops.mctp.setsockopt(sd, SOL_MCTP, MCTP_OPT_ADDR_EXT, &val,
@@ -1575,7 +1544,7 @@ static int endpoint_query_addr(struct ctx *ctx,
15751544
goto out;
15761545
}
15771546

1578-
rc = wait_fd_timeout(sd, EPOLLIN, ctx->mctp_timeout);
1547+
rc = read_message(ctx, sd, &buf, &buf_size, resp_addr);
15791548
if (rc < 0) {
15801549
if (rc == -ETIMEDOUT && ctx->verbose) {
15811550
warnx("%s: receive timed out from %s", __func__,
@@ -1584,11 +1553,6 @@ static int endpoint_query_addr(struct ctx *ctx,
15841553
goto out;
15851554
}
15861555

1587-
rc = read_message(ctx, sd, &buf, &buf_size, resp_addr);
1588-
if (rc < 0) {
1589-
goto out;
1590-
}
1591-
15921556
if (resp_addr->smctp_base.smctp_type !=
15931557
req_addr->smctp_base.smctp_type) {
15941558
warnx("Mismatching response type %d for request type %d. dest %s",

tests/mctp-ops-test.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,12 @@ static int mctp_op_setsockopt(int sd, int level, int optname, void *optval,
117117
struct iovec iov[2];
118118
ssize_t rc;
119119

120+
// For both real and stub socket descriptor, socket timeout can be handled by the kernel
121+
// because we are not really doing anything
122+
if (level == SOL_SOCKET && optname == SO_RCVTIMEO) {
123+
return setsockopt(sd, level, optname, optval, optlen);
124+
}
125+
120126
sock_msg.type = SOCK_SETSOCKOPT;
121127
sock_msg.setsockopt.level = level;
122128
sock_msg.setsockopt.optname = optname;

0 commit comments

Comments
 (0)