diff options
author | Joel Sherrill <joel.sherrill@OARcorp.com> | 2007-09-19 21:52:02 +0000 |
---|---|---|
committer | Joel Sherrill <joel.sherrill@OARcorp.com> | 2007-09-19 21:52:02 +0000 |
commit | 046d88cc0163bf6828beef043f011acdd9c43426 (patch) | |
tree | 1d4efdb6bba1768d1ccb802b2e4c3391c6c07051 | |
parent | 5538df4681e2cb126bc4c5762884e0943a59bdde (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/ChangeLog | 6 | ||||
-rw-r--r-- | mcast/Makefile | 77 | ||||
-rw-r--r-- | mcast/README | 52 | ||||
-rw-r--r-- | mcast/init.c | 88 | ||||
-rw-r--r-- | mcast/listener.c | 84 | ||||
-rw-r--r-- | mcast/mcast.c | 159 | ||||
-rw-r--r-- | mcast/mcast_params.h | 8 | ||||
-rw-r--r-- | mcast/mcast_route.c | 96 | ||||
-rw-r--r-- | mcast/rootfs/etc/host.conf | 1 | ||||
-rw-r--r-- | mcast/rootfs/etc/hosts | 2 |
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 |