summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@OARcorp.com>2007-09-19 21:52:02 +0000
committerJoel Sherrill <joel.sherrill@OARcorp.com>2007-09-19 21:52:02 +0000
commit046d88cc0163bf6828beef043f011acdd9c43426 (patch)
tree1d4efdb6bba1768d1ccb802b2e4c3391c6c07051
parent5538df4681e2cb126bc4c5762884e0943a59bdde (diff)
2007-09-19 Joel Sherrill <joel.sherrill@oarcorp.com>
* ChangeLog, Makefile, README, init.c, listener.c, mcast.c, mcast_params.h, mcast_route.c, rootfs/etc/host.conf, rootfs/etc/hosts: New files.
-rw-r--r--mcast/ChangeLog6
-rw-r--r--mcast/Makefile77
-rw-r--r--mcast/README52
-rw-r--r--mcast/init.c88
-rw-r--r--mcast/listener.c84
-rw-r--r--mcast/mcast.c159
-rw-r--r--mcast/mcast_params.h8
-rw-r--r--mcast/mcast_route.c96
-rw-r--r--mcast/rootfs/etc/host.conf1
-rw-r--r--mcast/rootfs/etc/hosts2
10 files changed, 573 insertions, 0 deletions
diff --git a/mcast/ChangeLog b/mcast/ChangeLog
new file mode 100644
index 0000000..1d7f2b9
--- /dev/null
+++ b/mcast/ChangeLog
@@ -0,0 +1,6 @@
+2007-09-19 Joel Sherrill <joel.sherrill@oarcorp.com>
+
+ * ChangeLog, Makefile, README, init.c, listener.c, mcast.c,
+ mcast_params.h, mcast_route.c, rootfs/etc/host.conf,
+ rootfs/etc/hosts: New files.
+
diff --git a/mcast/Makefile b/mcast/Makefile
new file mode 100644
index 0000000..3c09db1
--- /dev/null
+++ b/mcast/Makefile
@@ -0,0 +1,77 @@
+#
+# $Id$
+#
+
+PGM=${ARCH}/mcast.exe
+
+MANAGERS=all
+
+C_FILES=init.c mcast.c mcast_route.c FilesystemImage.c
+C_O_FILES=$(C_FILES:%.c=${ARCH}/%.o)
+
+H_FILES=
+
+SRCS=$(DOCS) $(C_FILES) $(H_FILES)
+OBJS=$(C_O_FILES)
+
+include $(RTEMS_MAKEFILE_PATH)/Makefile.inc
+include $(RTEMS_CUSTOM)
+include $(PROJECT_ROOT)/make/leaf.cfg
+
+#
+# (OPTIONAL) Add local stuff here using +=
+#
+
+DEFINES +=
+CPPFLAGS +=
+CFLAGS +=
+CFLAGS_LD +=
+# CFLAGS_LD += -Wl,--defsym -Wl,HeapSize=0xC0000
+CFLAGS_OPTIMIZE_V +=
+## CFLAGS_DEBUG_V += -v -qrtems_debug
+
+LD_PATHS +=
+LD_LIBS +=
+
+#
+# Add your list of files to delete here. The config files
+# already know how to delete some stuff, so you may want
+# to just run 'make clean' first to see what gets missed.
+# 'make clobber' already includes 'make clean'
+#
+
+CLEAN_ADDITIONS += FilesystemImage FilesystemImage.c FilesystemImage.h
+CLEAN_ADDITIONS += listener mcast
+CLOBBER_ADDITIONS +=
+
+all: $(ARCH) $(SRCS) $(OBJS) $(PGM) listener mcast
+
+listener: listener.c mcast_params.h
+ gcc -o $@ $<
+
+mcast: mcast.c mcast_params.h
+ gcc -o $@ $<
+
+$(PGM): $(ARCH) $(OBJS) $(LINK_FILES)
+
+$(ARCH)/init.o: $(ARCH) init.c FilesystemImage.c
+
+$(ARCH)/mcast_route.o: $(ARCH) mcast_route.c
+
+$(ARCH)/mcast.o: $(ARCH) mcast.c mcast_params.h
+
+$(ARCH)/FilesystemImage.o: $(ARCH) FilesystemImage.c
+
+FilesystemImage: rootfs/etc/host.conf rootfs/etc/hosts
+ cd rootfs ; tar cf ../FilesystemImage --exclude CVS --exclude .cvsignore .
+
+FilesystemImage.c: FilesystemImage
+ $(PROJECT_ROOT)/bin/bin2c FilesystemImage FilesystemImage
+
+${PGM}: $(OBJS) $(LINK_FILES)
+ $(make-exe)
+
+# Install the program(s), appending _g or _p as appropriate.
+# for include files, just use $(INSTALL)
+install: all
+# $(INSTALL_VARIANT) -m 555 ${PGM} ${PROJECT_RELEASE}/tests
diff --git a/mcast/README b/mcast/README
new file mode 100644
index 0000000..d15176c
--- /dev/null
+++ b/mcast/README
@@ -0,0 +1,52 @@
+#
+# $Id$
+#
+
+This directory contains a very simple multicast demo program. There
+are multiple multicast demo programs on the Internet and this program
+is a combination of those.
+
+Native Programs
+===============
+Two native programs are built as a side-effect of the RTEMS make.
+They are listener and mcast.
+
++ listener is a pure listener
+
++ mcast sends and receives data and is the same program run on the
+ RTEMS target
+
+
+Driver Requirements
+===================
++ NIC must set IFF_MULTICAST bit in if_flags during attach
+
+ ifp->if_flags = IFF_BROADCAST | IFF_MULTICAST;
+
++ NIC must support SIOCADDMULTI and SIOCDELMULTI ioctls.
+
+ case SIOCADDMULTI:
+ case SIOCDELMULTI: {
+ struct ifreq* ifr = (struct ifreq*) data;
+ error = (command == SIOCADDMULTI)
+ ? ether_addmulti(ifr, &sc->arpcom)
+ : ether_delmulti(ifr, &sc->arpcom);
+
+ if (error == ENETRESET) {
+ if (ifp->if_flags & IFF_RUNNING)
+ error = // driver specific routine to adjust filtering
+ }
+ break;
+ }
+
+ In some drivers, there is no need to adjust any driver specific
+ filtering. In this case, set error = 0 in the above code.
+
+GNU/Linux
+=========
+You will have to have a route in place. Something like this command should
+work if you adjust the 192.168.1.244 to match your IP addresa and adjust the
+239.9.8.0 to match the multicast address used in mcast_params.h:
+
+/sbin/route add -net 239.9.8.0 netmask 255.255.255.0 gw 192.168.1.244 dev eth0
+
diff --git a/mcast/init.c b/mcast/init.c
new file mode 100644
index 0000000..af00d90
--- /dev/null
+++ b/mcast/init.c
@@ -0,0 +1,88 @@
+/*
+ * RTEMS configuration/initialization
+ *
+ * This program may be distributed and used for any purpose.
+ * I ask only that you:
+ * 1. Leave this author information intact.
+ * 2. Document any changes you make.
+ *
+ * W. Eric Norum
+ * Saskatchewan Accelerator Laboratory
+ * University of Saskatchewan
+ * Saskatoon, Saskatchewan, CANADA
+ * eric@skatter.usask.ca
+ *
+ * $Id$
+ */
+
+#include <bsp.h>
+
+#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
+#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
+#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
+#define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 20
+#define CONFIGURE_USE_IMFS_AS_BASE_FILESYSTEM
+
+#define CONFIGURE_EXECUTIVE_RAM_SIZE (512*1024)
+#define CONFIGURE_MAXIMUM_SEMAPHORES 20
+#define CONFIGURE_MAXIMUM_TASKS 20
+
+#define CONFIGURE_MICROSECONDS_PER_TICK 10000
+
+#define CONFIGURE_INIT_TASK_STACK_SIZE (10*1024)
+#define CONFIGURE_INIT_TASK_PRIORITY 120
+#define CONFIGURE_INIT_TASK_INITIAL_MODES (RTEMS_PREEMPT | \
+ RTEMS_NO_TIMESLICE | \
+ RTEMS_NO_ASR | \
+ RTEMS_INTERRUPT_LEVEL(0))
+
+#define CONFIGURE_INIT
+rtems_task Init (rtems_task_argument argument);
+
+#include <rtems/confdefs.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <rtems/rtems_bsdnet.h>
+#include "../networkconfig.h"
+
+#include <rtems/untar.h>
+#include "FilesystemImage.h"
+
+#if 0
+int add_mcast_route(
+ char *multi_address,
+ char *multi_netmask,
+ char *multi_gateway
+);
+
+#define MULTI_ADDRESS "239.9.8.0"
+#define MULTI_NETMASK "255.255.255.0"
+#define MULTI_GATEWAY "192.168.1.244"
+#endif
+
+/*
+ * RTEMS Startup Task
+ */
+rtems_task
+Init (rtems_task_argument ignored)
+{
+ int mcast_main(int ac, char **av);
+ rtems_status_code status;
+
+ printf("Loading filesystem image\n");
+ status = Untar_FromMemory( (char *)FilesystemImage, FilesystemImage_size );
+
+ printk( "Initializing network\n" );
+ rtems_bsdnet_initialize_network ();
+
+ // This appears to have no effect.
+ // add_mcast_route( MULTI_ADDRESS, MULTI_NETMASK, MULTI_GATEWAY );
+
+ printk( "Network initialized\n" );
+ rtems_bsdnet_show_inet_routes ();
+
+ printk( "Initiating mcast test\n" );
+ mcast_main ( 0, 0 );
+ exit (0);
+}
diff --git a/mcast/listener.c b/mcast/listener.c
new file mode 100644
index 0000000..5daa6c4
--- /dev/null
+++ b/mcast/listener.c
@@ -0,0 +1,84 @@
+/*
+ * 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
+ *
+ * http://ntrg.cs.tcd.ie/undergrad/4ba2/multicast/antony/example.html
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <time.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "mcast_params.h"
+
+#define HELLO_PORT MCAST_PORT
+#define HELLO_GROUP MCAST_ADDR
+
+#define MSGBUFSIZE 256
+
+main(int argc, char *argv[])
+{
+ struct sockaddr_in addr;
+ int fd, nbytes,addrlen;
+ struct ip_mreq mreq;
+ char msgbuf[MSGBUFSIZE];
+
+ u_int yes=1; /*** MODIFICATION TO ORIGINAL */
+
+ /* create what looks like an ordinary UDP socket */
+ if ((fd=socket(AF_INET,SOCK_DGRAM,0)) < 0) {
+ perror("socket");
+ exit(1);
+ }
+
+
+/**** MODIFICATION TO ORIGINAL */
+ /* allow multiple sockets to use the same PORT number */
+ if (setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(yes)) < 0) {
+ perror("Reusing ADDR failed");
+ exit(1);
+ }
+/*** END OF MODIFICATION TO ORIGINAL */
+
+ /* set up destination address */
+ memset(&addr,0,sizeof(addr));
+ addr.sin_family=AF_INET;
+ addr.sin_addr.s_addr=htonl(INADDR_ANY); /* 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);
+ }
+
+ /* use setsockopt() to request that the kernel join a multicast group */
+ mreq.imr_multiaddr.s_addr=inet_addr(HELLO_GROUP);
+ mreq.imr_interface.s_addr=htonl(INADDR_ANY);
+ if (setsockopt(fd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(mreq)) < 0) {
+ perror("setsockopt");
+ exit(1);
+ }
+
+ /* now just enter a read-print loop */
+ while (1) {
+ addrlen=sizeof(addr);
+ if ((nbytes=recvfrom(fd,msgbuf,MSGBUFSIZE,0,
+ (struct sockaddr *) &addr,&addrlen)) < 0) {
+ perror("recvfrom");
+ exit(1);
+ }
+ puts(msgbuf);
+ }
+}
+
+
diff --git a/mcast/mcast.c b/mcast/mcast.c
new file mode 100644
index 0000000..c1becc5
--- /dev/null
+++ b/mcast/mcast.c
@@ -0,0 +1,159 @@
+#include <stdio.h>
+#include <sys/file.h>
+#include <sys/types.h>
+#ifdef __Lynx__
+#include <socket.h>
+#else
+#include <sys/socket.h>
+#endif
+#include <net/if.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <string.h>
+
+
+#include "mcast_params.h"
+
+#define ROUTERS_TO_HOP 10 // Keep my traffic in the same subnet
+
+
+static struct sockaddr_in addr;
+static int so;
+static char mhost[100];
+static unsigned long hostaddr;
+
+int msend(char *buf, int num)
+{
+ bzero(&addr, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons((u_short)MCAST_PORT);
+ addr.sin_addr.s_addr = inet_addr(MCAST_ADDR);
+ if (sendto(so, buf, num, 0, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+ if (errno != EAGAIN)
+ perror("sendto");
+ return 0;
+ }
+ return 1;
+}
+
+
+int mrecv(char *buf, int num)
+{
+ socklen_t i;
+ int n;
+
+ bzero(&addr, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons((u_short)MCAST_PORT);
+ addr.sin_addr.s_addr = inet_addr(MCAST_ADDR);
+
+
+ i = sizeof(addr);
+ if ((n = recvfrom(so, buf, num, 0, (struct sockaddr *)&addr, &i)) == -1) {
+ if (errno != EAGAIN)
+ perror("recvfrom");
+ return 0;
+ }
+ return n;
+}
+
+
+#if defined(__rtems__)
+int mcast_main(int ac, char **av)
+#else
+int main(int ac, char **av)
+#endif
+{
+ int yes=1;
+ char line[1024];
+ struct ip_mreq imr;
+ struct hostent *h;
+ unsigned char mttl;
+ int mlen;
+ unsigned long long i, j, k;
+
+
+ if (ac > 1) mlen = atoi(av[1]);
+ else mlen = 0;
+
+ if ((gethostname(mhost, 100) < 0)) { // Get the my hostname
+ perror("gethostname");
+ exit(1);
+ }
+ printf( "Hostname: %s\n", ((mhost) ? mhost : "NULL") );
+ if (!(h = gethostbyname(mhost))) { // Get host entry
+ perror("gethostbyname");
+ exit(1);
+ }
+
+ printf( "host=0x%08x\n", *(unsigned int *)h->h_addr );
+
+
+ printf( "Creating socket\n" );
+ if ((so = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+ perror("socket");
+ exit(1);
+ }
+
+ printf( "Setting SO_REUSEADDR\n" );
+ if (setsockopt(so, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) {
+ perror("setsockopt, reuse");
+ exit(1);
+ }
+
+ printf( "Binding\n" );
+ // Bind to port and address.
+ bzero(&addr, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons((u_short)MCAST_PORT);
+ addr.sin_addr.s_addr = INADDR_ANY;
+ if (bind(so, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+ perror("bind");
+ exit(1);
+ }
+
+ printf( "Performing IP_MULTICAST_TTL\n" );
+ mttl = ROUTERS_TO_HOP + 1; // ttl should be atleast one.
+ if (setsockopt(so, IPPROTO_IP, IP_MULTICAST_TTL, &mttl, sizeof(mttl)) < 0) {
+ perror("setsockopt, ttl" );
+ exit(1);
+ }
+ hostaddr = *(unsigned int *)h->h_addr;
+ imr.imr_interface.s_addr = htonl(INADDR_ANY);
+ // For some reason, this doesn't seem to work. I suspect it is because
+ // the /etc/hosts included with this demo must match the IP of the
+ // network interface you want to use. I couldn't get this to work
+ // so gave up. INADDR_ANY seems to reliably find the NIC. --joel
+ // imr.imr_interface.s_addr = hostaddr;
+ imr.imr_multiaddr.s_addr = inet_addr(MCAST_ADDR);
+
+ printf( "Performing IP_ADD_MEMBERSHIP\n" );
+ if (setsockopt(so, IPPROTO_IP, IP_ADD_MEMBERSHIP, &imr, sizeof(imr)) < 0) {
+ perror( "can't join group" );
+ close(so);
+ exit(1);
+ }
+
+ fcntl(so, F_SETFL, FNDELAY);
+ j = k = 0;
+ for(i = 1; 1; i++) {
+ int x;
+ if (i == 0) j++;
+ if (j == 0) k++;
+ sleep(1);
+ sprintf(line,
+ "%s i %" PRId64 ", j %" PRId64 ", k %" PRId64 "", mhost, i, j, k);
+ msend(line, strlen(line)+ mlen);
+ while ((x = mrecv(line, 500)) > 0) {
+ if (addr.sin_addr.s_addr != hostaddr) {
+ line[x] = 0;
+ printf("Raddr %s recv %s\n", inet_ntoa(addr.sin_addr), line);
+ }
+ }
+ }
+}
diff --git a/mcast/mcast_params.h b/mcast/mcast_params.h
new file mode 100644
index 0000000..86b5826
--- /dev/null
+++ b/mcast/mcast_params.h
@@ -0,0 +1,8 @@
+/*
+ * Multicast parameters which you might want to change
+ *
+ * $Id$
+ */
+
+#define MCAST_ADDR "239.9.8.0"
+#define MCAST_PORT 9753 // Some arbitrary port no.
diff --git a/mcast/mcast_route.c b/mcast/mcast_route.c
new file mode 100644
index 0000000..4d1df7a
--- /dev/null
+++ b/mcast/mcast_route.c
@@ -0,0 +1,96 @@
+/*
+ * Based upon
+ * http://www.rtems.com/ml/rtems-users/2005/may/msg00022.html
+ */
+
+/*
+
+http://ntrg.cs.tcd.ie/undergrad/4ba2/multicast/antony/index.html
+
+Every IP multicast group has a group address. IP multicast provides only
+open groups: That is, it is not necessary to be a member of a group in
+order to send datagrams to the group.
+
+Multicast address are like IP addresses used for single hosts, and is
+written in the same way: A.B.C.D. Multicast addresses will never clash
+with host addresses because a portion of the IP address space is
+specifically reserved for multicast. This reserved range consists of
+addresses from 224.0.0.0 to 239.255.255.255. However, the multicast
+addresses from 224.0.0.0 to 224.0.0.255 are reserved for multicast
+routing information; Application programs should use multicast
+addresses outside this range.
+
+*/
+
+/*
+ * Trying to have same effect of this command:
+ *
+ * /sbin/route add -net 239.9.8.0 netmask 255.255.255.0 gw 10.4.10.19 dev eth0
+ */
+
+
+#include <rtems/rtems_bsdnet.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <net/route.h>
+#include <arpa/inet.h>
+
+#include <stdio.h>
+#include <sys/errno.h>
+
+
+int add_mcast_route(
+ char *multi_address,
+ char *multi_netmask,
+ char *multi_gateway
+)
+{
+ int s;
+ struct sockaddr_in address;
+ struct sockaddr_in netmask;
+ struct sockaddr_in gateway;
+
+ memset(&address,0,sizeof(address));
+ address.sin_len = sizeof(address);
+ address.sin_family = AF_INET;
+ address.sin_addr.s_addr = inet_addr( multi_address );
+
+ memset(&netmask,0,sizeof(netmask));
+ netmask.sin_len = sizeof(netmask);
+ netmask.sin_family = AF_INET;
+ netmask.sin_addr.s_addr = inet_addr( multi_netmask );
+
+ memset(&gateway,0,sizeof(gateway));
+ gateway.sin_len = sizeof(gateway);
+ gateway.sin_family = AF_INET;
+ gateway.sin_addr.s_addr = inet_addr( multi_gateway );
+
+ s = rtems_bsdnet_rtrequest(
+ RTM_DELETE,
+ (struct sockaddr *)&address,
+ (struct sockaddr *)&gateway,
+ (struct sockaddr *)&netmask,
+ (RTF_GATEWAY | RTF_MULTICAST | RTF_STATIC),
+ NULL
+ );
+ if ( s == -1 ) {
+ fprintf( stderr, "RTM_DELETE failed errno=%d (%s)\n",
+ errno, strerror(errno) );
+ }
+
+ s = rtems_bsdnet_rtrequest(
+ RTM_ADD,
+ (struct sockaddr *)&address,
+ (struct sockaddr *)&gateway,
+ (struct sockaddr *)&netmask,
+ (RTF_UP | RTF_GATEWAY | RTF_MULTICAST | RTF_STATIC),
+ NULL
+ );
+ if ( s == -1 ) {
+ fprintf( stderr, "RTM_ADD failed errno=%d (%s)\n",
+ errno, strerror(errno) );
+ return -1;
+ }
+ fprintf( stderr, "Route added\n" );
+ return 0;
+}
diff --git a/mcast/rootfs/etc/host.conf b/mcast/rootfs/etc/host.conf
new file mode 100644
index 0000000..0e9eeb1
--- /dev/null
+++ b/mcast/rootfs/etc/host.conf
@@ -0,0 +1 @@
+order hosts, bind
diff --git a/mcast/rootfs/etc/hosts b/mcast/rootfs/etc/hosts
new file mode 100644
index 0000000..1439dc7
--- /dev/null
+++ b/mcast/rootfs/etc/hosts
@@ -0,0 +1,2 @@
+127.0.0.0 localhost rtems
+# 192.168.1.244 rtems # ip address of webserver