* [PATCH 0/1] tidbits: net-ping: add ping tidbit using raw socket @ 2026-06-28 15:39 Hannes Diethelm 2026-06-28 15:39 ` [PATCH 1/1] " Hannes Diethelm 2026-07-05 15:01 ` [PATCH 0/1] " Philippe Gerum 0 siblings, 2 replies; 10+ messages in thread From: Hannes Diethelm @ 2026-06-28 15:39 UTC (permalink / raw) To: xenomai, rpm; +Cc: Hannes Diethelm This patch is the result from experimenting with evl networking. I use it to do basic connection tests from the out of band network and check the timing. It is a bit complex due to evl doesn't support IPPROTO_ICMP sockets. Using the in-band network stack, you can use: sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP); and then only send the icmp part of the message. However, such a support is not really needed, it works fine without. Hannes Diethelm (1): tidbits: net-ping: add ping tidbit using raw socket tidbits/meson.build | 6 + tidbits/oob-net-ping.c | 480 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 486 insertions(+) create mode 100644 tidbits/oob-net-ping.c -- 2.47.3 ^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 1/1] tidbits: net-ping: add ping tidbit using raw socket 2026-06-28 15:39 [PATCH 0/1] tidbits: net-ping: add ping tidbit using raw socket Hannes Diethelm @ 2026-06-28 15:39 ` Hannes Diethelm 2026-07-05 14:57 ` Philippe Gerum 2026-07-05 15:01 ` [PATCH 0/1] " Philippe Gerum 1 sibling, 1 reply; 10+ messages in thread From: Hannes Diethelm @ 2026-06-28 15:39 UTC (permalink / raw) To: xenomai, rpm; +Cc: Hannes Diethelm This tidbit allows to ping any host and measure the response time. Signed-off-by: Hannes Diethelm <hannes.diethelm@gmail.com> --- tidbits/meson.build | 6 + tidbits/oob-net-ping.c | 480 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 486 insertions(+) create mode 100644 tidbits/oob-net-ping.c diff --git a/tidbits/meson.build b/tidbits/meson.build index 3713219..f24502f 100644 --- a/tidbits/meson.build +++ b/tidbits/meson.build @@ -6,6 +6,12 @@ executable('oob-net-icmp', dependencies: libevl_dep ) +executable('oob-net-ping', + 'oob-net-ping.c', + install: true, + dependencies: libevl_dep +) + executable('oob-net-udp', 'oob-net-udp.c', install: true, diff --git a/tidbits/oob-net-ping.c b/tidbits/oob-net-ping.c new file mode 100644 index 0000000..efbe11e --- /dev/null +++ b/tidbits/oob-net-ping.c @@ -0,0 +1,480 @@ +/* + * SPDX-License-Identifier: MIT + * + * This tidbit demonstrates out-of-band networking, by sending + * ICMPv4(ECHO) requests using the raw packet socket + * interface. Responses are received and checked. + * See https://v4.xenomai.org/core/net/ for details. + * + * Copyright (C) 2026 Hannes Diethelm <hannes.diethelm@gmail.com> + * based on oob-net-icmp.c + * + */ + +#include <pthread.h> +#include <error.h> +#include <errno.h> +#include <stdint.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <memory.h> +#include <getopt.h> +#include <sys/socket.h> +#include <sys/ioctl.h> +#include <linux/if_packet.h> +#include <netinet/ether.h> +#include <netinet/ip_icmp.h> +#include <net/ethernet.h> +#include <net/if.h> +#include <arpa/inet.h> +#include <evl/thread.h> +#include <evl/clock.h> +#include <evl/proxy.h> +#include <evl/net/net.h> + +static int verbosity = 1; + +static uint16_t ip_checksum(void *buf, int len) +{ + uint16_t *p = buf; /* buf is assumed to be 16bit-aligned. */ + uint32_t sum = 0; + int count = len; + + while (count > 1) { + sum += *p++; + count -= sizeof(*p); + } + + if (count > 0) + sum += *(uint8_t *)p; + + while (sum >> 16) + sum = (sum & 0xffff) + (sum >> 16); + + return ~sum & 0xffff; +} + +static void dump_packet(const char *title, const unsigned char *buf, int len) +{ + int n = 0; + + evl_printf("== dumping %s, length=%d\n", title, len); + + while (len-- > 0) { + evl_printf("%.2x ", *buf++); + if ((++n % 16) == 0) + evl_printf("\n"); + } + + if (n % 16) + evl_printf("\n"); +} + +static void print_ip_header(const struct ip *iphdr) +{ + evl_printf("iphdr.ip_hl=%d\n", iphdr->ip_hl); + evl_printf("iphdr.ip_v=%d\n", iphdr->ip_v); + evl_printf("iphdr.ip_len=%d\n", ntohs(iphdr->ip_len)); + evl_printf("iphdr.ip_id=%d\n", ntohs(iphdr->ip_id)); + evl_printf("iphdr.ip_p=%d\n", iphdr->ip_p); + evl_printf("iphdr.ip_sum=%#x\n", iphdr->ip_sum); +} + +static void print_icmp_reply(const void *etherbuf, size_t len) +{ + const struct icmphdr *icmphdr; + const struct ip *iphdr; /* no option behind */ + const void *icmpdata; + + dump_packet("ICMP reply", etherbuf, len); + iphdr = etherbuf + ETH_HLEN; + print_ip_header(iphdr); + icmphdr = (const struct icmphdr *)(iphdr + 1); + icmpdata = icmphdr + 1; + (void)icmpdata; + evl_printf("icmp.icmp_type=%d\n", icmphdr->type); + evl_printf("icmp.icmp_id=%d\n", ntohs(icmphdr->un.echo.id)); + evl_printf("icmp.icmp_seq=%d\n", ntohs(icmphdr->un.echo.sequence)); +} + +static int check_icmp_reply(void *etherbuf, size_t len, uint16_t id, uint16_t sequence) +{ + struct ip *iphdr; + struct icmphdr *icmphdr; + + if (len < ETH_HLEN + sizeof(struct ip) + sizeof(struct icmphdr)) { + if (verbosity > 1) + dump_packet("truncated packet", etherbuf, len); + return 1; + } + + size_t datalen = len - ETH_HLEN - sizeof(struct ip) - sizeof(struct icmphdr); + + iphdr = etherbuf + ETH_HLEN; + icmphdr = (struct icmphdr *)(iphdr + 1); + + if (iphdr->ip_hl != 5 || iphdr->ip_v != 4 || iphdr->ip_p != IPPROTO_ICMP) { + if (verbosity > 1) { + dump_packet("mangled packet", etherbuf, len); + print_ip_header(iphdr); + } + return 1; + } + + /* IP checksum */ + uint16_t ip_cksum = ip_checksum(iphdr, sizeof(*iphdr)); + if (ip_cksum != 0) { + evl_printf("ip checksum error\n"); + return 1; + } + + /* ICMP checksum */ + uint16_t icmp_cksum = ip_checksum(icmphdr, sizeof(*icmphdr) + datalen); + if (icmp_cksum != 0) { + evl_printf("icmp checksum error\n"); + return 1; + } + + if (ntohs(icmphdr->un.echo.id) != id) { + evl_printf("id mismatch\n"); + return 1; + } + if (ntohs(icmphdr->un.echo.sequence) != sequence) { + evl_printf("sequence mismatch\n"); + return 1; + } + + if (verbosity > 1) + print_icmp_reply(etherbuf, len); + + return 0; +} + +static size_t build_icmp_request(uint8_t *o_frame, size_t icmplen, + const struct in_addr *dst_ip, + const struct in_addr *src_ip, + const struct ether_addr *dst_mac, + const struct ether_addr *src_mac, + uint16_t id, + uint16_t sequence) +{ + struct icmphdr *icmphdr; + struct ip *iphdr; + uint16_t cksum; + size_t datalen; + size_t pktlen; + uint8_t *data; + + pktlen = icmplen + ETH_HLEN + sizeof(*iphdr); + memset(o_frame, 0, pktlen); + + iphdr = (struct ip *)(o_frame + ETH_HLEN); + icmphdr = (struct icmphdr *)(iphdr + 1); + data = (uint8_t *)(icmphdr + 1); + if (icmplen < sizeof(*icmphdr)) { + evl_printf("icmplen to short\n"); + return 0; + } + datalen = icmplen - sizeof(*icmphdr); + + /* MAC */ + memcpy(o_frame, dst_mac, ETH_ALEN); + memcpy(o_frame + ETH_ALEN, src_mac, ETH_ALEN); + o_frame[ETH_HLEN - 2] = (ETH_P_IP >> 8) & 0xff; + o_frame[ETH_HLEN - 1] = ETH_P_IP & 0xff; + + /* IPv4 */ + iphdr->ip_hl = 5; + iphdr->ip_v = 4; + iphdr->ip_tos = 0; + iphdr->ip_len = htons(pktlen - ETH_HLEN); + iphdr->ip_id = htons(sequence + id + 0x1000); + iphdr->ip_off = htons(IP_DF); + iphdr->ip_ttl = 64; + iphdr->ip_p = IPPROTO_ICMP; + memcpy(&iphdr->ip_src, src_ip, sizeof(iphdr->ip_src)); + memcpy(&iphdr->ip_dst, dst_ip, sizeof(iphdr->ip_dst)); + iphdr->ip_sum = 0; + iphdr->ip_sum = ip_checksum(iphdr, sizeof(*iphdr)); + + /* ICMP */ + icmphdr->type = ICMP_ECHO; + icmphdr->code = 0; + icmphdr->un.echo.id = htons(id); + icmphdr->un.echo.sequence = htons(sequence); + icmphdr->checksum = 0; + + /* data */ + for (size_t i = 0; i < datalen; i++) + data[i] = i + '0'; + + /* ICMP checksum */ + cksum = ip_checksum(icmphdr, sizeof(*icmphdr) + datalen); + icmphdr->checksum = cksum; + + if (verbosity > 1) { + evl_printf("ip_len=%zd, icmp_len=%zd, ip_len=%d, datalen=%ld\n", + sizeof(*iphdr), sizeof(struct icmphdr), + ntohs(iphdr->ip_len), datalen); + print_ip_header(iphdr); + dump_packet("ICMP request", o_frame, pktlen); + } + + return pktlen; +} + +static void usage(void) +{ + fprintf(stderr, "oob-net-ping -i <network-interface> -a <addr> [-d][-s]\n"); +} + +int main(int argc, char *argv[]) +{ + uint8_t i_frame[ETHER_MAX_LEN], o_frame[ETHER_MAX_LEN]; + int ret, tfd, s, c, ifindex; + const char *netif = NULL; + const char *ip_addr = NULL; + struct oob_msghdr msghdr; + struct sched_param param; + struct sockaddr_ll addr; + struct sockaddr_in dst_addr, src_addr; + struct sockaddr dst_hwaddr, src_hwaddr; + struct arpreq arp_request; + struct ifreq ifr; + struct iovec iov; + struct timespec ts_timeout; + struct timespec ts_ping_tx; + struct timespec ts_ping_rx; + uint16_t id = getpid(); //Use pid as ID randomization + uint16_t sequence = 0; + ssize_t count; + useconds_t delay=1000000; + + while ((c = getopt(argc, argv, "i:a:w:ds")) != EOF) { + switch (c) { + case 'i': + netif = optarg; + break; + case 'a': + ip_addr = optarg; + break; + case 'w': + delay = atoi(optarg); + break; + case 'd': + verbosity = 2; + break; + case 's': + verbosity = 0; + break; + default: + usage(); + exit(1); + } + } + + dst_addr.sin_family = AF_INET; + dst_addr.sin_port = htons(0); + if (!inet_pton(AF_INET, ip_addr, &dst_addr.sin_addr)) + error(1, EINVAL, "invalid IP address"); + + if (netif == NULL || ip_addr == NULL) { + usage(); + exit(2); + } + + param.sched_priority = 1; + ret = pthread_setschedparam(pthread_self(), SCHED_FIFO, ¶m); + if (ret) + error(1, ret, "pthread_setschedparam()"); + + tfd = evl_attach_self("oob-net-icmp:%d", getpid()); + if (tfd < 0) + error(1, -tfd, "cannot attach to the EVL core"); + + /* + * Get a UDP socket with out-of-band capabilities for solicit. + * Solicit does not work with raw socket (It can not, raw captures all) + */ + s = socket(AF_INET, SOCK_DGRAM | SOCK_OOB, 0); + if (s < 0) + error(1, errno, "cannot create drgram packet socket"); + + if (netif) { + if (setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE, netif, strlen(netif))) + error(1, errno, "setsockopt(SO_BINDTODEVICE)"); + if (verbosity) + printf("== bound to %s\n", netif); + } + /* + * Guarantee a mere oob path from the first packet + * onward by pre-caching the route and link-layer + * address via an explicit neighbour solicitation + * before we start sending data. + */ + ret = evl_net_solicit(s, (const struct sockaddr *)&dst_addr, + EVL_NEIGH_PERMANENT); + if (ret) + error(1, -ret, "evl_net_solicit()"); + + close(s); + + /* + * Get a raw socket with out-of-band capabilities. + */ + s = socket(AF_PACKET, SOCK_RAW | SOCK_OOB, 0); + if (s < 0) + error(1, errno, "cannot create raw packet socket"); + + /* + * Get ifindex + */ + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_name, netif, IFNAMSIZ - 1); + ret = ioctl(s, SIOCGIFINDEX, &ifr); + if (ret < 0) + error(1, errno, "ioctl(SIOCGIFINDEX)"); + + ifindex = ifr.ifr_ifindex; + + /* + * Get local mac address + */ + ret = ioctl(s, SIOCGIFHWADDR, &ifr); + if (ret < 0) + error(1, errno, "ioctl(SIOCGIFHWADDR)"); + + src_hwaddr = ifr.ifr_hwaddr; + + /* + * Get the local ip address + */ + ret = ioctl(s, SIOCGIFADDR, &ifr); + if (ret < 0) + error(1, errno, "ioctl(SIOCGIFADDR)"); + + src_addr.sin_family = AF_INET; + src_addr.sin_port = htons(0); + src_addr.sin_addr.s_addr = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr; + + /* + * Get the destination mac address + */ + memset(&arp_request, 0, sizeof(arp_request)); + ((struct sockaddr_in *)&arp_request.arp_pa)->sin_family = AF_INET; + ((struct sockaddr_in *)&arp_request.arp_pa)->sin_addr.s_addr = dst_addr.sin_addr.s_addr; + memcpy(arp_request.arp_dev, ifr.ifr_name, sizeof(arp_request.arp_dev)); + + ret = ioctl(s, SIOCGARP, &arp_request); + if (ret < 0) + error(1, errno, "ioctl(SIOCGARP)"); + + if (arp_request.arp_flags & ATF_COM) { + dst_hwaddr = arp_request.arp_ha; + } else { + error(1, 0, "ARP entry is incomplete or invalid.\n"); + } + + if (verbosity > 1) { + evl_printf("sending via %s (if%d), ip=%s, mac=%.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n", + ifr.ifr_name, ifindex, inet_ntoa(src_addr.sin_addr), + (uint8_t)src_hwaddr.sa_data[0], + (uint8_t)src_hwaddr.sa_data[1], + (uint8_t)src_hwaddr.sa_data[2], + (uint8_t)src_hwaddr.sa_data[3], + (uint8_t)src_hwaddr.sa_data[4], + (uint8_t)src_hwaddr.sa_data[5]); + evl_printf("sending to ip=%s, mac=%.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n", + inet_ntoa(dst_addr.sin_addr), + (uint8_t)dst_hwaddr.sa_data[0], + (uint8_t)dst_hwaddr.sa_data[1], + (uint8_t)dst_hwaddr.sa_data[2], + (uint8_t)dst_hwaddr.sa_data[3], + (uint8_t)dst_hwaddr.sa_data[4], + (uint8_t)dst_hwaddr.sa_data[5]); + } + + memset(&addr, 0, sizeof(addr)); + addr.sll_ifindex = ifindex; + addr.sll_family = AF_PACKET; + addr.sll_protocol = htons(ETH_P_ALL); + ret = bind(s, (struct sockaddr *)&addr, sizeof(addr)); + if (ret) + error(1, errno, "cannot bind packet socket"); + + if (verbosity) + evl_printf("listening to interface %s\n", netif); + + for (;;) { + count = build_icmp_request(o_frame, 64, + (struct in_addr *)&dst_addr.sin_addr.s_addr, + (struct in_addr *)&src_addr.sin_addr.s_addr, + (struct ether_addr *)dst_hwaddr.sa_data, + (struct ether_addr *)src_hwaddr.sa_data, + id, sequence); + + iov.iov_base = o_frame; + iov.iov_len = count; + msghdr.msg_iov = &iov; + msghdr.msg_iovlen = 1; + msghdr.msg_control = NULL; + msghdr.msg_controllen = 0; + msghdr.msg_name = NULL; + msghdr.msg_namelen = 0; + msghdr.msg_flags = 0; + if (verbosity > 1) + evl_printf(" .. ICMP request sent: %zd\n", count); + + evl_read_clock(EVL_CLOCK_MONOTONIC, &ts_ping_tx); + count = oob_sendmsg(s, &msghdr, NULL, 0); + if (count < 0) + error(1, errno, "oob_sendmsg() failed"); + + iov.iov_base = i_frame; + iov.iov_len = sizeof(i_frame); + msghdr.msg_name = &addr; + msghdr.msg_namelen = sizeof(addr); + + rx: + evl_read_clock(EVL_CLOCK_MONOTONIC, &ts_timeout); + ts_timeout.tv_sec += 1; + count = oob_recvmsg(s, &msghdr, &ts_timeout, 0); + evl_read_clock(EVL_CLOCK_MONOTONIC, &ts_ping_rx); + if (count < 0) { + if (errno != ETIMEDOUT) { + error(1, errno, "oob_recvmsg() failed"); + } else { + evl_printf(" .. ICMP timeout!\n"); + goto next; + } + } + + if (check_icmp_reply(i_frame, count, id, sequence) != 0) { + evl_printf("icmp check failed, probably intercepted other package, retry rx\n"); + goto rx; + } + + if (verbosity > 1) + evl_printf(" .. ICMP reply recv: %zd\n", count); + if (verbosity) + evl_printf("[%d] count=%zd, proto=%#hx, ifindex=%d, type=%u, halen=%u, " + "mac=%.2x:%.2x:%.2x:%.2x:%.2x:%.2x rtt=%.1fus\n", + sequence, count, ntohs(addr.sll_protocol), + addr.sll_ifindex, addr.sll_pkttype, + addr.sll_halen, (uint8_t)addr.sll_addr[0], + (uint8_t)addr.sll_addr[1], + (uint8_t)addr.sll_addr[2], + (uint8_t)addr.sll_addr[3], + (uint8_t)addr.sll_addr[4], + (uint8_t)addr.sll_addr[5], + (ts_ping_rx.tv_sec - ts_ping_tx.tv_sec) * 1000000.0 + + (ts_ping_rx.tv_nsec - ts_ping_tx.tv_nsec) / 1000.0); +next: + evl_usleep(delay); + sequence++; + } + + return 0; +} -- 2.47.3 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH 1/1] tidbits: net-ping: add ping tidbit using raw socket 2026-06-28 15:39 ` [PATCH 1/1] " Hannes Diethelm @ 2026-07-05 14:57 ` Philippe Gerum 2026-07-05 15:27 ` Hannes Diethelm 0 siblings, 1 reply; 10+ messages in thread From: Philippe Gerum @ 2026-07-05 14:57 UTC (permalink / raw) To: Hannes Diethelm; +Cc: xenomai Hannes Diethelm <hannes.diethelm@gmail.com> writes: > This tidbit allows to ping any host and measure the response time. > > Signed-off-by: Hannes Diethelm <hannes.diethelm@gmail.com> > --- > tidbits/meson.build | 6 + > tidbits/oob-net-ping.c | 480 +++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 486 insertions(+) > create mode 100644 tidbits/oob-net-ping.c > Thanks. We need this to build on 32bit systems: --- a/tidbits/oob-net-ping.c +++ b/tidbits/oob-net-ping.c @@ -215,7 +215,7 @@ static size_t build_icmp_request(uint8_t *o_frame, size_t icmplen, icmphdr->checksum = cksum; if (verbosity > 1) { - evl_printf("ip_len=%zd, icmp_len=%zd, ip_len=%d, datalen=%ld\n", + evl_printf("ip_len=%zd, icmp_len=%zd, ip_len=%d, datalen=%zu\n", sizeof(*iphdr), sizeof(struct icmphdr), ntohs(iphdr->ip_len), datalen); print_ip_header(iphdr); What about turning this code into the (currently missing) 'evl-ping' utility? I believe it is of general interest to any user. -- Philippe. ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/1] tidbits: net-ping: add ping tidbit using raw socket 2026-07-05 14:57 ` Philippe Gerum @ 2026-07-05 15:27 ` Hannes Diethelm 2026-07-05 16:52 ` Philippe Gerum 0 siblings, 1 reply; 10+ messages in thread From: Hannes Diethelm @ 2026-07-05 15:27 UTC (permalink / raw) To: Philippe Gerum; +Cc: xenomai Am 05.07.26 um 16:57 schrieb Philippe Gerum: > Hannes Diethelm <hannes.diethelm@gmail.com> writes: > >> This tidbit allows to ping any host and measure the response time. >> >> Signed-off-by: Hannes Diethelm <hannes.diethelm@gmail.com> >> --- >> tidbits/meson.build | 6 + >> tidbits/oob-net-ping.c | 480 +++++++++++++++++++++++++++++++++++++++++ >> 2 files changed, 486 insertions(+) >> create mode 100644 tidbits/oob-net-ping.c >> > > Thanks. We need this to build on 32bit systems: > > --- a/tidbits/oob-net-ping.c > +++ b/tidbits/oob-net-ping.c > @@ -215,7 +215,7 @@ static size_t build_icmp_request(uint8_t *o_frame, size_t icmplen, > icmphdr->checksum = cksum; > > if (verbosity > 1) { > - evl_printf("ip_len=%zd, icmp_len=%zd, ip_len=%d, datalen=%ld\n", > + evl_printf("ip_len=%zd, icmp_len=%zd, ip_len=%d, datalen=%zu\n", > sizeof(*iphdr), sizeof(struct icmphdr), > ntohs(iphdr->ip_len), datalen); > print_ip_header(iphdr); > > What about turning this code into the (currently missing) 'evl-ping' > utility? I believe it is of general interest to any user. > Thanks, I will fix this. Why not. So I would move the code in the tools place and rename it? Meanwhile, I was continuing work, so statistics are available, ping style. oob-ping: 2 packets transmitted, 2 received, 0% packet loss, time 1633ms rtt min/avg/max/mdev = 226.8/248.3/269.9/21.6 us ping: 3 packets transmitted, 3 received, 0% packet loss, time 2030ms rtt min/avg/max/mdev = 0.118/0.142/0.159/0.017 ms The only difference is, that I use us instead of ms. That could confuse some users. What do you think, stay at us or use ms? BTW: This is in a VM, that's the reason for the bad timing. ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/1] tidbits: net-ping: add ping tidbit using raw socket 2026-07-05 15:27 ` Hannes Diethelm @ 2026-07-05 16:52 ` Philippe Gerum 0 siblings, 0 replies; 10+ messages in thread From: Philippe Gerum @ 2026-07-05 16:52 UTC (permalink / raw) To: Hannes Diethelm; +Cc: xenomai Hannes Diethelm <hannes.diethelm@gmail.com> writes: > Am 05.07.26 um 16:57 schrieb Philippe Gerum: >> Hannes Diethelm <hannes.diethelm@gmail.com> writes: >> >>> This tidbit allows to ping any host and measure the response time. >>> >>> Signed-off-by: Hannes Diethelm <hannes.diethelm@gmail.com> >>> --- >>> tidbits/meson.build | 6 + >>> tidbits/oob-net-ping.c | 480 +++++++++++++++++++++++++++++++++++++++++ >>> 2 files changed, 486 insertions(+) >>> create mode 100644 tidbits/oob-net-ping.c >>> >> Thanks. We need this to build on 32bit systems: >> --- a/tidbits/oob-net-ping.c >> +++ b/tidbits/oob-net-ping.c >> @@ -215,7 +215,7 @@ static size_t build_icmp_request(uint8_t *o_frame, size_t icmplen, >> icmphdr->checksum = cksum; >> if (verbosity > 1) { >> - evl_printf("ip_len=%zd, icmp_len=%zd, ip_len=%d, datalen=%ld\n", >> + evl_printf("ip_len=%zd, icmp_len=%zd, ip_len=%d, datalen=%zu\n", >> sizeof(*iphdr), sizeof(struct icmphdr), >> ntohs(iphdr->ip_len), datalen); >> print_ip_header(iphdr); >> What about turning this code into the (currently missing) 'evl-ping' >> utility? I believe it is of general interest to any user. >> > > Thanks, I will fix this. > > Why not. So I would move the code in the tools place and rename it? Meanwhile, > I was continuing work, so statistics are available, ping style. > > oob-ping: > 2 packets transmitted, 2 received, 0% packet loss, time 1633ms > rtt min/avg/max/mdev = 226.8/248.3/269.9/21.6 us > Yep, that's nice. We would make good use of this program as a standard evl utility. > ping: > 3 packets transmitted, 3 received, 0% packet loss, time 2030ms > rtt min/avg/max/mdev = 0.118/0.142/0.159/0.017 ms > > The only difference is, that I use us instead of ms. That could confuse some users. > What do you think, stay at us or use ms? > I would stick with the standard ping convention (ms), maybe adding an option to display delays in microseconds. > BTW: This is in a VM, that's the reason for the bad timing. Noted. -- Philippe. ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 0/1] tidbits: net-ping: add ping tidbit using raw socket 2026-06-28 15:39 [PATCH 0/1] tidbits: net-ping: add ping tidbit using raw socket Hannes Diethelm 2026-06-28 15:39 ` [PATCH 1/1] " Hannes Diethelm @ 2026-07-05 15:01 ` Philippe Gerum 2026-07-05 15:21 ` Hannes Diethelm 1 sibling, 1 reply; 10+ messages in thread From: Philippe Gerum @ 2026-07-05 15:01 UTC (permalink / raw) To: Hannes Diethelm; +Cc: xenomai Hannes Diethelm <hannes.diethelm@gmail.com> writes: > This patch is the result from experimenting with evl networking. I use it to do basic > connection tests from the out of band network and check the timing. > > It is a bit complex due to evl doesn't support IPPROTO_ICMP sockets. > > Using the in-band network stack, you can use: sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP); > and then only send the icmp part of the message. However, such a support is not really needed, > it works fine without. > This said, we have an ICMP protocol module in the evl stack since recently, which only responds to ICMP_ECHO requests ATM, directly from kernel space. Extending IPPROTO_ICMP by implementing the oob_sendmsg() handler for it there has become an option. -- Philippe. ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 0/1] tidbits: net-ping: add ping tidbit using raw socket 2026-07-05 15:01 ` [PATCH 0/1] " Philippe Gerum @ 2026-07-05 15:21 ` Hannes Diethelm 2026-07-05 16:49 ` Philippe Gerum 0 siblings, 1 reply; 10+ messages in thread From: Hannes Diethelm @ 2026-07-05 15:21 UTC (permalink / raw) To: Philippe Gerum; +Cc: xenomai Am 05.07.26 um 17:01 schrieb Philippe Gerum: > Hannes Diethelm <hannes.diethelm@gmail.com> writes: > >> This patch is the result from experimenting with evl networking. I use it to do basic >> connection tests from the out of band network and check the timing. >> >> It is a bit complex due to evl doesn't support IPPROTO_ICMP sockets. >> >> Using the in-band network stack, you can use: sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP); >> and then only send the icmp part of the message. However, such a support is not really needed, >> it works fine without. >> > > This said, we have an ICMP protocol module in the evl stack since > recently, which only responds to ICMP_ECHO requests ATM, directly from > kernel space. Extending IPPROTO_ICMP by implementing the oob_sendmsg() > handler for it there has become an option. > That would make the ping tool way simpler. I can also wait until this is available and create a new patch. It's mostly done just to figure out that IPPROTO_ICMP is not available. ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 0/1] tidbits: net-ping: add ping tidbit using raw socket 2026-07-05 15:21 ` Hannes Diethelm @ 2026-07-05 16:49 ` Philippe Gerum 2026-07-05 22:17 ` Hannes Diethelm 0 siblings, 1 reply; 10+ messages in thread From: Philippe Gerum @ 2026-07-05 16:49 UTC (permalink / raw) To: Hannes Diethelm; +Cc: xenomai Hannes Diethelm <hannes.diethelm@gmail.com> writes: > Am 05.07.26 um 17:01 schrieb Philippe Gerum: >> Hannes Diethelm <hannes.diethelm@gmail.com> writes: >> >>> This patch is the result from experimenting with evl networking. I use it to do basic >>> connection tests from the out of band network and check the timing. >>> >>> It is a bit complex due to evl doesn't support IPPROTO_ICMP sockets. >>> >>> Using the in-band network stack, you can use: sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP); >>> and then only send the icmp part of the message. However, such a support is not really needed, >>> it works fine without. >>> >> This said, we have an ICMP protocol module in the evl stack since >> recently, which only responds to ICMP_ECHO requests ATM, directly from >> kernel space. Extending IPPROTO_ICMP by implementing the oob_sendmsg() >> handler for it there has become an option. >> > > That would make the ping tool way simpler. I can also wait until this is available and > create a new patch. It's mostly done just to figure out that IPPROTO_ICMP is not available. Ok, I believe having IPPROTO_ICMP would be the best approach. I'll let you know when this is available. -- Philippe. ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 0/1] tidbits: net-ping: add ping tidbit using raw socket 2026-07-05 16:49 ` Philippe Gerum @ 2026-07-05 22:17 ` Hannes Diethelm 2026-07-05 23:57 ` Hannes Diethelm 0 siblings, 1 reply; 10+ messages in thread From: Hannes Diethelm @ 2026-07-05 22:17 UTC (permalink / raw) To: Philippe Gerum; +Cc: xenomai [-- Attachment #1: Type: text/plain, Size: 3146 bytes --] Am 05.07.26 um 18:49 schrieb Philippe Gerum: > Hannes Diethelm <hannes.diethelm@gmail.com> writes: > >> Am 05.07.26 um 17:01 schrieb Philippe Gerum: >>> Hannes Diethelm <hannes.diethelm@gmail.com> writes: >>> >>>> This patch is the result from experimenting with evl networking. I use it to do basic >>>> connection tests from the out of band network and check the timing. >>>> >>>> It is a bit complex due to evl doesn't support IPPROTO_ICMP sockets. >>>> >>>> Using the in-band network stack, you can use: sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP); >>>> and then only send the icmp part of the message. However, such a support is not really needed, >>>> it works fine without. >>>> >>> This said, we have an ICMP protocol module in the evl stack since >>> recently, which only responds to ICMP_ECHO requests ATM, directly from >>> kernel space. Extending IPPROTO_ICMP by implementing the oob_sendmsg() >>> handler for it there has become an option. >>> >> >> That would make the ping tool way simpler. I can also wait until this is available and >> create a new patch. It's mostly done just to figure out that IPPROTO_ICMP is not available. > > Ok, I believe having IPPROTO_ICMP would be the best approach. I'll > let you know when this is available. > Meanwhile, I changed to ms and corrected the "%zu". Attached 4 variants: oob-net-ping.c - The variant from the patch, improved oob-net-ping-nonraw.c - OOB with IPPROTO_ICMP (Not tested due to obvious reasons) ping-raw.c - POSIX raw ping-nonraw.c - POSIX with IPPROTO_ICMP This might help you debug the IPPROTO_ICMP implementation. While sometimes having issues with EVL, I created also POSIX variants so see if it is my issue. I can create also a patch if you prefer for one of the two OOB variants. There where issues with -O3 in ip_checksum(). With -O0, it works. The only difference I see between working and faulty is that with 16bit-aligned (raw) it fails and with 32bit-aligned (nonraw) it works. -O3 debugging doesn't really work, in assembly its nearly unreadable with -O3 and as soon as I add a printf() in the while loop, the checksum is good. I have no clue might be UB or a compiler bug. Took me some time to debug. I have gcc (Debian 14.2.0-19) 14.2.0 Of course, as soon as I create a test program with only ip_checksum() and exactly the same data, it works also, just combined with the code, it breaks down. This version creates faulty check-sums: static uint16_t ip_checksum(void *buf, int len) { uint16_t *p = buf; /* buf is assumed to be 16bit-aligned. */ uint32_t sum = 0; int count = len; while (count > 1) { sum += *p++; count -= sizeof(*p); } if (count > 0) sum += *(uint8_t *)p; while (sum >> 16) sum = (sum & 0xffff) + (sum >> 16); return ~sum & 0xffff; } While this works: static uint16_t ip_checksum(void *buf, int len) { void *p = buf; uint32_t sum = 0; int count = len; while (count > 1) { sum += (uint16_t)(*(uint8_t *)p) + ((uint16_t)(*(uint8_t *)(p + 1)) << 8); p += 2; count -= 2; } if (count > 0) sum += *(uint8_t *)p; while (sum >> 16) sum = (sum & 0xffff) + (sum >> 16); return ~sum & 0xffff; } [-- Attachment #2: ping-variants.tar.xz --] [-- Type: application/x-xz, Size: 5188 bytes --] ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 0/1] tidbits: net-ping: add ping tidbit using raw socket 2026-07-05 22:17 ` Hannes Diethelm @ 2026-07-05 23:57 ` Hannes Diethelm 0 siblings, 0 replies; 10+ messages in thread From: Hannes Diethelm @ 2026-07-05 23:57 UTC (permalink / raw) To: Philippe Gerum; +Cc: xenomai Am 06.07.26 um 00:17 schrieb Hannes Diethelm: > Am 05.07.26 um 18:49 schrieb Philippe Gerum: >> Hannes Diethelm <hannes.diethelm@gmail.com> writes: >> >>> Am 05.07.26 um 17:01 schrieb Philippe Gerum: >>>> Hannes Diethelm <hannes.diethelm@gmail.com> writes: >>>> >>>>> This patch is the result from experimenting with evl networking. I >>>>> use it to do basic >>>>> connection tests from the out of band network and check the timing. >>>>> >>>>> It is a bit complex due to evl doesn't support IPPROTO_ICMP sockets. >>>>> >>>>> Using the in-band network stack, you can use: sockfd = >>>>> socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP); >>>>> and then only send the icmp part of the message. However, such a >>>>> support is not really needed, >>>>> it works fine without. >>>>> >>>> This said, we have an ICMP protocol module in the evl stack since >>>> recently, which only responds to ICMP_ECHO requests ATM, directly from >>>> kernel space. Extending IPPROTO_ICMP by implementing the oob_sendmsg() >>>> handler for it there has become an option. >>>> >>> >>> That would make the ping tool way simpler. I can also wait until this >>> is available and >>> create a new patch. It's mostly done just to figure out that >>> IPPROTO_ICMP is not available. >> >> Ok, I believe having IPPROTO_ICMP would be the best approach. I'll >> let you know when this is available. >> > > Meanwhile, I changed to ms and corrected the "%zu". Attached 4 variants: > oob-net-ping.c - The variant from the patch, improved > oob-net-ping-nonraw.c - OOB with IPPROTO_ICMP (Not tested due to obvious > reasons) > ping-raw.c - POSIX raw > ping-nonraw.c - POSIX with IPPROTO_ICMP > > This might help you debug the IPPROTO_ICMP implementation. > > While sometimes having issues with EVL, I created also POSIX variants > so see if it is my issue. > > I can create also a patch if you prefer for one of the two OOB variants. > > There where issues with -O3 in ip_checksum(). With -O0, it works. > > The only difference I see between working and faulty is that with 16bit- > aligned (raw) > it fails and with 32bit-aligned (nonraw) it works. -O3 debugging doesn't > really work, in assembly > its nearly unreadable with -O3 and as soon as I add a printf() in the > while loop, > the checksum is good. I have no clue might be UB or a compiler bug. Took > me some time to debug. > I have gcc (Debian 14.2.0-19) 14.2.0 > > Of course, as soon as I create a test program with only ip_checksum() > and exactly the > same data, it works also, just combined with the code, it breaks down. > > This version creates faulty check-sums: > static uint16_t ip_checksum(void *buf, int len) > { > uint16_t *p = buf; /* buf is assumed to be 16bit-aligned. */ > uint32_t sum = 0; > int count = len; > > while (count > 1) { > sum += *p++; > count -= sizeof(*p); > } > > if (count > 0) > sum += *(uint8_t *)p; > > while (sum >> 16) > sum = (sum & 0xffff) + (sum >> 16); > > return ~sum & 0xffff; > } > > While this works: > static uint16_t ip_checksum(void *buf, int len) > { > void *p = buf; > uint32_t sum = 0; > int count = len; > > while (count > 1) { > sum += (uint16_t)(*(uint8_t *)p) + ((uint16_t)(*(uint8_t *)(p + > 1)) << 8); > p += 2; > count -= 2; > } > > if (count > 0) > sum += *(uint8_t *)p; > > while (sum >> 16) > sum = (sum & 0xffff) + (sum >> 16); > > return ~sum & 0xffff; > } Disregard the issue with ip_checksum(). -fsanitize=undefined gave the clue. It was indeed UB, just not where I expected it. Fixing it right now: ping-raw.c:206:16: runtime error: member access within misaligned address 0x7f4bbbd00a3e for type 'struct ip', which requires 4 byte alignment 0x7f4bbbd00a3e: note: pointer points here 6f 6a 08 00 45 00 00 54 c3 84 40 00 40 01 00 00 c0 a8 7a f6 c0 a8 7a 01 00 00 00 00 00 00 00 00 ^ ^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2026-07-05 23:57 UTC | newest] Thread overview: 10+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-06-28 15:39 [PATCH 0/1] tidbits: net-ping: add ping tidbit using raw socket Hannes Diethelm 2026-06-28 15:39 ` [PATCH 1/1] " Hannes Diethelm 2026-07-05 14:57 ` Philippe Gerum 2026-07-05 15:27 ` Hannes Diethelm 2026-07-05 16:52 ` Philippe Gerum 2026-07-05 15:01 ` [PATCH 0/1] " Philippe Gerum 2026-07-05 15:21 ` Hannes Diethelm 2026-07-05 16:49 ` Philippe Gerum 2026-07-05 22:17 ` Hannes Diethelm 2026-07-05 23:57 ` Hannes Diethelm
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.