[PATCH] tidbits: net-udp: use MSG_STABLE for server mode
Hannes Diethelm <[email protected]> Sun, 26 Jul 2026 20:35:11 +0200
| Newsgroups | dev.linux.lists.xenomai |
|---|---|
| Message-ID | <[email protected]> |
MSG_STABLE is now supported, so it is used to check if a client is already in ARP cache and permanent. If not, use evl_net_solicit() and try again. Signed-off-by: Hannes Diethelm <[email protected]> --- tidbits/oob-net-udp.c | 72 +++++++++++++++++++------------------------ 1 file changed, 32 insertions(+), 40 deletions(-) diff --git a/tidbits/oob-net-udp.c b/tidbits/oob-net-udp.c index 658b463..931c4dc 100644 --- a/tidbits/oob-net-udp.c +++ b/tidbits/oob-net-udp.c @@ -238,9 +238,6 @@ static void server(int s, const char *text, int mcount, ssize_t ret; char *tbuf; char rbuf[16384]; - in_addr_t addr_list[SERVER_ADDR_LIST_SIZE] = {}; - size_t addr_list_fill = 0; - bool solicit_done; tlen = (strlen(text) + 1) * mcount; tbuf = malloc(tlen); @@ -281,39 +278,6 @@ static void server(int s, const char *text, int mcount, evl_printf(" (TRUNCATED)"); evl_printf(": %.*s\n", (int)ret, rbuf); - /* - * We need to call evl_net_solicit for each new client - * once before sending data. This demotes the caller to the - * in-band stage for the first response. - * If this is not done and the ARP address is not - * yet in cache or garbage-collected, oob_sendmsg - * will return EINPROGRESS on start or during runtime. - */ - solicit_done = false; - for (size_t i = 0; i < addr_list_fill && !solicit_done; i++) { - if (addr_list[i] == _addr.sin_addr.s_addr) { - solicit_done = true; - } - } - if (!solicit_done) { - if (verbosity) { - char ip_str[INET_ADDRSTRLEN+1]; - inet_ntop(AF_INET, &(_addr.sin_addr), ip_str, sizeof(ip_str)); - evl_printf("== client %s first seen: evl_net_solicit\n", ip_str); - } - ret = evl_net_solicit(s, (const struct sockaddr *)&_addr, - EVL_NEIGH_PERMANENT); - if (ret) - error(1, -ret, "evl_net_solicit()"); - - if (addr_list_fill < SERVER_ADDR_LIST_SIZE) { - addr_list[addr_list_fill] = _addr.sin_addr.s_addr; - addr_list_fill++; - } else { - error(1, EPERM, "address list full"); - } - } - iov.iov_base = tbuf; iov.iov_len = tlen; msghdr.msg_iov = &iov; @@ -323,9 +287,37 @@ static void server(int s, const char *text, int mcount, msghdr.msg_name = &_addr; msghdr.msg_namelen = sizeof(_addr); msghdr.msg_flags = 0; - ret = oob_sendmsg(s, &msghdr, NULL, 0); - if (ret < 0) - error(1, errno, "oob_sendmsg() failed"); + ret = oob_sendmsg(s, &msghdr, NULL, MSG_STEADY); + if (ret < 0) { + if (errno == EADDRNOTAVAIL) { + /* + * oob_sendmsg with MSG_STEADY returns EADDRNOTAVAIL if + * the MAC address is not yet in ARP cache or not permanent. + * We need to call evl_net_solicit in this case. + * This demotes the caller to the in-band stage for the first response. + * To probe if the MAC address is in the ARP cache without sending + * any data, oob_sendmsg() with msghdr.msg_iov = NULL + * and msghdr.msg_iovlen = 0 can be used. + */ + if (verbosity) { + char ip_str[INET_ADDRSTRLEN + 1]; + inet_ntop(AF_INET, &(_addr.sin_addr), ip_str, sizeof(ip_str)); + evl_printf("== client %s not in ARP cache: evl_net_solicit\n", + ip_str); + } + ret = evl_net_solicit(s, (const struct sockaddr *)&_addr, + EVL_NEIGH_PERMANENT); + if (ret) + error(1, -ret, "evl_net_solicit()"); + + /* oob_sendmsg again, now it should succeed */ + ret = oob_sendmsg(s, &msghdr, NULL, MSG_STEADY); + if (ret < 0) + error(1, errno, "oob_sendmsg() failed"); + } else { + error(1, errno, "oob_sendmsg() failed"); + } + } if (verbosity > 1) print_addr("sent to", &_addr); } @@ -350,7 +342,7 @@ int main(int argc, char *argv[]) struct sockaddr_in addr; const char *ip = NULL; ssize_t ret; - useconds_t delay=1000000; + useconds_t delay = 1000000; while ((c = getopt(argc, argv, "a:m:n:i:w:I:p:dsTRCSb")) != EOF) { switch (c) { -- 2.47.3