From: Gilles Chanteperdrix <gilles.chanteperd...@xenomai.org>

Signed-off-by: Philippe Gerum <r...@xenomai.org>
---
 configure.ac                   |   1 +
 demo/Makefile.am               |   2 +-
 demo/net/Makefile.am           |  78 ++++++++
 demo/net/mcast-receiver.c      | 205 ++++++++++++++++++++
 demo/net/mcast-sender.c        | 151 +++++++++++++++
 demo/net/raw-ethernet.c        | 100 ++++++++++
 demo/net/rtt-mcast-measure.c   | 210 ++++++++++++++++++++
 demo/net/rtt-mcast-responder.c | 109 +++++++++++
 demo/net/rtt-responder.c       | 193 +++++++++++++++++++
 demo/net/rtt-sender.c          | 341 +++++++++++++++++++++++++++++++++
 demo/net/rttcp-client.c        | 212 ++++++++++++++++++++
 demo/net/rttcp-server.c        | 181 +++++++++++++++++
 demo/net/udp-send.c            | 136 +++++++++++++
 13 files changed, 1918 insertions(+), 1 deletion(-)
 create mode 100644 demo/net/Makefile.am
 create mode 100644 demo/net/mcast-receiver.c
 create mode 100644 demo/net/mcast-sender.c
 create mode 100644 demo/net/raw-ethernet.c
 create mode 100644 demo/net/rtt-mcast-measure.c
 create mode 100644 demo/net/rtt-mcast-responder.c
 create mode 100644 demo/net/rtt-responder.c
 create mode 100644 demo/net/rtt-sender.c
 create mode 100644 demo/net/rttcp-client.c
 create mode 100644 demo/net/rttcp-server.c
 create mode 100644 demo/net/udp-send.c

diff --git a/configure.ac b/configure.ac
index bd5fd5ba9..8fd322d54 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1010,6 +1010,7 @@ AC_CONFIG_FILES([ \
        demo/posix/cobalt/Makefile \
        demo/alchemy/Makefile \
        demo/alchemy/cobalt/Makefile \
+       demo/net/Makefile \
        include/Makefile \
        include/cobalt/uapi/Makefile \
        include/cobalt/uapi/asm-generic/Makefile \
diff --git a/demo/Makefile.am b/demo/Makefile.am
index fe5107c25..2839d074b 100644
--- a/demo/Makefile.am
+++ b/demo/Makefile.am
@@ -1,2 +1,2 @@
 
-SUBDIRS = posix alchemy
+SUBDIRS = posix alchemy net
diff --git a/demo/net/Makefile.am b/demo/net/Makefile.am
new file mode 100644
index 000000000..f9755bace
--- /dev/null
+++ b/demo/net/Makefile.am
@@ -0,0 +1,78 @@
+demodir = @XENO_DEMO_DIR@
+
+CCLD = $(top_srcdir)/scripts/wrap-link.sh $(CC)
+
+demo_PROGRAMS =        \
+       mcast-receiver  \
+       mcast-sender    \
+       raw-ethernet    \
+       rttcp-client    \
+       rttcp-server    \
+       rtt-mcast-measure       \
+       rtt-mcast-responder     \
+       rtt-responder   \
+       rtt-sender      \
+       udp-send
+
+cppflags =                     \
+       $(XENO_USER_CFLAGS)     \
+       -I$(top_srcdir)/include
+
+ldflags = @XENO_AUTOINIT_LDFLAGS@ $(XENO_POSIX_WRAPPERS)
+
+ldadd =                                        \
+        @XENO_CORE_LDADD@                      \
+        @XENO_USER_LDADD@                      \
+       -lpthread -lrt
+
+mcast_receiver_SOURCES = mcast-receiver.c
+mcast_receiver_CPPFLAGS = $(cppflags)
+mcast_receiver_LDFLAGS = $(ldflags)
+mcast_receiver_LDADD = $(ldadd)
+
+mcast_sender_SOURCES = mcast-sender.c
+mcast_sender_CPPFLAGS = $(cppflags)
+mcast_sender_LDFLAGS = $(ldflags)
+mcast_sender_LDADD = $(ldadd)
+
+raw_ethernet_SOURCES = raw-ethernet.c
+raw_ethernet_CPPFLAGS = $(cppflags)
+raw_ethernet_LDFLAGS = $(ldflags)
+raw_ethernet_LDADD = $(ldadd)
+
+rttcp_client_SOURCES = rttcp-client.c
+rttcp_client_CPPFLAGS = $(cppflags)
+rttcp_client_LDFLAGS = $(ldflags)
+rttcp_client_LDADD = $(ldadd)
+
+rttcp_server_SOURCES = rttcp-server.c
+rttcp_server_CPPFLAGS = $(cppflags)
+rttcp_server_LDFLAGS = $(ldflags)
+rttcp_server_LDADD = $(ldadd)
+
+rtt_mcast_measure_SOURCES = rtt-mcast-measure.c
+rtt_mcast_measure_CPPFLAGS = $(cppflags)
+rtt_mcast_measure_LDFLAGS = $(ldflags)
+rtt_mcast_measure_LDADD = ../../lib/alchemy/libalchemy.la      \
+               ../../lib/copperplate/libcopperplate.la         \
+               $(ldadd)
+
+rtt_mcast_responder_SOURCES = rtt-mcast-responder.c
+rtt_mcast_responder_CPPFLAGS = $(cppflags)
+rtt_mcast_responder_LDFLAGS = $(ldflags)
+rtt_mcast_responder_LDADD = $(ldadd)
+
+rtt_responder_SOURCES = rtt-responder.c
+rtt_responder_CPPFLAGS = $(cppflags)
+rtt_responder_LDFLAGS = $(ldflags)
+rtt_responder_LDADD = $(ldadd)
+
+rtt_sender_SOURCES = rtt-sender.c
+rtt_sender_CPPFLAGS = $(cppflags)
+rtt_sender_LDFLAGS = $(ldflags)
+rtt_sender_LDADD = $(ldadd)
+
+udp_send_SOURCES = udp-send.c
+udp_send_CPPFLAGS = $(cppflags)
+udp_send_LDFLAGS = $(ldflags)
+udp_send_LDADD = $(ldadd)
diff --git a/demo/net/mcast-receiver.c b/demo/net/mcast-receiver.c
new file mode 100644
index 000000000..a121d0d32
--- /dev/null
+++ b/demo/net/mcast-receiver.c
@@ -0,0 +1,205 @@
+/*
+ * listener.c -- joins a multicast group and echoes all data it receives from
+ *             the group to its stdout...
+ *
+ * Antony Courtney,    25/11/94
+ * Modified by: Frédéric Bastien (25/03/04)
+ * to compile without warning and work correctly
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <time.h>
+#include <string.h>
+#include <sched.h>
+#include <pthread.h>
+#include <errno.h>
+
+#include <sys/ioctl.h>
+#include <linux/sockios.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <signal.h>
+
+#include <execinfo.h>
+
+#define HELLO_PORT 12345
+#define HELLO_GROUP "225.0.0.37"
+#define MSGBUFSIZE 256
+
+#define TO_US(ns) \
+    (ns) / 1000, (ns) % 1000
+
+static void check(const char *file, int line, const char *service, int status, 
int err)
+{
+       if (status >= 0)
+               return;
+
+       pthread_setmode_np(PTHREAD_WARNSW, 0, NULL);
+       __real_fprintf(stderr, "%s:%d: %s: %s\n", file, line, service, 
strerror(err));
+
+       exit(EXIT_FAILURE);
+}
+
+#define check_pthread(expr)                                            \
+    ({                                                                 \
+           int _status = (expr);                                       \
+           check(__FILE__, __LINE__, #expr, -_status, _status);        \
+    })
+
+#define check_unix(expr)                                       \
+    ({                                                         \
+           int _status = (expr);                               \
+           check(__FILE__, __LINE__, #expr, _status, errno);   \
+    })
+
+static const char *reason_str[] = {
+       [SIGDEBUG_UNDEFINED] = "received SIGDEBUG for unknown reason",
+       [SIGDEBUG_MIGRATE_SIGNAL] = "received signal",
+       [SIGDEBUG_MIGRATE_SYSCALL] = "invoked syscall",
+       [SIGDEBUG_MIGRATE_FAULT] = "triggered fault",
+       [SIGDEBUG_MIGRATE_PRIOINV] = "owner is not in real-time mode",
+       [SIGDEBUG_NOMLOCK] = "process memory not locked",
+       [SIGDEBUG_WATCHDOG] = "watchdog triggered (period too short?)",
+       [SIGDEBUG_LOCK_BREAK] = "scheduler lock break",
+       [SIGDEBUG_MUTEX_SLEEP] = "caller sleeps with mutex",
+};
+
+static void sigdebug(int sig, siginfo_t *si, void *context)
+{
+       const char fmt[] = "%s, aborting.\n";
+       unsigned int reason = sigdebug_reason(si);
+       int n __attribute__ ((unused));
+       static char buffer[256];
+       void *bt[32];
+       int nentries;
+
+       if (reason >= sizeof(reason_str) / sizeof(reason_str[0]))
+               reason = SIGDEBUG_UNDEFINED;
+
+       n = snprintf(buffer, sizeof(buffer), fmt, reason_str[reason]);
+       n = write(STDERR_FILENO, buffer, n);
+       nentries = backtrace(bt, sizeof(bt) / sizeof(bt[0]));
+       backtrace_symbols_fd(bt, nentries, STDERR_FILENO);
+
+       signal(sig, SIG_DFL);
+       kill(getpid(), sig);
+}
+
+int main(int argc, char *argv[])
+{
+       unsigned long long min, max, sum, count, gmin, gmax, gsum, gcount;
+       struct sigaction sa __attribute__((unused));
+       struct sockaddr_in addr;
+       int fd, err;
+       struct ip_mreq mreq;
+       socklen_t addrlen;
+       struct timespec last_print;
+       struct sched_param sparm;
+       char msgbuf[MSGBUFSIZE];
+       bool first = true;
+
+       if (argc != 2) {
+               fprintf(stderr, "Local ip address expected as first and "
+                       "only argument\n");
+               exit(EXIT_FAILURE);
+       }
+
+       sparm.sched_priority = 97;
+       check_pthread(pthread_setschedparam(pthread_self(),
+                                                   SCHED_FIFO, &sparm));
+
+       check_unix(fd = socket(AF_INET,SOCK_DGRAM,0));
+
+       sigemptyset(&sa.sa_mask);
+       sa.sa_sigaction = sigdebug;
+       sa.sa_flags = SA_SIGINFO;
+       check_unix(sigaction(SIGDEBUG, &sa, NULL));
+
+       memset(&addr,0,sizeof(addr));
+       addr.sin_family = AF_INET;
+       addr.sin_addr.s_addr = inet_addr(argv[1]);
+       addr.sin_port = htons(HELLO_PORT);
+
+       check_unix(bind(fd, (struct sockaddr *)&addr,sizeof(addr)));
+
+       mreq.imr_multiaddr.s_addr = inet_addr(HELLO_GROUP);
+       mreq.imr_interface.s_addr = addr.sin_addr.s_addr;
+       check_unix(setsockopt(fd,IPPROTO_IP,
+                               IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)));
+
+       gmin = min = ~0ULL;
+       gmax = max = 0;
+       gsum = sum = 0;
+       gcount = count = 0;
+
+       check_pthread(pthread_setmode_np(0, PTHREAD_WARNSW, NULL));
+
+       check_unix(clock_gettime(CLOCK_REALTIME, &last_print));
+
+       while (1) {
+               struct timespec now;
+               struct timeval packet;
+               unsigned long long diff;
+
+               addrlen = sizeof(addr);
+               check_unix(recvfrom(fd, msgbuf, sizeof(msgbuf), 0,
+                                       (struct sockaddr *)&addr, &addrlen));
+               check_unix(clock_gettime(CLOCK_REALTIME, &now));
+
+               err = ioctl(fd, SIOCGSTAMP, &packet);
+               if (err < 0) {
+                       perror("ioctl");
+                       exit(1);
+               }
+
+               if (first) {
+                       first = false;
+                       continue;
+               }
+
+               diff = now.tv_sec * 1000000000ULL + now.tv_nsec -
+                       (packet.tv_sec * 1000000000ULL
+                       + packet.tv_usec * 1000ULL);
+               if ((long long)diff < 0)
+                       printf("%lu.%09lu - %lu.%06lu\n",
+                               now.tv_sec, now.tv_nsec,
+                               packet.tv_sec, packet.tv_usec);
+
+               if (diff < min)
+                       min = diff;
+               if (diff > max)
+                       max = diff;
+               sum += diff;
+               ++count;
+
+               diff = now.tv_sec * 1000000000ULL + now.tv_nsec -
+                       (last_print.tv_sec * 1000000000ULL
+                       + last_print.tv_nsec);
+               if (diff < 1000000000)
+                       continue;
+
+               if (min < gmin)
+                       gmin = min;
+               if (max > gmax)
+                       gmax = max;
+               gsum += sum;
+               gcount += count;
+
+               printf("%g pps, %Lu.%03Lu %Lu.%03Lu %Lu.%03Lu "
+                       "| %Lu.%03Lu %Lu.%03Lu %Lu.%03Lu\n",
+                       count / (diff / 1000000000.0),
+                       TO_US(min), TO_US(sum / count), TO_US(max),
+                       TO_US(gmin), TO_US(gsum / gcount), TO_US(gmax));
+
+               min = ~0ULL;
+               max = 0;
+               sum = 0;
+               count = 0;
+               last_print = now;
+       }
+}
diff --git a/demo/net/mcast-sender.c b/demo/net/mcast-sender.c
new file mode 100644
index 000000000..3e4a083f9
--- /dev/null
+++ b/demo/net/mcast-sender.c
@@ -0,0 +1,151 @@
+/*
+ * sender.c -- multicasts "hello, world!" to a multicast group once a second
+ *
+ * Antony Courtney,    25/11/94
+ */
+
+#include <time.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sched.h>
+#include <pthread.h>
+#include <errno.h>
+#include <signal.h>
+#include <execinfo.h>
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+
+#define HELLO_PORT 12345
+#define HELLO_GROUP "225.0.0.37"
+
+static void check(const char *file, int line, const char *service, int status, 
int err)
+{
+       if (status >= 0)
+               return;
+
+       pthread_setmode_np(PTHREAD_WARNSW, 0, NULL);
+       __real_fprintf(stderr, "%s:%d: %s: %s\n", file, line, service, 
strerror(err));
+
+       exit(EXIT_FAILURE);
+}
+
+#define check_pthread(expr)                                            \
+    ({                                                                 \
+           int _status = (expr);                                       \
+           check(__FILE__, __LINE__, #expr, -_status, _status);        \
+    })
+
+#define check_unix(expr)                                       \
+    ({                                                         \
+           int _status = (expr);                               \
+           check(__FILE__, __LINE__, #expr, _status, errno);   \
+    })
+
+static const char *reason_str[] = {
+       [SIGDEBUG_UNDEFINED] = "received SIGDEBUG for unknown reason",
+       [SIGDEBUG_MIGRATE_SIGNAL] = "received signal",
+       [SIGDEBUG_MIGRATE_SYSCALL] = "invoked syscall",
+       [SIGDEBUG_MIGRATE_FAULT] = "triggered fault",
+       [SIGDEBUG_MIGRATE_PRIOINV] = "owner is not in real-time mode",
+       [SIGDEBUG_NOMLOCK] = "process memory not locked",
+       [SIGDEBUG_WATCHDOG] = "watchdog triggered (period too short?)",
+       [SIGDEBUG_LOCK_BREAK] = "scheduler lock break",
+       [SIGDEBUG_MUTEX_SLEEP] = "caller sleeps with mutex",
+};
+
+static void sigdebug(int sig, siginfo_t *si, void *context)
+{
+       const char fmt[] = "%s, aborting.\n";
+       unsigned int reason = sigdebug_reason(si);
+       int n __attribute__ ((unused));
+       static char buffer[256];
+       void *bt[32];
+       int nentries;
+
+       if (reason >= sizeof(reason_str) / sizeof(reason_str[0]))
+               reason = SIGDEBUG_UNDEFINED;
+
+       n = snprintf(buffer, sizeof(buffer), fmt, reason_str[reason]);
+       n = write(STDERR_FILENO, buffer, n);
+       nentries = backtrace(bt, sizeof(bt) / sizeof(bt[0]));
+       backtrace_symbols_fd(bt, nentries, STDERR_FILENO);
+
+       signal(sig, SIG_DFL);
+       kill(getpid(), sig);
+}
+
+static void usage(const char *progname)
+{
+       fprintf(stderr, "%s address frequency\n"
+               "Starts sending 'frequency' multicast UDP packets per second on"
+               " the interface\nwith IP address 'address'.\n",
+               progname);
+}
+
+int main(int argc, char *argv[])
+{
+       struct sigaction sa __attribute__((unused));
+       struct sockaddr_in addr;
+       int fd;
+       char message[] = "Hello, World!\n";
+       struct sched_param sparm;
+       struct timespec next;
+       double freq;
+       unsigned period_ns;
+
+       if (argc != 3) {
+               usage(argv[0]);
+               exit(EXIT_FAILURE);
+       }
+
+       freq = atof(argv[2]);
+       period_ns = freq ? 1000000000 / freq : 0;
+
+       check_unix(fd = socket(AF_INET,SOCK_DGRAM, 0));
+
+       addr.sin_addr.s_addr = inet_addr(argv[1]);
+
+       check_unix(setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF,
+                               &addr.sin_addr, sizeof(addr.sin_addr)));
+
+       sigemptyset(&sa.sa_mask);
+       sa.sa_sigaction = sigdebug;
+       sa.sa_flags = SA_SIGINFO;
+       check_unix(sigaction(SIGDEBUG, &sa, NULL));
+
+       memset(&addr,0,sizeof(addr));
+       addr.sin_family = AF_INET;
+       addr.sin_addr.s_addr = inet_addr(HELLO_GROUP);
+       addr.sin_port = htons(HELLO_PORT);
+
+       sparm.sched_priority = 99;
+       check_pthread(pthread_setschedparam(pthread_self(),
+                                               SCHED_FIFO, &sparm));
+
+       check_unix(clock_gettime(CLOCK_MONOTONIC, &next));
+
+       check_pthread(pthread_setmode_np(0, PTHREAD_WARNSW, NULL));
+
+       while (1) {
+               check_unix(sendto(fd,message,sizeof(message), 0,
+                                       (struct sockaddr *)&addr,
+                                       sizeof(addr)));
+
+               if (!period_ns)
+                       continue;
+
+               next.tv_nsec += period_ns;
+               if (next.tv_nsec >= 1000000000) {
+                       next.tv_nsec -= 1000000000;
+                       next.tv_sec++;
+               }
+               check_unix(clock_nanosleep(CLOCK_MONOTONIC,
+                                               TIMER_ABSTIME, &next, NULL));
+       }
+}
diff --git a/demo/net/raw-ethernet.c b/demo/net/raw-ethernet.c
new file mode 100644
index 000000000..f0448d8f6
--- /dev/null
+++ b/demo/net/raw-ethernet.c
@@ -0,0 +1,100 @@
+/***
+ *
+ *  examples/xenomai/posix/raw-ethernet.c
+ *
+ *  SOCK_RAW sender - sends out Ethernet frames via a SOCK_RAW packet socket
+ *
+ *  Copyright (C) 2006 Jan Kiszka <jan.kis...@web.de>
+ *
+ *  RTnet - real-time networking example
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <netpacket/packet.h>
+#include <net/ethernet.h>
+#include <net/if.h>
+#include <arpa/inet.h>
+
+char buffer[1514];
+int sock;
+
+
+int main(int argc, char *argv[])
+{
+    struct sched_param param = { .sched_priority = 1 };
+    ssize_t len;
+    struct sockaddr_ll addr;
+    struct ifreq ifr;
+    struct timespec delay = { 1, 0 };
+    struct ether_header *eth = (struct ether_header *)buffer;
+
+
+    if (argc < 2) {
+        printf("usage: %s <interface>\n", argv[0]);
+        return 0;
+    }
+
+    if ((sock = socket(PF_PACKET, SOCK_RAW, htons(0x1234))) < 0) {
+        perror("socket cannot be created");
+        return 1;
+    }
+
+    strncpy(ifr.ifr_name, argv[1], IFNAMSIZ-1)[IFNAMSIZ-1] = 0;
+    if (ioctl(sock, SIOCGIFINDEX, &ifr) < 0) {
+        perror("cannot get interface index");
+        close(sock);
+        return 1;
+    }
+
+    addr.sll_family   = AF_PACKET;
+    addr.sll_protocol = htons(0x1234);
+    addr.sll_ifindex  = ifr.ifr_ifindex;
+
+    if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+        perror("cannot bind to local ip/port");
+        close(sock);
+        return 1;
+    }
+
+    memset(eth->ether_dhost, 0xFF, ETH_HLEN);
+    eth->ether_type = htons(0x1234);
+
+    pthread_setschedparam(pthread_self(), SCHED_FIFO, &param);
+
+    while (1) {
+        len = send(sock, buffer, sizeof(buffer), 0);
+        if (len < 0)
+            break;
+
+        printf("Sent frame of %zd bytes\n", len);
+
+        nanosleep(&delay, NULL);
+    }
+
+    /* This call also leaves primary mode, required for socket cleanup. */
+    printf("shutting down\n");
+
+    return 0;
+}
diff --git a/demo/net/rtt-mcast-measure.c b/demo/net/rtt-mcast-measure.c
new file mode 100644
index 000000000..dc6650645
--- /dev/null
+++ b/demo/net/rtt-mcast-measure.c
@@ -0,0 +1,210 @@
+/*
+ * Multicast RTT sender. Derived from.
+ *
+ * listener.c -- joins a multicast group and echoes all data it receives from
+ *             the group to its stdout...
+ *
+ * Antony Courtney,    25/11/94
+ * Modified by: Frédéric Bastien (25/03/04)
+ * to compile without warning and work correctly
+ */
+
+#include <stdio.h>
+#include <time.h>
+#include <stdlib.h>
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <alchemy/task.h>
+#include <alchemy/timer.h>
+#include <rtdm/net.h>
+
+#define RTT_PORT 12345
+#define RTT_RECEIVER_GROUP "225.0.0.37"
+#define RTT_SENDER_GROUP "224.0.0.37"
+
+#define rt_inet_aton inet_addr
+#define do_div(ull, u) ({ unsigned long _r = ull % u; ull /= u; _r; })
+
+static int fd;
+
+static void thread(void *arg)
+{
+       unsigned long long gmin, gmax, gsum, gcount;
+       struct sockaddr_in addr, to_addr;
+       RTIME period, start;
+       int i, nbytes, err;
+       socklen_t addrlen;
+       char msgbuf[1500];
+
+       (void)arg;
+
+       memset(&to_addr, 0, sizeof(to_addr));
+       to_addr.sin_family = AF_INET;
+       to_addr.sin_addr.s_addr = rt_inet_aton(RTT_RECEIVER_GROUP);
+       to_addr.sin_port = htons(RTT_PORT);
+
+       start = 0;
+       period = 1000000;
+       err = rt_task_set_periodic(NULL, start, period);
+       if (err < 0) {
+               printf("make_periodic: %d\n", err);
+               rt_task_delete(NULL);
+       }
+
+       gmin = ~0ULL;
+       gmax = 0;
+       gsum = 0;
+       gcount = 0;
+
+       /* now just enter a receive/send loop */
+       for(;;) {
+               unsigned long long smin, smax, ssum, savg, gavg,
+                       smin_us, smin_ns, savg_us, savg_ns, smax_us, smax_ns,
+                       gmin_us, gmin_ns, gavg_us, gavg_ns, gmax_us, gmax_ns;
+
+               smin = ~0ULL;
+               smax = 0;
+               ssum = 0;
+
+               for (i = 0; i < 1000; i++) {
+                       unsigned long overruns;
+                       long long rtt;
+
+                       err = rt_task_wait_period(&overruns);
+                       if (err == -ETIMEDOUT)
+                               printf("%ld overruns\n", overruns);
+                       else if (err < 0) {
+                               printf("wait_period: %d\n", err);
+                               rt_task_delete(NULL);
+                       }
+
+                       rtt = rt_timer_read();
+                       err = sendto(fd, msgbuf, 4, 0,
+                               (struct sockaddr *)&to_addr, sizeof(to_addr));
+                       if (err < 0) {
+                               perror("sendto");
+                               rt_task_delete(NULL);
+                       }
+
+                       addrlen = sizeof(addr);
+                       nbytes = recvfrom(fd, msgbuf, sizeof(msgbuf), 0,
+                                         (struct sockaddr *)&addr, &addrlen);
+                       rtt = rt_timer_read() - rtt;
+                       if (nbytes <= 0) {
+                               perror("recvfrom");
+                               rt_task_delete(NULL);
+                       }
+
+                       if (rtt < smin)
+                               smin = rtt;
+                       if (rtt > smax)
+                               smax = rtt;
+                       ssum += rtt;
+               }
+
+               if (smin < gmin)
+                       gmin = smin;
+               if (smax > gmax)
+                       gmax = smax;
+               gsum += ssum;
+               gcount += 1000;
+
+               savg = ssum + 500;
+               do_div(savg, 1000);
+
+               gavg = gsum + gcount / 2;
+               do_div(gavg, gcount);
+
+               smin_us = smin;
+               smin_ns = do_div(smin_us, 1000);
+
+               savg_us = savg;
+               savg_ns = do_div(savg_us, 1000);
+
+               smax_us = smax;
+               smax_ns = do_div(smax_us, 1000);
+
+               gmin_us = gmin;
+               gmin_ns = do_div(gmin_us, 1000);
+
+               gavg_us = gavg;
+               gavg_ns = do_div(gavg_us, 1000);
+
+               gmax_us = gmax;
+               gmax_ns = do_div(gmax_us, 1000);
+
+               printf("%Lu.%03Lu %Lu.%03Lu %Lu.%03Lu | %Lu.%03Lu %Lu.%03Lu 
%Lu.%03Lu\n",
+                       smin_us, smin_ns, savg_us, savg_ns, smax_us, smax_ns,
+                       gmin_us, gmin_ns, gavg_us, gavg_ns, gmax_us, gmax_ns);
+       }
+}
+
+static int create_thread(RT_TASK *tid, int mode, void *arg)
+{
+       struct sockaddr_in addr;
+       struct ip_mreq mreq;
+       int err;
+
+       /* create what looks like an ordinary UDP socket */
+       fd = socket(AF_INET, SOCK_DGRAM, 0);
+       if (fd < 0) {
+               perror("socket");
+               return fd;
+       }
+
+       /* set up destination address */
+       memset(&addr, 0, sizeof(addr));
+       addr.sin_family = AF_INET;
+       if (!arg) {
+               printf("Local ip address expected as first and only 
argument\n");
+               return -EINVAL;
+       }
+
+       addr.sin_addr.s_addr = rt_inet_aton(arg);
+       addr.sin_port = htons(RTT_PORT);
+
+       /* bind to receive address */
+       err = bind(fd, (struct sockaddr *)&addr, sizeof(addr));
+       if (err < 0) {
+               perror("bind");
+               return err;
+       }
+
+       /* use setsockopt() to request that the kernel join a multicast group */
+       mreq.imr_multiaddr.s_addr = rt_inet_aton(RTT_SENDER_GROUP);
+       mreq.imr_interface.s_addr = addr.sin_addr.s_addr;
+       err = setsockopt(fd, IPPROTO_IP,
+                        IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
+       if (err < 0) {
+               perror("setsockopt");
+               rt_task_delete(NULL);
+       }
+
+       err = rt_task_spawn(tid, "rtt-mcast-measure", 8192, 99, mode,
+               thread, NULL);
+       if (err < 0)
+               printf("rt_task_spawn: %d\n", err);
+
+       return err;
+}
+
+int main(int argc, char *argv[])
+{
+       RT_TASK tid;
+       int err;
+
+       err = create_thread(&tid, T_JOINABLE, argc >= 2 ? argv[1] : NULL);
+       if (err)
+               exit(EXIT_FAILURE);
+
+       err = rt_task_join(&tid);
+       if (err < 0)
+               printf("rt_task_join: %d\n", err);
+
+       exit(EXIT_FAILURE);
+}
diff --git a/demo/net/rtt-mcast-responder.c b/demo/net/rtt-mcast-responder.c
new file mode 100644
index 000000000..b8f7dee02
--- /dev/null
+++ b/demo/net/rtt-mcast-responder.c
@@ -0,0 +1,109 @@
+/*
+ * Multicast RTT responder. Derived from.
+ *
+ * listener.c -- joins a multicast group and echoes all data it receives from
+ *             the group to its stdout...
+ *
+ * Antony Courtney,    25/11/94
+ * Modified by: Frédéric Bastien (25/03/04)
+ * to compile without warning and work correctly
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+#include <string.h>
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <pthread.h>
+#include <rtdm/net.h>
+
+
+#define RTT_PORT 12345
+#define RTT_RECEIVER_GROUP "225.0.0.37"
+#define RTT_SENDER_GROUP "224.0.0.37"
+
+int main(int argc, char *argv[])
+{
+       struct sockaddr_in addr, to_addr;
+       struct sched_param sparm;
+       int add_rtskbs = 128;
+       struct ip_mreq mreq;
+       int fd, err, nbytes;
+       socklen_t addrlen;
+       char msgbuf[1500];
+
+       sparm.sched_priority = 99;
+       err = pthread_setschedparam(pthread_self(), SCHED_FIFO, &sparm);
+       if (err) {
+               fprintf(stderr, "pthread_setschedparam: %d\n", err);
+               exit(EXIT_FAILURE);
+       }
+
+       /* create what looks like an ordinary UDP socket */
+       fd = socket(AF_INET, SOCK_DGRAM, 0);
+       if (fd < 0) {
+               perror("socket");
+               exit(EXIT_FAILURE);
+       }
+
+       /* set up destination address */
+       memset(&addr, 0, sizeof(addr));
+       addr.sin_family = AF_INET;
+       if (argc != 2) {
+               fprintf(stderr, "Local ip address expected as first and only 
argument\n");
+               exit(EXIT_FAILURE);
+       }
+
+       addr.sin_addr.s_addr = inet_addr(argv[1]);
+       addr.sin_port = htons(RTT_PORT);
+
+       /* bind to receive address */
+       err = bind(fd, (struct sockaddr *)&addr, sizeof(addr));
+       if (err < 0) {
+               perror("bind");
+               exit(EXIT_FAILURE);
+       }
+
+       memset(&to_addr, 0, sizeof(to_addr));
+       to_addr.sin_family = AF_INET;
+       to_addr.sin_addr.s_addr = inet_addr(RTT_SENDER_GROUP);
+       to_addr.sin_port = htons(RTT_PORT);
+
+       /* use setsockopt() to request that the kernel join a multicast group */
+       mreq.imr_multiaddr.s_addr = inet_addr(RTT_RECEIVER_GROUP);
+       mreq.imr_interface.s_addr = addr.sin_addr.s_addr;
+       err = setsockopt(fd, IPPROTO_IP,
+                       IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
+       if (err < 0) {
+               perror("setsockopt");
+               exit(EXIT_FAILURE);
+       }
+
+       err = ioctl(fd, RTNET_RTIOC_EXTPOOL, &add_rtskbs);
+       if (err < 0)
+               perror("ioctl(RTNET_RTIOC_EXTPOOL)\n");
+
+       /* now just enter a receive/send loop */
+       while (1) {
+               addrlen = sizeof(addr);
+               nbytes = recvfrom(fd, msgbuf, sizeof(msgbuf), 0,
+                               (struct sockaddr *)&addr, &addrlen);
+               if (nbytes <= 0) {
+                       perror("recvfrom");
+                       exit(EXIT_FAILURE);
+               }
+
+               err = sendto(fd, msgbuf, nbytes, 0,
+                       (struct sockaddr *)&to_addr, sizeof(addr));
+               if (err < 0) {
+                       perror("sendto");
+                       exit(EXIT_FAILURE);
+               }
+       }
+}
diff --git a/demo/net/rtt-responder.c b/demo/net/rtt-responder.c
new file mode 100644
index 000000000..6e31a1ff2
--- /dev/null
+++ b/demo/net/rtt-responder.c
@@ -0,0 +1,193 @@
+/***
+ *
+ *  examples/xenomai/posix/rtt-responder.c
+ *
+ *  Round-Trip Time Responder - listens and sends back a packet
+ *
+ *  Based on Ulrich Marx's module, later ported over user space POSIX.
+ *
+ *  Copyright (C) 2002 Ulrich Marx <m...@kammer.uni-hannover.de>
+ *                2002 Marc Kleine-Budde <kleine-bu...@gmx.de>
+ *                2004, 2006 Jan Kiszka <jan.kis...@web.de>
+ *
+ *  RTnet - real-time networking example
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <string.h>
+#include <unistd.h>
+#include <netinet/in.h>
+#include <sys/mman.h>
+#include <arpa/inet.h>
+#include <limits.h>
+
+#include <rtdm/net.h>
+
+char *dest_ip_s = "";
+char *local_ip_s  = "";
+unsigned int reply_size = 0;
+
+pthread_t rt_thread;
+
+#define RCV_PORT    36000
+#define XMT_PORT    35999
+
+struct sockaddr_in dest_addr;
+
+int sock;
+
+char buffer[65536];
+
+
+static void *responder(void* arg)
+{
+    struct sched_param  param = { .sched_priority = 81 };
+    struct msghdr       rx_msg;
+    struct iovec        iov;
+    ssize_t             ret;
+
+
+    if (dest_addr.sin_addr.s_addr == INADDR_ANY) {
+        rx_msg.msg_name    = &dest_addr;
+        rx_msg.msg_namelen = sizeof(dest_addr);
+    } else {
+        rx_msg.msg_name    = NULL;
+        rx_msg.msg_namelen = 0;
+    }
+    rx_msg.msg_namelen     = sizeof(struct sockaddr_in);
+    rx_msg.msg_iov         = &iov;
+    rx_msg.msg_iovlen      = 1;
+    rx_msg.msg_control     = NULL;
+    rx_msg.msg_controllen  = 0;
+
+    pthread_setschedparam(pthread_self(), SCHED_FIFO, &param);
+
+    while(1) {
+        iov.iov_base = &buffer;
+        iov.iov_len  = sizeof(buffer);
+
+        ret = recvmsg(sock, &rx_msg, 0);
+        if (ret <= 0) {
+            printf("terminating responder thread\n");
+            return NULL;
+        }
+
+        sendto(sock, &buffer, reply_size ? : ret, 0,
+               (struct sockaddr *)&dest_addr,
+               sizeof(struct sockaddr_in));
+    }
+}
+
+
+int main(int argc, char *argv[])
+{
+    struct sockaddr_in local_addr;
+    int add_rtskbs = 30;
+    pthread_attr_t thattr;
+    int ret;
+
+
+    while (1) {
+        switch (getopt(argc, argv, "d:l:s:")) {
+            case 'd':
+                dest_ip_s = optarg;
+                break;
+
+            case 'l':
+                local_ip_s = optarg;
+                break;
+
+            case 's':
+                reply_size = atoi(optarg);
+                break;
+
+            case -1:
+                goto end_of_opt;
+
+            default:
+                printf("usage: %s [-d <dest_ip>] [-l <local_ip>] "
+                       "[-s <reply_size>]\n", argv[0]);
+                return 0;
+        }
+    }
+ end_of_opt:
+
+    if (dest_ip_s[0]) {
+        inet_aton(dest_ip_s, &dest_addr.sin_addr);
+        dest_addr.sin_port = htons(XMT_PORT);
+    } else
+        dest_addr.sin_addr.s_addr = INADDR_ANY;
+
+    if (local_ip_s[0])
+        inet_aton(local_ip_s, &local_addr.sin_addr);
+    else
+        local_addr.sin_addr.s_addr = INADDR_ANY;
+
+    if (reply_size > 65505)
+        reply_size = 65505;
+    else if (reply_size < sizeof(struct timespec))
+        reply_size = sizeof(struct timespec);
+
+    printf("destination ip address: %s = %08x\n",
+           dest_ip_s[0] ? dest_ip_s : "SENDER", dest_addr.sin_addr.s_addr);
+    printf("local ip address: %s = %08x\n",
+           local_ip_s[0] ? local_ip_s : "INADDR_ANY", 
local_addr.sin_addr.s_addr);
+    printf("reply size: %d\n", reply_size);
+
+    /* create rt-socket */
+    if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
+        perror("socket cannot be created");
+        return 1;
+    }
+
+    /* bind the rt-socket to local_addr */
+    local_addr.sin_family = AF_INET;
+    local_addr.sin_port   = htons(RCV_PORT);
+    if (bind(sock, (struct sockaddr *)&local_addr, sizeof(local_addr)) < 0) {
+        perror("cannot bind to local ip/port");
+        close(sock);
+        return 1;
+    }
+
+    /* extend the socket pool */
+    ret = ioctl(sock, RTNET_RTIOC_EXTPOOL, &add_rtskbs);
+    if (ret < 0)
+        perror("ioctl(RTNET_RTIOC_EXTPOOL)\n");
+
+    /* create reply rt-thread */
+    pthread_attr_init(&thattr);
+    pthread_attr_setdetachstate(&thattr, PTHREAD_CREATE_JOINABLE);
+    pthread_attr_setstacksize(&thattr, PTHREAD_STACK_MIN);
+    ret = pthread_create(&rt_thread, &thattr, &responder, NULL);
+    if (ret) {
+        close(sock);
+        errno = ret; perror("pthread_create failed");
+        return 1;
+    }
+
+    pause();
+
+    pthread_kill(rt_thread, SIGHUP);
+    pthread_join(rt_thread, NULL);
+
+    return 0;
+}
diff --git a/demo/net/rtt-sender.c b/demo/net/rtt-sender.c
new file mode 100644
index 000000000..ae75a6f19
--- /dev/null
+++ b/demo/net/rtt-sender.c
@@ -0,0 +1,341 @@
+/***
+ *
+ *  examples/xenomai/posix/rtt-requester.c
+ *
+ *  Round-Trip Time Requester - sends packet, receives echo, evaluates
+ *                              and displays per-station round-trip times
+ *
+ *  Based on Ulrich Marx's module, adopted to RTmac and later ported over
+ *  user space POSIX.
+ *
+ *  Copyright (C) 2002 Ulrich Marx <m...@kammer.uni-hannover.de>
+ *                2002 Marc Kleine-Budde <kleine-bu...@gmx.de>
+ *                2006 Jan Kiszka <jan.kis...@web.de>
+ *
+ *  RTnet - real-time networking example
+ *  RTmac - real-time media access control example
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <errno.h>
+#include <mqueue.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <string.h>
+#include <unistd.h>
+#include <netinet/in.h>
+#include <sys/mman.h>
+#include <arpa/inet.h>
+#include <limits.h>
+
+#include <rtdm/net.h>
+
+char *dest_ip_s = "127.0.0.1";
+char *local_ip_s = "";
+unsigned int cycle = 50000; /* 50 ms */
+
+pthread_t xmit_thread;
+pthread_t recv_thread;
+
+#define RCV_PORT                35999
+#define XMT_PORT                36000
+
+#define DEFAULT_ADD_BUFFERS     30
+
+struct sockaddr_in dest_addr;
+
+int sock;
+mqd_t mq;
+
+#define BUFSIZE 1500
+union {
+    char            data[BUFSIZE];
+    struct timespec tx_date;
+} packet;
+
+struct station_stats {
+    struct in_addr  addr;
+    long long       last, min, max;
+    unsigned long   count;
+};
+
+struct packet_stats {
+    struct in_addr  addr;
+    long long       rtt;
+};
+
+#define MAX_STATIONS 100
+static struct station_stats station[MAX_STATIONS];
+
+
+static struct station_stats *lookup_stats(struct in_addr addr)
+{
+    int i;
+
+    for (i = 0; i < MAX_STATIONS; i++) {
+        if (station[i].addr.s_addr == addr.s_addr)
+            break;
+        if (station[i].addr.s_addr == 0) {
+            station[i].addr = addr;
+            station[i].min  = LONG_MAX;
+            station[i].max  = LONG_MIN;
+            break;
+        }
+    }
+    if (i == MAX_STATIONS)
+        return NULL;
+    return &station[i];
+}
+
+
+static void *transmitter(void *arg)
+{
+    struct sched_param  param = { .sched_priority = 80 };
+    struct timespec     next_period;
+    struct timespec     tx_date;
+
+
+    pthread_setschedparam(pthread_self(), SCHED_FIFO, &param);
+
+    clock_gettime(CLOCK_MONOTONIC, &next_period);
+
+    while(1) {
+        next_period.tv_nsec += cycle * 1000;
+        if (next_period.tv_nsec >= 1000000000) {
+            next_period.tv_nsec = 0;
+            next_period.tv_sec++;
+        }
+
+        clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &next_period, NULL);
+
+        clock_gettime(CLOCK_MONOTONIC, &tx_date);
+
+        /* transmit the request packet containing the local time */
+        if (sendto(sock, &tx_date, sizeof(tx_date), 0,
+                   (struct sockaddr *)&dest_addr,
+                   sizeof(struct sockaddr_in)) < 0) {
+            if (errno == EBADF)
+                printf("terminating transmitter thread\n");
+            else
+                perror("sendto failed");
+            return NULL;
+        }
+    }
+}
+
+
+static void *receiver(void *arg)
+{
+    struct sched_param  param = { .sched_priority = 82 };
+    struct msghdr       msg;
+    struct iovec        iov;
+    struct sockaddr_in  addr;
+    struct timespec     rx_date;
+    struct packet_stats stats;
+    int                 ret;
+
+
+    msg.msg_name       = &addr;
+    msg.msg_namelen    = sizeof(addr);
+    msg.msg_iov        = &iov;
+    msg.msg_iovlen     = 1;
+    msg.msg_control    = NULL;
+    msg.msg_controllen = 0;
+
+    pthread_setschedparam(pthread_self(), SCHED_FIFO, &param);
+
+    while (1) {
+        iov.iov_base = &packet;
+        iov.iov_len  = sizeof(packet);
+
+        ret = recvmsg(sock, &msg, 0);
+        if (ret <= 0) {
+            printf("terminating receiver thread\n");
+            return NULL;
+        }
+
+        clock_gettime(CLOCK_MONOTONIC, &rx_date);
+        stats.rtt = rx_date.tv_sec * 1000000000LL + rx_date.tv_nsec;
+        stats.rtt -= packet.tx_date.tv_sec * 1000000000LL +
+            packet.tx_date.tv_nsec;
+        stats.addr = addr.sin_addr;
+
+        mq_send(mq, (char *)&stats, sizeof(stats), 0);
+    }
+}
+
+
+int main(int argc, char *argv[])
+{
+    struct sched_param param = { .sched_priority = 1 };
+    struct sockaddr_in local_addr;
+    int add_rtskbs = DEFAULT_ADD_BUFFERS;
+    pthread_attr_t thattr;
+    char mqname[32];
+    struct mq_attr mqattr;
+    int stations = 0;
+    int ret;
+
+
+    while (1) {
+        switch (getopt(argc, argv, "d:l:c:b:")) {
+            case 'd':
+                dest_ip_s = optarg;
+                break;
+
+            case 'l':
+                local_ip_s = optarg;
+                break;
+
+            case 'c':
+                cycle = atoi(optarg);
+                break;
+
+            case 'b':
+                add_rtskbs = atoi(optarg);
+
+            case -1:
+                goto end_of_opt;
+
+            default:
+                printf("usage: %s [-d <dest_ip>] [-l <local_ip>] "
+                       "[-c <cycle_microsecs>] [-b <add_buffers>]\n",
+                       argv[0]);
+                return 0;
+        }
+    }
+ end_of_opt:
+
+    dest_addr.sin_family = AF_INET;
+    dest_addr.sin_port   = htons(XMT_PORT);
+    if (dest_ip_s[0])
+        inet_aton(dest_ip_s, &dest_addr.sin_addr);
+    else
+        dest_addr.sin_addr.s_addr = INADDR_ANY;
+
+    if (local_ip_s[0])
+        inet_aton(local_ip_s, &local_addr.sin_addr);
+    else
+        local_addr.sin_addr.s_addr = INADDR_ANY;
+
+    printf("destination ip address: %s = %08x\n",
+           dest_ip_s[0] ? dest_ip_s : "SENDER", dest_addr.sin_addr.s_addr);
+    printf("local ip address: %s = %08x\n",
+           local_ip_s[0] ? local_ip_s : "INADDR_ANY", 
local_addr.sin_addr.s_addr);
+    printf("cycle: %d us\n", cycle);
+
+    /* create rt-socket */
+    if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
+        perror("socket cannot be created");
+        return 1;
+    }
+
+    /* bind the rt-socket to local_addr */
+    local_addr.sin_family = AF_INET;
+    local_addr.sin_port   = htons(RCV_PORT);
+    if (bind(sock, (struct sockaddr *)&local_addr, sizeof(local_addr)) < 0) {
+        perror("cannot bind to local ip/port");
+        close(sock);
+        return 1;
+    }
+
+    /* extend the socket pool */
+    ret = ioctl(sock, RTNET_RTIOC_EXTPOOL, &add_rtskbs);
+    if (ret < 0)
+        perror("ioctl(RTNET_RTIOC_EXTPOOL)");
+
+    /* create statistics message queue */
+    snprintf(mqname, sizeof(mqname), "/rtt-sender-%d", getpid());
+    mqattr.mq_flags   = 0;
+    mqattr.mq_maxmsg  = 100;
+    mqattr.mq_msgsize = sizeof(struct packet_stats);
+    mq = mq_open(mqname, O_RDWR | O_CREAT | O_EXCL, 0600, &mqattr);
+    if (mq == (mqd_t)-1) {
+        perror("opening mqueue failed");
+        close(sock);
+        return 1;
+    }
+
+    /* create transmitter rt-thread */
+    pthread_attr_init(&thattr);
+    pthread_attr_setdetachstate(&thattr, PTHREAD_CREATE_JOINABLE);
+    pthread_attr_setstacksize(&thattr, PTHREAD_STACK_MIN);
+    ret = pthread_create(&recv_thread, &thattr, &receiver, NULL);
+    if (ret) {
+        errno = ret; perror("pthread_create(receiver) failed");
+        close(sock);
+        mq_close(mq);
+        return 1;
+    }
+
+    /* create receiver rt-thread */
+    ret = pthread_create(&xmit_thread, &thattr, &transmitter, NULL);
+    if (ret) {
+        errno = ret; perror("pthread_create(transmitter) failed");
+        close(sock);
+        mq_close(mq);
+        pthread_kill(recv_thread, SIGHUP);
+        pthread_join(recv_thread, NULL);
+        return 1;
+    }
+
+    pthread_setschedparam(pthread_self(), SCHED_FIFO, &param);
+
+    while (1) {
+        struct packet_stats pack;
+        struct station_stats *pstat;
+        int nr;
+
+        ret = mq_receive(mq, (char *)&pack, sizeof(pack), NULL);
+        if (ret < (int)sizeof(pack))
+            break;
+
+        pstat = lookup_stats(pack.addr);
+        if (!pstat)
+            continue;
+
+        pstat->last = pack.rtt;
+        if (pstat->last < pstat->min)
+            pstat->min = pstat->last;
+        if (pstat->last > pstat->max)
+            pstat->max = pstat->last;
+        pstat->count++;
+
+        nr = pstat - &station[0];
+        if (nr >= stations) {
+            stations = nr+1;
+            printf("\n");
+        }
+
+        printf("\033[%dA%s\t%9.3f us, min=%9.3f us, max=%9.3f us, count=%ld\n",
+               stations-nr, inet_ntoa(pack.addr), (float)pstat->last/1000,
+               (float)pstat->min/1000, (float)pstat->max/1000, pstat->count);
+        for (nr = stations-nr-1; nr > 0; nr --)
+            printf("\n");
+    }
+
+    /* This call also leaves primary mode, required for socket cleanup. */
+    printf("shutting down\n");
+
+    pthread_join(xmit_thread, NULL);
+    pthread_kill(recv_thread, SIGHUP);
+    pthread_join(recv_thread, NULL);
+
+    return 0;
+}
diff --git a/demo/net/rttcp-client.c b/demo/net/rttcp-client.c
new file mode 100644
index 000000000..e7da36b91
--- /dev/null
+++ b/demo/net/rttcp-client.c
@@ -0,0 +1,212 @@
+/***
+ *
+ *  examples/xenomai/posix/rttcp-client.c
+ *
+ *  Simple RTNet TCP client - sends packet to a server
+ *
+ *  Copyright (C) 2009 Vladimir Zapolskiy <vladimir.zapols...@siemens.com>
+ *
+ *  RTnet - real-time networking example
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License, version 2, as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <netinet/in.h>
+#include <sys/mman.h>
+#include <arpa/inet.h>
+#include <limits.h>
+
+#include <rtdm/net.h>
+
+char *dest_ip_s = "127.0.0.1";
+char *local_ip_s = "";
+unsigned int cycle = 500000; /* 500 ms */
+
+#define RCV_PORT                35999
+#define XMT_PORT                36000
+#define DEFAULT_LOOPS           10
+#define DEFAULT_ADD_BUFFERS     30
+
+int add_rtskbs = DEFAULT_ADD_BUFFERS;
+
+pthread_t sender_task = 0;
+
+struct conn_t {
+    int nloops;
+    int sock;
+    struct sockaddr_in dest_addr;
+    struct sockaddr_in local_addr;
+};
+
+const char msg[] = "Hello";
+
+static void *sender(void *arg)
+{
+    struct conn_t *connection = (struct conn_t *)arg;
+    int sock = connection->sock;
+    int ret, i, sopt_len;
+    struct timeval  tv;
+    struct timespec sleep_period;
+
+    sopt_len = 1;
+    if ((ret = setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &sopt_len,
+                          sizeof(sopt_len))) < 0) {
+        perror("set SO_KEEPALIVE socket option");
+        return NULL;
+    }
+
+    tv.tv_sec = 0;
+    tv.tv_usec = 100000;
+    if ((ret = setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &tv,
+                          sizeof(tv))) < 0) {
+        perror("set SO_SNDTIMEO socket option");
+        return NULL;
+    }
+
+    if ((ret = bind(sock, (struct sockaddr*)&connection->local_addr,
+        sizeof(struct sockaddr_in))) < 0)
+    {
+        perror("bind socket");
+        return NULL;
+    }
+
+    if ((ret = connect(sock, (struct sockaddr*)&connection->dest_addr,
+        sizeof(struct sockaddr_in))) < 0)
+    {
+        perror("connect to server");
+        return NULL;
+    }
+
+    sleep_period.tv_nsec = cycle * 1000;
+
+    for (i = 1; i <= connection->nloops; i++) {
+        clock_gettime(CLOCK_MONOTONIC, &sleep_period);
+
+        sleep_period.tv_nsec += cycle * 1000;
+        if (sleep_period.tv_nsec >= 1000000000) {
+            sleep_period.tv_nsec = 0;
+            sleep_period.tv_sec++;
+        }
+
+        ret = write(sock, msg, sizeof(msg));
+        if (ret <= 0) {
+            if (ret == 0)
+                printf("connection closed by peer\n");
+            else
+                perror("write to socket");
+            return NULL;
+        }
+        printf("%d: wrote %d bytes to socket\n", i, ret);
+
+        clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &sleep_period, NULL);
+    }
+
+    return NULL;
+}
+
+int main(int argc, char** argv)
+{
+    struct conn_t connection = { .nloops = DEFAULT_LOOPS };
+    struct sched_param param;
+    pthread_attr_t attr;
+    int local_port = RCV_PORT;
+    int ret;
+
+    while (1) {
+        switch (getopt(argc, argv, "d:l:p:n:")) {
+            case 'd':
+                dest_ip_s = optarg;
+                break;
+
+            case 'l':
+                local_ip_s = optarg;
+                break;
+
+            case 'p':
+                local_port = atoi(optarg);
+                break;
+
+            case 'n':
+                connection.nloops = atoi(optarg);
+                break;
+
+            case -1:
+                goto end_of_opt;
+
+            default:
+                printf("usage: %s [-d <dest_ip>] [-l <local_ip>] "
+                       "[-p <local port>] [-n <number of loops>]\n", argv[0]);
+                return 0;
+        }
+    }
+ end_of_opt:
+
+    connection.dest_addr.sin_family = AF_INET;
+    connection.dest_addr.sin_port   = htons(XMT_PORT);
+    if (dest_ip_s[0])
+        inet_aton(dest_ip_s, &connection.dest_addr.sin_addr);
+    else
+        connection.dest_addr.sin_addr.s_addr = INADDR_ANY;
+
+    connection.local_addr.sin_family = AF_INET;
+    connection.local_addr.sin_port = htons(local_port);
+    if (local_ip_s[0])
+        inet_aton(local_ip_s, &connection.local_addr.sin_addr);
+    else
+        connection.local_addr.sin_addr.s_addr = INADDR_ANY;
+
+    printf("destination ip address: %s = %08x\n",
+           dest_ip_s[0] ? dest_ip_s : "SENDER",
+           connection.dest_addr.sin_addr.s_addr);
+    printf("local ip address: %s = %08x\n",
+           local_ip_s[0] ? local_ip_s : "INADDR_ANY",
+           connection.local_addr.sin_addr.s_addr);
+    printf("port: %d\n", local_port);
+
+    /* create rt-socket */
+    if ((connection.sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
+        perror("socket create");
+        return 1;
+    }
+
+    /* extend the socket pool (optional, will fail with non-RT sockets) */
+    ret = ioctl(connection.sock, RTNET_RTIOC_EXTPOOL, &add_rtskbs);
+    if (ret < 0)
+        perror("ioctl(RTNET_RTIOC_EXTPOOL)");
+
+    pthread_attr_init(&attr);
+    pthread_attr_setinheritsched(&attr, 1);
+    pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
+    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+    pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN);
+    param.sched_priority = 80;
+    pthread_attr_setschedparam(&attr, &param);
+
+    ret = pthread_create(&sender_task, &attr, &sender, &connection);
+    if (ret) {
+        perror("start real-time task");
+        return 1;
+    }
+
+    pthread_join(sender_task, NULL);
+    close(connection.sock);
+
+    return 0;
+}
diff --git a/demo/net/rttcp-server.c b/demo/net/rttcp-server.c
new file mode 100644
index 000000000..d6422e60e
--- /dev/null
+++ b/demo/net/rttcp-server.c
@@ -0,0 +1,181 @@
+/***
+ *
+ *  examples/xenomai/posix/rttcp-server.c
+ *
+ *  Simple RTNet TCP server - listens and sends back a packet
+ *
+ *  Copyright (C) 2009 Vladimir Zapolskiy <vladimir.zapols...@siemens.com>
+ *
+ *  RTnet - real-time networking example
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License, version 2, as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <netinet/in.h>
+#include <sys/mman.h>
+#include <arpa/inet.h>
+#include <limits.h>
+
+#include <rtdm/net.h>
+
+char *local_ip_s  = "";
+
+#define RCV_PORT            36000
+#define MAX_STRLENGTH       128
+#define DEFAULT_ADD_BUFFERS 30
+
+int add_rtskbs = DEFAULT_ADD_BUFFERS;
+
+pthread_t receiver_task = 0;
+
+struct conn_t {
+    int sock;
+    struct sockaddr_in client_addr;
+    struct sockaddr_in local_addr;
+};
+
+static void* receiver(void* arg)
+{
+    struct conn_t *connection = (struct conn_t*)arg;
+    socklen_t len = sizeof(struct sockaddr_in);
+    int sock = connection->sock;
+    struct timeval tv;
+    fd_set readset;
+    int cnt = 0;
+    char chr;
+    int ret;
+
+    /* bind the rt-socket to local_addr */
+    connection->local_addr.sin_family = AF_INET;
+    connection->local_addr.sin_port   = htons(RCV_PORT);
+    if (bind(sock, (struct sockaddr *)&connection->local_addr,
+             sizeof(struct sockaddr_in)) < 0) {
+        perror("bind socket");
+        return NULL;
+    }
+
+    /* Backlog is ignored, current realization just transmit state to LISTEN */
+    if (listen(sock, 1) < 0) {
+        perror("listen on socket");
+        return NULL;
+    }
+
+    /* Warning, no new socket descriptor, only one connection */
+    sock = accept(sock, (struct sockaddr *)&connection->client_addr, &len);
+    if (sock < 0) {
+        perror("accept connection");
+        return NULL;
+    }
+    printf("connection from %s:%d\n",
+           inet_ntoa(connection->client_addr.sin_addr),
+           ntohs(connection->client_addr.sin_port));
+
+    while (1) {
+        FD_ZERO(&readset);
+        FD_SET(sock, &readset);
+        tv.tv_sec = 5;
+        tv.tv_usec = 0;
+
+        ret = select(sock + 1, &readset, NULL, NULL, &tv);
+        if (ret <= 0) {
+            if (ret == 0)
+                fprintf(stderr, "timeout during select()\n");
+            else
+                perror("error on select()");
+            return NULL;
+        }
+
+        if (FD_ISSET(sock, &readset)) {
+            ret = read(sock, &chr, 1);
+            if (ret <= 0) {
+                if (ret == 0)
+                    printf("connection closed\n");
+                else
+                    perror("error on read()");
+                return NULL;
+            }
+
+            printf("%d: received %d bytes, message: %c\n", cnt++, ret, chr);
+        }
+    }
+    return NULL;
+}
+
+int main(int argc, char** argv)
+{
+    struct conn_t connection;
+    struct sched_param param;
+    pthread_attr_t attr;
+    int ret;
+
+    while (1) {
+        switch (getopt(argc, argv, "l:")) {
+            case 'l':
+                local_ip_s = optarg;
+                break;
+
+            case -1:
+                goto end_of_opt;
+
+            default:
+                printf("usage: %s [-l <local_ip>]\n", argv[0]);
+                return 0;
+        }
+    }
+ end_of_opt:
+
+    if (local_ip_s[0])
+        inet_aton(local_ip_s, &connection.local_addr.sin_addr);
+    else
+        connection.local_addr.sin_addr.s_addr = INADDR_ANY;
+
+    printf("local ip address: %s = %08x\n",
+           local_ip_s[0] ? local_ip_s : "INADDR_ANY",
+           connection.local_addr.sin_addr.s_addr);
+
+    /* create rt-socket */
+    if ((connection.sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
+        perror("socket create");
+        return 1;
+    }
+
+    /* extend the socket pool (optional, will fail with non-RT sockets) */
+    ret = ioctl(connection.sock, RTNET_RTIOC_EXTPOOL, &add_rtskbs);
+    if (ret < 0)
+        perror("ioctl(RTNET_RTIOC_EXTPOOL)");
+
+    pthread_attr_init(&attr);
+    pthread_attr_setinheritsched(&attr, 1);
+    pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
+    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+    pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN);
+    param.sched_priority = 20;
+    pthread_attr_setschedparam(&attr, &param);
+
+    ret = pthread_create(&receiver_task, NULL, &receiver, &connection);
+    if (ret) {
+        perror("start real-time task");
+        return 1;
+    }
+
+    pthread_join(receiver_task, NULL);
+    close(connection.sock);
+
+    return 0;
+}
diff --git a/demo/net/udp-send.c b/demo/net/udp-send.c
new file mode 100644
index 000000000..a29f98024
--- /dev/null
+++ b/demo/net/udp-send.c
@@ -0,0 +1,136 @@
+/*
+ * sender.c -- multicasts "hello, world!" to a multicast group once a second
+ *
+ * Antony Courtney,    25/11/94
+ */
+
+#include <time.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <error.h>
+#include <stdlib.h>
+#include <sched.h>
+#include <pthread.h>
+#include <sys/timerfd.h>
+#include <boilerplate/trace.h>
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+
+#define HELLO_PORT 12345
+#define HELLO_GROUP "225.0.0.37"
+#define ONE_BILLION    1000000000
+
+#define check_pthread(expr)                    \
+       ({ \
+               int __e = (expr);               \
+               if (__e) {                      \
+                       printf("%s: %d\n", #expr, __e); \
+                       exit(EXIT_FAILURE);             \
+               }                                       \
+       })
+
+int main(int argc, char *argv[])
+{
+     struct sockaddr_in addr;
+     int fd, tfd, err;
+     char message[] = "Hello, World!\n";
+     struct timespec last_print, start, now;
+     struct sched_param sparm;
+     unsigned long long diff, min = ~0ULL, max = 0, sum, count;
+     struct itimerspec timer_conf;
+
+     /* create what looks like an ordinary UDP socket */
+     if ((fd=socket(AF_INET,SOCK_DGRAM,0)) < 0) {
+         perror("socket");
+         exit(1);
+     }
+
+     if (argc != 2) {
+        fprintf(stderr, "Local ip address expected as first and only 
argument\n");
+        exit(1);
+     }
+
+     memset(&addr,0,sizeof(addr));
+     addr.sin_family=AF_INET;
+     addr.sin_addr.s_addr=inet_addr(argv[1]); /* N.B.: differs from sender */
+     addr.sin_port=htons(HELLO_PORT);
+
+     /* bind to receive address */
+     if (bind(fd,(struct sockaddr *) &addr,sizeof(addr)) < 0) {
+         perror("bind");
+         exit(1);
+     }
+
+     /* set up destination address */
+     memset(&addr,0,sizeof(addr));
+     addr.sin_family=AF_INET;
+     addr.sin_addr.s_addr=inet_addr(HELLO_GROUP);
+     addr.sin_port=htons(HELLO_PORT);
+
+     sparm.sched_priority = 99;
+
+     check_pthread(pthread_setschedparam(pthread_self(), SCHED_FIFO, &sparm));
+
+     tfd = timerfd_create(CLOCK_MONOTONIC, 0);
+     if (tfd == -1)
+            error(1, errno, "timerfd_create()");
+
+     check_pthread(pthread_setmode_np(0, PTHREAD_WARNSW, NULL));
+
+     /* now just sendto() our destination! */
+     sum = 0;
+     count = 0;
+     err = clock_gettime(CLOCK_MONOTONIC, &start);
+     start.tv_nsec += 1000000;
+     if (start.tv_nsec > ONE_BILLION) {
+            start.tv_nsec -= ONE_BILLION;
+            start.tv_sec++;
+     }
+     timer_conf.it_value = start;
+     timer_conf.it_interval.tv_sec = 0;
+     timer_conf.it_interval.tv_nsec = 5000000;
+     err = timerfd_settime(tfd, TFD_TIMER_ABSTIME, &timer_conf, NULL);
+     if (err)
+            error(1, errno, "timerfd_settime()");
+     clock_gettime(CLOCK_MONOTONIC, &last_print);
+
+     while (1) {
+            uint64_t ticks;
+            clock_gettime(CLOCK_MONOTONIC, &start);
+            if (sendto(fd,message,sizeof(message),0,(struct sockaddr *) &addr,
+                            sizeof(addr)) < 0) {
+                    perror("sendto");
+                    exit(1);
+            }
+            clock_gettime(CLOCK_MONOTONIC, &now);
+
+            diff = now.tv_sec * 1000000ULL + now.tv_nsec / 1000 -
+                    (start.tv_sec * 1000000ULL + start.tv_nsec / 1000);
+            if (diff < min)
+                    min = diff;
+            if (diff > max) {
+                    xntrace_user_freeze(diff, 0);
+                    max = diff;
+            }
+            sum += diff;
+            count++;
+
+            diff = now.tv_sec * 1000000ULL + now.tv_nsec / 1000 -
+                    (last_print.tv_sec * 1000000ULL + last_print.tv_sec / 
1000);
+            if (diff >= 1000000) {
+                    fprintf(stderr, "%Lu, %Lu, %Lu\n",
+                            min, sum / count, max);
+                    last_print = now;
+            }
+
+            err = read(tfd, &ticks, sizeof(ticks));
+            if (err < 0)
+                    error(1, errno, "read()");
+     }
+}
-- 
2.17.1


Reply via email to