diff -urNb aodv-uu-0.7.2/Makefile maodv-umd-0.7.2/Makefile --- aodv-uu-0.7.2/Makefile Mon Jun 2 19:46:08 2003 +++ maodv-umd-0.7.2/Makefile Fri Dec 5 17:43:09 2003 @@ -4,7 +4,10 @@ SRC = main.c list.c debug.c timer_queue.c aodv_socket.c aodv_hello.c \ aodv_neighbor.c aodv_timeout.c routing_table.c seek_list.c \ k_route.c aodv_rreq.c aodv_rrep.c aodv_rerr.c packet_input.c \ - packet_queue.c libipq.c icmp.c + packet_queue.c libipq.c icmp.c maodv_grph.c maodv_mact.c \ + multicast_routing_table.c igmp.c \ + maodv_rreq.c maodv_rrep.c k_mroute.c multicast_packet_cache.c \ + maodv_neighbor.c SRC_NS = debug.c list.c timer_queue.c aodv_socket.c aodv_hello.c \ aodv_neighbor.c aodv_timeout.c routing_table.c seek_list.c \ @@ -33,7 +36,8 @@ # Comment out to disable debug operation... DEBUG=-g -DDEBUG -DEFS=#-DUSE_IW_SPY +DEFS= -DMAODV #-DUSE_IW_SPY + CFLAGS=$(OPTS) $(DEBUG) $(DEFS) ifneq (,$(findstring USE_IW_SPY,$(DEFS))) @@ -63,13 +67,14 @@ # These are the options for the kernel modules: #============================================== KINC=-nostdinc $(shell $(CC) -print-search-dirs | sed -ne 's/install: \(.*\)/-I \1include/gp') -I/lib/modules/$(KERNEL)/build/include -KDEFS=-D__KERNEL__ -DMODULE +KDEFS=-D__KERNEL__ -DMODULE -DMAODV KCFLAGS=-Wall -O2 $(KDEFS) $(KINC) KCFLAGS_ARM =-Wall -O2 -D__KERNEL__ -DMODULE $(KINC) -.PHONY: default clean install uninstall depend tags aodvd-arm docs +# .PHONY used to have a docs target in it, I removed it, we got no docs... +.PHONY: default clean install uninstall depend tags aodvd-arm -default: aodvd kaodv.o +default: aodvd kaodv.o kinject.o all: default @@ -106,6 +111,10 @@ kaodv.o: kaodv.c $(CC) $(KCFLAGS) -c -o $@ $< +# Kernel module for packet injection: +kinject.o: kinject.c + $(CC) $(KCFLAGS) -c -o $@ $< + kaodv-arm.o: kaodv.c $(ARM_CC) $(KCFLAGS_ARM) -c -o $(@:%-arm.o=%.o) $< tags: @@ -117,6 +126,7 @@ @echo "Updating Makefile dependencies..." @makedepend -Y./ -- $(DEFS) -- $(SRC) &>/dev/null @makedepend -a -Y./ -- $(KDEFS) kaodv.c &>/dev/null + @makedepend -a -Y./ -- $(KDEFS) kinject.c &>/dev/null install: all install -s -m 755 aodvd /usr/sbin/aodvd @@ -124,14 +134,16 @@ mkdir /lib/modules/$(KERNEL)/aodv; \ fi install -m 644 kaodv.o /lib/modules/$(KERNEL)/aodv/kaodv.o + install -m 644 kinject.o /lib/modules/$(KERNEL)/aodv/kinject.o /sbin/depmod -a uninstall: rm -f /usr/sbin/aodvd rm -rf /lib/modules/$(KERNEL)/aodv -docs: - cd docs && $(MAKE) all +# Commented out, we don't have any documentation... yet. +#docs: +# cd docs && $(MAKE) all clean: rm -f aodvd *~ *.o core *.log libaodv-uu.a endian endian.h #cd docs && $(MAKE) clean diff -urNb aodv-uu-0.7.2/TODO.maodv maodv-umd-0.7.2/TODO.maodv --- aodv-uu-0.7.2/TODO.maodv Wed Dec 31 19:00:00 1969 +++ maodv-umd-0.7.2/TODO.maodv Wed Jun 25 17:46:09 2003 @@ -0,0 +1,20 @@ +MAODV TODO +? expire unactivated nexthops +* out of spec. umd additions + * mact-ack + * tree optimization +* ns-2 maybe... +* more tests... + +MAODV KNOWN LIMITATIONS +* one way link breaks +* cannot handle multiple interfaces (although the protocol is + at least ill-definied when multiple interfaces are used) + +CONCERNS AODV-UU +* ratelimiting seems broken. +* setting the d flag for RREQ breaks things. Incorrect destination + reply code. + +DRAW STUFF +* draw-all needs per-group timeouts diff -urNb aodv-uu-0.7.2/aodv_hello.c maodv-umd-0.7.2/aodv_hello.c --- aodv-uu-0.7.2/aodv_hello.c Mon May 26 16:45:49 2003 +++ maodv-umd-0.7.2/aodv_hello.c Wed Jun 25 17:46:09 2003 @@ -106,14 +106,15 @@ for (i = 0; i < MAX_NR_INTERFACES; i++) { if (!DEV_NR(i).enabled) continue; -#ifdef DEBUG_HELLO +/* #ifdef DEBUG_HELLO */ DEBUG(LOG_DEBUG, 0, "sending Hello to %s", ip_to_str(AODV_BROADCAST)); -#endif +/* #endif */ rrep = rrep_create(flags, 0, 0, DEV_NR(i).ipaddr, this_host.seqno, DEV_NR(i).ipaddr, - ALLOWED_HELLO_LOSS * HELLO_INTERVAL); + ALLOWED_HELLO_LOSS * HELLO_INTERVAL, + 0 ); /* Assemble a RREP extension which contain our neighbor set... */ if (unidir_hack) { @@ -167,7 +168,6 @@ } } - /* Process a hello message */ void NS_CLASS hello_process(RREP * hello, int rreplen, unsigned int ifindex) { @@ -232,10 +232,10 @@ ext = AODV_EXT_NEXT(ext); } -#ifdef DEBUG_HELLO +/* #ifdef DEBUG_HELLO */ DEBUG(LOG_DEBUG, 0, "rcvd HELLO from %s, seqno %lu", ip_to_str(hello_dst), hello_seqno); -#endif +/* #endif */ /* This neighbor should only be valid after receiving 3 consecutive hello messages... */ if (receive_n_hellos) @@ -289,6 +289,71 @@ return; } +/* Process a broadcast message */ +void NS_CLASS bcast_process(u_int32_t addr, + int ifindex) +{ + u_int32_t hello_interval = HELLO_INTERVAL; + u_int32_t timeout; + u_int8_t state, flags = 0; + rt_table_t *rt; + struct timeval now; + + gettimeofday(&now, NULL); + + DEBUG(LOG_DEBUG, 0, "rcvd BCAST from %s", + ip_to_str(addr)); + + /* This neighbor should only be valid after receiving 3 + consecutive hello messages... */ + if (receive_n_hellos) + state = INVALID; + else + state = VALID; + + timeout = ALLOWED_HELLO_LOSS * hello_interval + ROUTE_TIMEOUT_SLACK; + + if ((rt = rt_table_find(addr)) == NULL) { + /* No active or expired route in the routing table. So we add a + new entry... */ + + /* seqno == 0 because we have no idea... */ + rt = rt_table_insert(addr, addr, 1, 0, timeout, + state, flags, ifindex); + + if (flags & RT_UNIDIR) + DEBUG(LOG_INFO, 0, "%s new NEIGHBOR, link UNI-DIR", + ip_to_str(rt->dest_addr)); + else + DEBUG(LOG_INFO, 0, "%s new NEIGHBOR!", ip_to_str(rt->dest_addr)); + + rt->hello_cnt = 1; + } else { + + if ((flags & RT_UNIDIR) && rt->state == VALID && rt->hcnt > 1) { + goto hello_update; + } + + if (receive_n_hellos && rt->hello_cnt < (receive_n_hellos - 1)) { + if (timeval_diff(&now, &rt->last_hello_time) < + (long) (hello_interval + hello_interval / 2)) + rt->hello_cnt++; + else + rt->hello_cnt = 1; + + rt->last_hello_time = now; + return; + } + rt_table_update(rt, addr, 1, rt->dest_seqno, timeout, VALID, + flags); + } + + hello_update: + + hello_update_timeout(rt, ALLOWED_HELLO_LOSS * hello_interval); + rt->last_hello_time = now; + return; +} #define HELLO_DELAY 50 /* The extra time we should allow an hello message to take (due to processing) before diff -urNb aodv-uu-0.7.2/aodv_hello.h maodv-umd-0.7.2/aodv_hello.h --- aodv-uu-0.7.2/aodv_hello.h Thu May 22 19:11:34 2003 +++ maodv-umd-0.7.2/aodv_hello.h Wed Jun 25 17:46:09 2003 @@ -38,8 +38,7 @@ void hello_stop(); void hello_send(void *arg); void hello_process(RREP * hello, int rreplen, unsigned int ifindex); -void hello_process_non_hello(AODV_msg * aodv_msg, u_int32_t source, - unsigned int ifindex); +void NS_CLASS bcast_process(u_int32_t addr, int ifindex); NS_INLINE void hello_update_timeout(rt_table_t * rt, long time); #ifdef NS_PORT diff -urNb aodv-uu-0.7.2/aodv_neighbor.c maodv-umd-0.7.2/aodv_neighbor.c --- aodv-uu-0.7.2/aodv_neighbor.c Tue May 27 12:32:58 2003 +++ maodv-umd-0.7.2/aodv_neighbor.c Wed Jun 25 17:46:09 2003 @@ -43,6 +43,7 @@ rt_table_t *rt = NULL; u_int32_t seqno = 0; int flags = 0; + struct timeval now; /* According to the draft, the seqno should always be set to * invalid when adding neighbors... */ @@ -69,6 +70,12 @@ rt_table_update(rt, source, 1, seqno, ACTIVE_ROUTE_TIMEOUT, VALID, flags); } + + gettimeofday(&now, NULL); + hello_update_timeout(rt, ALLOWED_HELLO_LOSS * HELLO_INTERVAL); + rt->last_hello_time = now; + + DEBUG( LOG_DEBUG, 0, "Updated bcast/HELLO timer for %s", ip_to_str( source ) ); if (!llfeedback) hello_update_timeout(rt, ALLOWED_HELLO_LOSS * HELLO_INTERVAL); diff -urNb aodv-uu-0.7.2/aodv_rrep.c maodv-umd-0.7.2/aodv_rrep.c --- aodv-uu-0.7.2/aodv_rrep.c Tue May 27 12:32:58 2003 +++ maodv-umd-0.7.2/aodv_rrep.c Wed Jun 25 17:46:09 2003 @@ -38,6 +38,13 @@ extern int unidir_hack, optimized_hellos, llfeedback; +#ifdef MAODV +#include "maodv_rrep.h" +#include "maodv_ext.h" +#include "maodv_mact.h" +#include "seek_list.h" +#endif + #endif RREP *NS_CLASS rrep_create(u_int8_t flags, @@ -46,9 +53,14 @@ u_int32_t dest_addr, u_int32_t dest_seqno, u_int32_t orig_addr, - u_int32_t life) + u_int32_t life, + u_int32_t grp_addr ) { RREP *rrep; +#ifdef MAODV + int size = RREP_SIZE; + GRP_MERGE_EXT * gme; +#endif rrep = (RREP *) aodv_socket_new_msg(); rrep->type = AODV_RREP; @@ -66,6 +78,19 @@ if (flags & RREP_ACK) rrep->a = 1; +#ifdef MAODV + if ( rrep->r ) { + /* add group merge extension */ + gme = (GRP_MERGE_EXT *) ((char *)rrep + size); + gme->type = GME_TYPE; + gme->length = GME_LENGTH; + gme->res = 0; + gme->grp_addr = htonl(grp_addr); + + size += GME_LENGTH + 2; /* length + "header" */ + } +#endif /* MAODV */ + /* Don't print information about hello messages... */ #ifdef DEBUG_OUTPUT if (dest_addr != orig_addr) { @@ -107,13 +132,15 @@ timer_remove(&rt->ack_timer); } -void NS_CLASS rrep_send(rt_table_t * rev_rt, rt_table_t * fwd_rt) +void NS_CLASS rrep_send(rt_table_t * rev_rt, rt_table_t * fwd_rt, + u_int16_t flags, u_int32_t grp_addr ) { RREP *rrep; - u_int8_t rrep_flags = 0; + u_int8_t rrep_flags = flags; u_int32_t seqno, dest, lifetime; int hcnt; struct timeval now; + int size = RREP_SIZE; if (!rev_rt) { DEBUG(LOG_WARNING, 0, "Can't send RREP, rev_rt = NULL!"); @@ -165,9 +192,16 @@ ip_to_str(dest)); rrep = rrep_create(rrep_flags, 0, hcnt, dest, seqno, rev_rt->dest_addr, - lifetime); + lifetime, grp_addr ); + +#ifdef MAODV + if ( rrep_flags & RREP_REPAIR ) { + DEBUG( LOG_DEBUG, 0, "RREP_GRP_MERGE_EXT set." ); + size += GRP_MERGE_EXT_SIZE; + } +#endif /* MAODV */ - aodv_socket_send((AODV_msg *) rrep, rev_rt->next_hop, RREP_SIZE, MAXTTL, + aodv_socket_send((AODV_msg *) rrep, rev_rt->next_hop, size, MAXTTL, &DEV_IFINDEX(rev_rt->ifindex)); /* Update precursor lists */ @@ -181,7 +215,7 @@ } void NS_CLASS rrep_forward(RREP * rrep, rt_table_t * rev_rt, - rt_table_t * fwd_rt, int ttl) + rt_table_t * fwd_rt, int ttl, int size ) { /* Sanity checks... */ if (!fwd_rt || !rev_rt) { @@ -220,10 +254,10 @@ } } - rrep = (RREP *) aodv_socket_queue_msg((AODV_msg *) rrep, RREP_SIZE); + rrep = (RREP *) aodv_socket_queue_msg((AODV_msg *) rrep, size); rrep->hcnt = fwd_rt->hcnt; /* Update the hopcount */ - aodv_socket_send((AODV_msg *) rrep, rev_rt->next_hop, RREP_SIZE, ttl, + aodv_socket_send((AODV_msg *) rrep, rev_rt->next_hop, size, ttl, &DEV_IFINDEX(rev_rt->ifindex)); precursor_add(fwd_rt, rev_rt->next_hop); @@ -239,6 +273,16 @@ u_int32_t rrep_dest, rrep_orig, rrep_lifetime, rrep_seqno, rrep_new_hcnt; u_int8_t pre_repair_hcnt = 0, pre_repair_flags = 0; rt_table_t *fwd_rt, *rev_rt; + int size = rreplen; + + AODV_ext * ext; + +#ifdef MAODV + GRP_MERGE_EXT * gmg_ext = NULL; + u_int32_t grp_addr; + + grp_addr = 0; +#endif /* Convert to correct byte order on affeected fields: */ rrep_dest = ntohl(rrep->dest_addr); @@ -265,6 +309,47 @@ log_pkt_fields((AODV_msg *) rrep); #endif + ext = (AODV_ext *) ((char *) rrep + RREP_SIZE); + + while( rreplen > (int) RREP_SIZE ) { + switch(ext->type) { +#ifdef MAODV + case RREP_GRP_MERGE_EXT: + DEBUG(LOG_INFO, 0, "RREP includes group merge extension." ); + gmg_ext = (GRP_MERGE_EXT *) ext; + if ( gmg_ext->length != GME_LENGTH ) { + DEBUG(LOG_DEBUG, 0, "Wrong length[%d] for gmg_ext.", + gmg_ext->length ); + gmg_ext = NULL; + } else { + grp_addr = ntohl(gmg_ext->grp_addr); + } + break; +#endif + default: + log(LOG_WARNING, 0, __FUNCTION__, "Unknown extension type %d", + ext->type); + break; + } + rreplen -= AODV_EXT_SIZE(ext); + ext = AODV_EXT_NEXT(ext); + } + +#ifdef MAODV + if ( IN_MULTICAST( rrep_dest ) ) { + DEBUG(LOG_DEBUG, 0, "MAODV rrep process." ); + maodv_rrep_process( rrep, rreplen, ip_src, ip_dst, ip_ttl, + ifindex, size); + +#ifndef AODVUU_LL_FEEDBACK + if (optimized_hellos) + hello_start(); +#endif + + return; + } +#endif + /* ---------- CHECK IF WE SHOULD MAKE A FORWARD ROUTE ------------ */ fwd_rt = rt_table_find(rrep_dest); @@ -288,8 +373,13 @@ DEBUG(LOG_DEBUG, 0, "Dropping RREP, fwd_rt->hcnt=%d fwd_rt->seqno=%ld", fwd_rt->hcnt, fwd_rt->dest_seqno); } + + if ( rrep->r ) { + DEBUG(LOG_DEBUG, 0, "Special RREP for group merge. Accepting despite an existing route." ); + } else { return; } + } /* If the RREP_ACK flag is set we must send a RREP @@ -327,11 +417,102 @@ RERR_CALC_SIZE(rerr), 1, &DEV_IFINDEX(fwd_rt->ifindex)); } + } else { +#ifdef MAODV + mrt_table_t *mrt; + + if ( (gmg_ext != NULL) && + (mrt = mrt_table_find(grp_addr)) && + rrep->r ) { + mrt_nexthop_t *upstream; + + DEBUG(LOG_DEBUG, 0, "in gmg_ext processing section"); + DEBUG(LOG_DEBUG, 0, "grp_addr: %s", ip_to_str(grp_addr)); + + /* make ip_src upstream */ + upstream=mrt_table_get_activated_upstream(mrt); + if(upstream!=NULL){ + mrt_nexthop_deactivate(mrt, upstream->addr); + } + + upstream=mrt_nexthop_find(mrt, ip_src); + if(upstream==NULL){ + upstream=mrt_nexthop_add(mrt, ip_src, MRT_UPSTREAM, 0); + } + + if(upstream->activated){ + mrt_nexthop_deactivate(mrt, upstream->addr); + } + upstream->direction=MRT_UPSTREAM; + + mrt_nexthop_activate(mrt, upstream->addr); + + /* send mact */ + mact_send(MACT_JOIN, 1, grp_addr, ip_src, 1); + + /* route is repaired */ + mrt->in_repair=0; + + /* stop being leader */ + mrt->am_leader = 0; + + DEBUG( LOG_DEBUG, 0, "Giving up leadership to other leader." ); + DEBUG( LOG_DEBUG, 0, "grp_addr: %s", ip_to_str(grp_addr) ); + + seek_list_remove_mcast(rrep_dest, grp_addr); + } +#endif /* MAODV */ } } else { /* --- Here we FORWARD the RREP on the REVERSE route --- */ if (rev_rt && rev_rt->state == VALID) { - rrep_forward(rrep, rev_rt, fwd_rt, --ip_ttl); +#ifdef MAODV + if ( rrep->r ) { + /* make old activated upstream a downstream? or let mact? */ + mrt_table_t *mrt; + + DEBUG(LOG_DEBUG, 0, "grp_addr: %s", ip_to_str(grp_addr)); + + if ( (gmg_ext != NULL) && + (mrt = mrt_table_find(grp_addr)) && + rrep->r ) { + mrt_nexthop_t *upstream; + + DEBUG(LOG_DEBUG, 0, "in gmg_ext processing section"); + DEBUG(LOG_DEBUG, 0, "grp_addr: %s", ip_to_str(grp_addr)); + + /* make ip_src upstream */ + upstream=mrt_table_get_activated_upstream(mrt); + if(upstream!=NULL){ + mrt_nexthop_deactivate(mrt, upstream->addr); + } + + upstream=mrt_nexthop_find(mrt, ip_src); + if(upstream==NULL){ + upstream=mrt_nexthop_add(mrt, ip_src, + MRT_UPSTREAM, 0); + } + + if(upstream->activated){ + mrt_nexthop_deactivate(mrt, upstream->addr); + } + upstream->direction=MRT_UPSTREAM; + + mrt_table_start_routing(mrt); + + mrt_nexthop_activate(mrt, upstream->addr); + + /* send mact */ + mact_send(MACT_JOIN, 1, grp_addr, ip_src, 1); + + /* update GL information */ + /* GRPH->u */ + } + } + rrep_forward(rrep, rev_rt, fwd_rt, --ip_ttl, size); +#else /* MAODV */ + rrep_forward(rrep, rev_rt, fwd_rt, --ip_ttl, size); +#endif /* MAODV */ } else { DEBUG(LOG_DEBUG, 0, "Could not forward RREP - NO ROUTE!!!"); } diff -urNb aodv-uu-0.7.2/aodv_rrep.h maodv-umd-0.7.2/aodv_rrep.h --- aodv-uu-0.7.2/aodv_rrep.h Thu May 22 19:11:35 2003 +++ maodv-umd-0.7.2/aodv_rrep.h Wed Jun 25 17:46:09 2003 @@ -72,12 +72,14 @@ u_int8_t prefix, u_int8_t hcnt, u_int32_t dest_addr, - u_int32_t dest_seqno, u_int32_t orig_addr, u_int32_t life); + u_int32_t dest_seqno, u_int32_t orig_addr, u_int32_t life, + u_int32_t grp_addr ); RREP_ack *rrep_ack_create(); -void rrep_send(rt_table_t * rev_rt, rt_table_t * fwd_rt); +void rrep_send(rt_table_t * rev_rt, rt_table_t * fwd_rt, u_int16_t flags, + u_int32_t grp_addr ); void rrep_forward(RREP * rrep, rt_table_t * rev_rt, rt_table_t * fwd_rt, - int ttl); + int ttl, int size ); void rrep_process(RREP * rrep, int rreplen, u_int32_t ip_src, u_int32_t ip_dst, int ip_ttl, unsigned int ifindex); void rrep_ack_process(RREP_ack * rrep_ack, int rreplen, u_int32_t ip_src, diff -urNb aodv-uu-0.7.2/aodv_rreq.c maodv-umd-0.7.2/aodv_rreq.c --- aodv-uu-0.7.2/aodv_rreq.c Thu May 22 19:11:35 2003 +++ maodv-umd-0.7.2/aodv_rreq.c Fri Dec 5 17:42:32 2003 @@ -25,6 +25,7 @@ #include "aodv-uu.h" #else #include +#include #include "aodv_rreq.h" #include "aodv_rrep.h" #include "routing_table.h" @@ -36,6 +37,14 @@ #include "seek_list.h" #include "defs.h" #include "debug.h" + + +#ifdef MAODV +#include "multicast_routing_table.h" +#include "maodv_rreq.h" +#include "maodv_ext.h" +#endif + #endif /* Comment this to remove packet field output: */ @@ -57,9 +66,15 @@ #endif RREQ *NS_CLASS rreq_create(u_int8_t flags, u_int32_t dest_addr, - u_int32_t dest_seqno, u_int32_t orig_addr) + u_int32_t dest_seqno, u_int32_t orig_addr, + u_int16_t grp_hcnt, u_int32_t grp_addr ) { RREQ *rreq; +#ifdef MAODV + int size = RREQ_SIZE; + GRP_REBUILD_EXT * gre; + GRP_MERGE_EXT * gme; +#endif rreq = (RREQ *) aodv_socket_new_msg(); rreq->type = AODV_RREQ; @@ -86,6 +101,30 @@ if (flags & RREQ_UNKNOWN_SEQNO) rreq->u = 1; +#ifdef MAODV + + if (flags & RREQ_GRP_REBUILD ) { + gre = (GRP_REBUILD_EXT *) ((char *) rreq + size); + gre->type = GRE_TYPE; + gre->length = GRE_LENGTH; + gre->grp_hcnt = htons(grp_hcnt); + + size += GRP_REBUILD_EXT_SIZE; + } + + if ( rreq->r && rreq->j ) { + /* add merge extension */ + gme = (GRP_MERGE_EXT *) ((char *) rreq + size); + gme->type = GME_TYPE; + gme->length = GME_LENGTH; + gme->res = 0; + gme->grp_addr = htonl(grp_addr); + + size += GRP_MERGE_EXT_SIZE; + } + +#endif /* MAODV */ + DEBUG(LOG_DEBUG, 0, "Assembled RREQ %s", ip_to_str(dest_addr)); #ifdef DEBUG_OUTPUT log_pkt_fields((AODV_msg *) rreq); @@ -94,6 +133,44 @@ return rreq; } +void NS_CLASS rreq_send_ext(u_int32_t dest_addr, u_int32_t dest_seqno, + int ttl, u_int8_t flags, u_int16_t grp_hcnt, + u_int32_t grp_addr ) +{ + RREQ *rreq; + int i; + int size = RREQ_SIZE; + + /* Check if we should force the gratuitous flag... (-g option). */ + if (rreq_gratuitous) + flags |= RREQ_GRATUITOUS; + +#ifdef MAODV + + if ( flags & RREQ_GRP_REBUILD ) { + DEBUG( LOG_DEBUG, 0, "RREQ_GRP_REBUILD_EXT set." ); + size += GRP_REBUILD_EXT_SIZE; + } + + if ( (flags & RREQ_JOIN) && (flags & RREQ_REPAIR) ) { + DEBUG( LOG_DEBUG, 0, "RREQ_GRP_MERGE_EXT set, group %s", ip_to_str(grp_addr) ); + size += GRP_MERGE_EXT_SIZE; + } + +#endif /* MAODV */ + + /* Broadcast on all interfaces */ + for (i = 0; i < MAX_NR_INTERFACES; i++) { + if (!DEV_NR(i).enabled) + continue; + rreq = rreq_create(flags, dest_addr, dest_seqno, DEV_NR(i).ipaddr, + grp_hcnt, grp_addr ); + + aodv_socket_send((AODV_msg *) rreq, AODV_BROADCAST, size, + ttl, &DEV_NR(i) ); + } +} + void NS_CLASS rreq_send(u_int32_t dest_addr, u_int32_t dest_seqno, int ttl, u_int8_t flags) { @@ -108,13 +185,14 @@ for (i = 0; i < MAX_NR_INTERFACES; i++) { if (!DEV_NR(i).enabled) continue; - rreq = rreq_create(flags, dest_addr, dest_seqno, DEV_NR(i).ipaddr); + rreq = rreq_create(flags, dest_addr, dest_seqno, DEV_NR(i).ipaddr, + 0, 0 ); aodv_socket_send((AODV_msg *) rreq, AODV_BROADCAST, RREQ_SIZE, ttl, &DEV_NR(i)); } } -void NS_CLASS rreq_forward(RREQ * rreq, int ttl) +void NS_CLASS rreq_forward(RREQ * rreq, int ttl, int size ) { int i; /* FORWARD the RREQ if the TTL allows it. */ @@ -122,7 +200,7 @@ ip_to_str(ntohl(rreq->orig_addr)), ntohl(rreq->rreq_id)); /* Queue the received message in the send buffer */ - rreq = (RREQ *) aodv_socket_queue_msg((AODV_msg *) rreq, RREQ_SIZE); + rreq = (RREQ *) aodv_socket_queue_msg((AODV_msg *) rreq, size ); rreq->hcnt++; /* Increase hopcount to account for * intermediate route */ @@ -131,10 +209,35 @@ for (i = 0; i < MAX_NR_INTERFACES; i++) { if (!DEV_NR(i).enabled) continue; - aodv_socket_send((AODV_msg *) rreq, AODV_BROADCAST, RREQ_SIZE, ttl, + aodv_socket_send((AODV_msg *) rreq, AODV_BROADCAST, size, ttl, + &DEV_NR(i)); + } +} + +#ifdef MAODV +void NS_CLASS rreq_forward_uni(RREQ * rreq, u_int32_t dest, int ttl, + int size ) +{ + int i; + /* FORWARD the RREQ if the TTL allows it. */ + DEBUG(LOG_INFO, 0, "forwarding RREQ src=%s, rreq_id=%lu", + ip_to_str(ntohl(rreq->orig_addr)), ntohl(rreq->rreq_id)); + + /* Queue the received message in the send buffer */ + rreq = (RREQ *) aodv_socket_queue_msg((AODV_msg *) rreq, size ); + + rreq->hcnt++; /* Increase hopcount to account for + * intermediate route */ + + /* Send out on all interfaces */ + for (i = 0; i < MAX_NR_INTERFACES; i++) { + if (!DEV_NR(i).enabled) + continue; + aodv_socket_send((AODV_msg *) rreq, AODV_BROADCAST, size, ttl, &DEV_NR(i)); } } +#endif /* MAODV */ void NS_CLASS rreq_process(RREQ * rreq, int rreqlen, u_int32_t ip_src, u_int32_t ip_dst, int ip_ttl, unsigned int ifindex) @@ -144,6 +247,14 @@ rt_table_t *rev_rt, *fwd_rt = NULL; u_int32_t rreq_orig, rreq_dest, rreq_orig_seqno, rreq_dest_seqno; u_int32_t rreq_id, rreq_new_hcnt, life; + int size; +#ifdef MAODV + GRP_REBUILD_EXT *grb_ext=NULL; + GRP_MERGE_EXT *gmg_ext=NULL; + u_int32_t grp_addr; + + grp_addr = 0; +#endif rreq_id = ntohl(rreq->rreq_id); rreq_dest = ntohl(rreq->dest_addr); @@ -152,6 +263,7 @@ rreq_orig_seqno = ntohl(rreq->orig_seqno); rreq_new_hcnt = rreq->hcnt + 1; + size = rreqlen; DEBUG(LOG_DEBUG, 0, "ip_src=%s rreq_orig=%s rreq_dest=%s", ip_to_str(ip_src), ip_to_str(rreq_orig), ip_to_str(rreq_dest)); @@ -193,14 +305,36 @@ DEBUG(LOG_INFO, 0, "RREQ include EXTENSION"); /* Do something here */ break; +#ifdef MAODV + case RREQ_GRP_REBUILD_EXT: + DEBUG(LOG_INFO, 0, "RREQ includes group rebuild extension"); + grb_ext=(GRP_REBUILD_EXT*)ext; + if(grb_ext->length!=GRE_LENGTH) { + grb_ext=NULL; + } + break; + case RREQ_GRP_MERGE_EXT: + DEBUG(LOG_INFO, 0, "RREQ includes group merge extension" ); + gmg_ext = (GRP_MERGE_EXT *) ext; + if ( gmg_ext->length != GME_LENGTH ) { + gmg_ext = NULL; + } else { + grp_addr = ntohl(gmg_ext->grp_addr); + } + break; +#endif default: - log(LOG_WARNING, 0, __FUNCTION__, "Unknown extension type %d", - ext->type); + log(LOG_WARNING, 0, __FUNCTION__, "Unknown extension type." ); break; } rreqlen -= AODV_EXT_SIZE(ext); ext = AODV_EXT_NEXT(ext); } + +#ifdef MAODV + DEBUG(LOG_DEBUG, 0, "grp_addr: %s", ip_to_str(grp_addr)); +#endif /* MAODV */ + #ifdef DEBUG_OUTPUT log_pkt_fields((AODV_msg *) rreq); #endif @@ -239,14 +373,17 @@ } /**** END updating/creating REVERSE route ****/ - /* BAD HACK for Internet gateway support: */ - if (internet_gw_mode && - this_host.gateway_mode && - (rreq_dest & DEV_IFINDEX(ifindex).netmask) != - (DEV_IFINDEX(ifindex).ipaddr & DEV_IFINDEX(ifindex).netmask)) { - rrep_send(rev_rt, NULL); +#ifdef MAODV + if ( IN_MULTICAST(rreq_dest) ) { + DEBUG(LOG_DEBUG, 0, "MAODV RREQ process."); + /* TODO: Added multicast rreq support. */ + maodv_rreq_process( rreq, rreqlen, ip_src, ip_dst, + ip_ttl, ifindex, grb_ext, size ); + return; } +#endif + /* Are we the destination of the RREQ?, if so we should immediately send a RREP.. */ if (rreq_dest == DEV_IFINDEX(ifindex).ipaddr) { @@ -254,15 +391,47 @@ /* WE are the RREQ DESTINATION. Update the node's own sequence number to the maximum of the current seqno and the one in the RREQ. */ - if (!rreq->u && this_host.seqno < rreq_dest_seqno) - this_host.seqno = rreq_dest_seqno; + if (!rreq->u && this_host.seqno == rreq_dest_seqno) + this_host.seqno++; - rrep_send(rev_rt, NULL); +#ifdef MAODV + if ((rreq->j) && (rreq->r) && (gmg_ext != NULL)) { + mrt_table_t *mrt; + mrt=mrt_table_find(grp_addr); + if(mrt->am_leader && !mrt->in_repair){ + /* recieved a rreq because i'm leader */ + DEBUG(LOG_DEBUG, 0, "Received a RREQ[j] for me. Should send RREP for group."); + /* make GRPH flag update */ + mrt->grph_update_cnt=2; + rrep_send(rev_rt, NULL, RREP_REPAIR, grp_addr ); + } + } else { + rrep_send(rev_rt, NULL, 0, 0); + } +#else /* MAODV */ + rrep_send(rev_rt, NULL, 0, 0); +#endif /* MAODV */ } else { - /* We are an INTERMEDIATE node. - check if we have an active - * route entry */ + /* We are an intermediate node, first check if being gatewayed */ + + /* Internet gateway support: */ + if (internet_gw_mode && this_host.gateway_mode && + (rreq_dest & DEV_IFINDEX(ifindex).netmask) != + (DEV_IFINDEX(ifindex).ipaddr & DEV_IFINDEX(ifindex).netmask)) { + printf("In here!!!\n"); + int metric = get_route_metric(rreq->dest_addr); + if(metric >= 0) { + printf("Good metric!!!\n"); + RREP *rrep = rrep_create(0, 0, ++metric, rreq_dest, + ++this_host.seqno, rev_rt->dest_addr, MY_ROUTE_TIMEOUT, 0); + aodv_socket_send((AODV_msg*)rrep, rev_rt->next_hop, RREP_SIZE, + MAXTTL, &DEV_IFINDEX(rev_rt->ifindex)); + return; + } + } + /* check if we have an active route entry */ fwd_rt = rt_table_find(rreq_dest); if (fwd_rt && fwd_rt->state == VALID && !rreq->d && @@ -273,12 +442,12 @@ enough (our destination sequence number for that route is larger than the one in the RREQ). */ - rrep_send(rev_rt, fwd_rt); + rrep_send(rev_rt, fwd_rt, 0, 0); /* If the GRATUITOUS flag is set, we must also unicast a gratuitous RREP to the destination. */ if (rreq->g) { - rrep_send(fwd_rt, rev_rt); + rrep_send(fwd_rt, rev_rt, 0, 0); DEBUG(LOG_INFO, 0, "Sending G-RREP to %s with rte to %s", ip_to_str(rreq_dest), ip_to_str(rreq_orig)); @@ -292,7 +461,38 @@ rreq->u = 0; } - rreq_forward(rreq, --ip_ttl); +#ifdef MAODV + if (( rreq->j ) && ( rreq->r ) && (gmg_ext != NULL)) { + mrt_table_t * mrt; + mrt_nexthop_t * upstream; + + /* if I am part of group, unicast up. */ + /* else regular rreq */ + DEBUG( LOG_DEBUG, 0, "Recieved a RREQ[jr], forwarding." ); + + mrt = mrt_table_find( grp_addr ); + if (( mrt != NULL ) && + ( mrt->grp_leader_addr == rreq_dest ) && + ( mrt->is_router ) ) { + /* one of the members of the >ip tree */ + + /* find activated upstream */ + upstream = mrt_table_get_activated_upstream( mrt ); + if ( ! upstream ) { + DEBUG( LOG_DEBUG, 0, "Odd State: no activated upstream, but not leader..." ); + } else { + rreq_forward_uni(rreq, upstream->addr, --ip_ttl, size ); + } + } else { + /* not part of > ip tree, just forward along */ + rreq_forward(rreq, --ip_ttl, size ); + } + } else { + rreq_forward(rreq, --ip_ttl, size ); + } +#else /* MAODV */ + rreq_forward(rreq, --ip_ttl, size ); +#endif /* MAODV */ } else { DEBUG(LOG_DEBUG, 0, "RREQ not forwarded - ttl=0"); @@ -303,7 +503,7 @@ /* Perform route discovery for a unicast destination */ void NS_CLASS rreq_route_discovery(u_int32_t dest_addr, u_int8_t flags, - struct ip_data *ipd) + struct ip_data *ipd, u_int32_t grp_addr) { struct timeval now; rt_table_t *rt; @@ -311,26 +511,51 @@ u_int32_t dest_seqno; int ttl; #define TTL_VALUE ttl + u_int16_t grp_hcnt; + +#ifdef MAODV + mrt_table_t *mrt; +#endif /* MAODV */ gettimeofday(&now, NULL); +#ifdef MAODV + /* for non-merge RREQs, grp_addr should always be zero, so + seek_list_find_mcast will act like seek_list_find. */ + if(seek_list_find_mcast(dest_addr, grp_addr)) + return; +#else if (seek_list_find(dest_addr)) return; +#endif /* If we already have a route entry, we use information from it. */ rt = rt_table_find(dest_addr); + grp_hcnt = 0; + +#ifdef MAODV + mrt = NULL; + if(IN_MULTICAST(dest_addr)) { + mrt = mrt_table_find(dest_addr); + } +#endif + ttl = NET_DIAMETER; /* This is the TTL if we don't use expanding ring search */ +#ifdef MAODV + if((rt == NULL) && (mrt == NULL)) { +#else if (rt == NULL) { +#endif flags |= RREQ_UNKNOWN_SEQNO; dest_seqno = 0; if (expanding_ring_search) ttl = TTL_START; - } else { + } else if(rt != NULL) { if (rt->flags & RT_INV_SEQNO) { flags |= RREQ_UNKNOWN_SEQNO; @@ -346,12 +571,44 @@ if (timeval_diff(&rt->rt_timer.timeout, &now) < (2 * NET_TRAVERSAL_TIME)) rt_table_update_timeout(rt, 2 * NET_TRAVERSAL_TIME); + +#ifndef MAODV } +#else + } else { - rreq_send(dest_addr, dest_seqno, ttl, flags); + if ( mrt->grp_seqno == 0 ) { + flags |= RREQ_UNKNOWN_SEQNO; + dest_seqno = 0; + } else + dest_seqno = mrt->grp_seqno; + + if (expanding_ring_search) { + if ( mrt->leader_hcnt == 0xff ) { + ttl = TTL_START; + } else { + ttl = mrt->leader_hcnt + TTL_INCREMENT; + } + } + + grp_hcnt = mrt->leader_hcnt; + + /* A routing table entry waiting for a RREP should not be expunged + before 2 * NET_TRAVERSAL_TIME... */ + /* CHECK: timeouts not happening yet. */ + /* + if (timeval_diff(&mrt->mrt_timer.timeout, &now) < + (2 * NET_TRAVERSAL_TIME)) + mrt_table_update_timeout(mrt, 2 * NET_TRAVERSAL_TIME); + */ + } +#endif /* MAODV */ + + rreq_send_ext(dest_addr, dest_seqno, ttl, flags, grp_hcnt, grp_addr); /* Remember that we are seeking this destination */ - seek_entry = seek_list_insert(dest_addr, dest_seqno, ttl, flags, ipd); + seek_entry = seek_list_insert(dest_addr, dest_seqno, ttl, flags, ipd, + grp_hcnt, grp_addr); /* Set a timer for this RREQ */ if (expanding_ring_search) @@ -416,7 +673,7 @@ /* Remember that we are seeking this destination and setup the timers */ seek_entry = seek_list_insert(rt->dest_addr, rt->dest_seqno, - ttl, flags, ipd); + ttl, flags, ipd, 0, 0); if (expanding_ring_search) timer_set_timeout(&seek_entry->seek_timer, @@ -528,3 +785,56 @@ list_detach(&bl->l); free(bl); } + +static int get_mask_bitlen(u_int32_t mask) { + int bits = 0; + while(mask) { + if(mask & 1) { + bits++; + } + mask >>= 1; + } + return bits; +} + +int get_route_metric(u_int32_t dest_addr) { + FILE *routes; + char buff[1024]; + u_int32_t dest, gw, mask, metric, flags; + int valid_entry = 0, valid_metric = -1, valid_bitlen = -1, bitlen; + + /* Open Linux route table for reading */ + routes = fopen("/proc/net/route", "r"); + if(routes == NULL) { + return -1; + } + + /* Read and discard header line */ + fgets(buff, sizeof(buff), routes); + while(!feof(routes)) { + fgets(buff, sizeof(buff), routes); + /* Iface Destination Gateway Flags RefCnt Use Metric + * Mask MTU Window IRTT */ + sscanf(buff, "%*s %x %x %x %*x %*x %x %x", &dest, &gw, &flags, + &metric, &mask); + if((flags & RTF_UP) && ((dest&mask) == (dest_addr&mask))) { + bitlen = get_mask_bitlen(mask); + if(!valid_entry) { + valid_entry++; + valid_metric = metric; + valid_bitlen = bitlen; + } else if(bitlen > valid_bitlen) { + valid_metric = metric; + valid_bitlen = bitlen; + } else if((bitlen == valid_bitlen) && (valid_metric > metric)) { + valid_metric = metric; + } + } + } + fclose(routes); + + /* If we found a matching, valid route, return its metric; otherwise, + * return an invalid metric (-1) */ + return valid_entry ? metric : -1; +} + diff -urNb aodv-uu-0.7.2/aodv_rreq.h maodv-umd-0.7.2/aodv_rreq.h --- aodv-uu-0.7.2/aodv_rreq.h Mon Jun 9 06:43:40 2003 +++ maodv-umd-0.7.2/aodv_rreq.h Thu Jul 17 18:03:41 2003 @@ -36,6 +36,7 @@ #define RREQ_GRATUITOUS 0x4 #define RREQ_DEST_ONLY 0x8 #define RREQ_UNKNOWN_SEQNO 0x10 +#define RREQ_GRP_REBUILD 0x20 typedef struct { u_int8_t type; @@ -84,25 +85,34 @@ #ifndef NS_NO_DECLARATIONS RREQ *rreq_create(u_int8_t flags, u_int32_t dest_addr, - u_int32_t dest_seqno, u_int32_t orig_addr); + u_int32_t dest_seqno, u_int32_t orig_addr, + u_int16_t grp_hcnt, u_int32_t grpaddr); +void rreq_send_ext(u_int32_t dest_addr, u_int32_t dest_seqno, int ttl, + u_int8_t flags, u_int16_t grp_hcnt, u_int32_t grp_addr); void rreq_send(u_int32_t dest_addr, u_int32_t dest_seqno, int ttl, u_int8_t flags); -void rreq_forward(RREQ * rreq, int ttl); +void rreq_forward(RREQ * rreq, int ttl, int size); void rreq_process(RREQ * rreq, int rreqlen, u_int32_t ip_src, u_int32_t ip_dst, int ip_ttl, unsigned int ifindex); void rreq_route_discovery(u_int32_t dest_addr, u_int8_t flags, - struct ip_data *ipd); + struct ip_data *ipd, u_int32_t grp_addr); void rreq_record_timeout(void *arg); struct blacklist *rreq_blacklist_insert(u_int32_t dest_addr); void rreq_blacklist_timeout(void *arg); void rreq_local_repair(rt_table_t * rt, u_int32_t src_addr, struct ip_data *ipd); +#ifdef MAODV +void NS_CLASS rreq_forward_uni(RREQ * rreq, u_int32_t dest, int ttl, int size); +#endif /* MAODV */ + #ifdef NS_PORT struct rreq_record *rreq_record_insert(u_int32_t orig_addr, u_int32_t rreq_id); struct rreq_record *rreq_record_find(u_int32_t orig_addr, u_int32_t rreq_id); struct blacklist *rreq_blacklist_find(u_int32_t dest_addr); #endif /* NS_PORT */ + +int get_route_metric(u_int32_t dest_addr); #endif /* NS_NO_DECLARATIONS */ diff -urNb aodv-uu-0.7.2/aodv_socket.c maodv-umd-0.7.2/aodv_socket.c --- aodv-uu-0.7.2/aodv_socket.c Wed Jun 18 15:41:38 2003 +++ maodv-umd-0.7.2/aodv_socket.c Mon Jun 30 13:53:46 2003 @@ -43,6 +43,12 @@ #ifdef USE_IW_SPY #include "link_qual.h" #endif + +#ifdef MAODV +#include "maodv_mact.h" +#include "maodv_grph.h" +#endif + #endif /* NS_PORT */ #ifndef NS_PORT @@ -93,10 +99,11 @@ } if (nleft == 1) - sum += *(unsigned char *) w; + sum += *(unsigned char*)w; sum = (sum >> 16) + (sum & 0xffff); sum += (sum >> 16); + return ~sum; } @@ -209,6 +216,8 @@ if ((aodv_msg->type == AODV_RREP && ttl == 1 && dst == AODV_BROADCAST)) { hello_process((RREP *) aodv_msg, len, ifindex); return; +/* } else if ( dst == AODV_BROADCAST ) { + bcast_process( src, ifindex ); */ } /* Make sure we add/update neighbors */ @@ -233,6 +242,16 @@ DEBUG(LOG_DEBUG, 0, "Received RREP_ACK"); rrep_ack_process((RREP_ack *) aodv_msg, len, src, dst); break; +#ifdef MAODV + case MAODV_MACT: + DEBUG(LOG_DEBUG, 0, "Received MACT"); + mact_process((MACT *) aodv_msg); + break; + case MAODV_GRPH: + DEBUG(LOG_DEBUG, 0, "Received GRPH"); + grph_process((GRPH *) aodv_msg, src, ttl); + break; +#endif default: log(LOG_WARNING, 0, __FUNCTION__, "Unknown msg type %u rcvd from %s to %s", aodv_msg->type, @@ -361,7 +380,7 @@ ip = (struct iphdr *) send_buf; ip->version = IPVERSION; ip->ihl = sizeof(struct iphdr) >> 2; - ip->tos |= IPTOS_PREC_NETCONTROL | IPTOS_LOWDELAY; /* Highest priority */ + ip->tos = IPTOS_PREC_NETCONTROL | IPTOS_LOWDELAY; /* Highest priority */ ip->tot_len = htons(totlen); ip->id = 0; /* Let IP set */ ip->frag_off = htons(0x4000); /* Set Do Not Fragment bit */ @@ -378,6 +397,7 @@ udp->dest = htons(AODV_PORT); udp->len = htons(len + sizeof(struct udphdr)); + udp->check = 0; udp->check = in_udp_csum(ip->saddr, ip->daddr, udp->len, ip->protocol, (unsigned short *)udp); diff -urNb aodv-uu-0.7.2/aodv_timeout.c maodv-umd-0.7.2/aodv_timeout.c --- aodv-uu-0.7.2/aodv_timeout.c Tue May 27 12:32:58 2003 +++ maodv-umd-0.7.2/aodv_timeout.c Wed Jun 25 17:46:09 2003 @@ -42,6 +42,12 @@ #include "seek_list.h" #include "icmp.h" +#ifdef MAODV +#include "multicast_routing_table.h" +#include "maodv_mact.h" +#include "maodv_neighbor.h" +#endif /* MAODV */ + extern int expanding_ring_search, local_repair; void route_delete_timeout(void *arg); @@ -54,6 +60,10 @@ struct timeval now; seek_list_t *seek_entry; rt_table_t *rt, *repair_rt; +#ifdef MAODV + u_int32_t dest_addr; +#endif + seek_entry = (seek_list_t *) arg; #define TTL_VALUE seek_entry->ttl @@ -97,10 +107,76 @@ (2 * NET_TRAVERSAL_TIME)) rt_table_update_timeout(rt, 2 * NET_TRAVERSAL_TIME); - rreq_send(seek_entry->dest_addr, seek_entry->dest_seqno, - TTL_VALUE, seek_entry->flags); + rreq_send_ext(seek_entry->dest_addr, seek_entry->dest_seqno, + seek_entry->ttl, seek_entry->flags, seek_entry->grp_hcnt, + seek_entry->grp_addr); + } else { +#ifdef MAODV + if(seek_entry->flags & RREQ_JOIN && !(seek_entry->flags & RREQ_REPAIR)) { + mrt_table_t *group_rec; + mrt_nexthop_t *upstream; + + DEBUG(LOG_DEBUG, 0, "In special MCAST timeout segment"); + + /* try to join the group */ + group_rec = mrt_table_find(seek_entry->dest_addr); + upstream = mact_activate_best_upstream(group_rec); + + if(upstream) { + if(group_rec->is_broken) { + /* we were repairing route */ + group_rec->is_broken = 0; + } else if(group_rec->is_gateway) { + /* Gateway joining, not a member */ + } else { + /* we were able to select an upstream */ + group_rec->is_member = 1; + DEBUG(LOG_DEBUG, 0, "Joined Group"); + } + } else { + /* have to become leader ourselves */ + if(group_rec->is_broken && !group_rec->is_member) { + /* we are a router who lost his upstream */ + group_rec->is_broken = 0; + mact_make_downstream_leader(group_rec); + DEBUG(LOG_DEBUG, 0, "Link broke, make downstream leader."); + } else { + if(group_rec->is_broken) { + group_rec->is_broken = 0; + DEBUG(LOG_DEBUG, 0, "Was broken, now fixed."); + } + mrt_table_become_leader(group_rec); + DEBUG(LOG_DEBUG, 0, "Became group leader"); + } + } + + dest_addr = seek_entry->dest_addr; + if(seek_list_remove(seek_list_find(seek_entry->dest_addr))) { + if(mcast_packet_queue_send(dest_addr) < 0) { + DEBUG(LOG_DEBUG, 0, "Error dequeueing packets."); + } } else { + DEBUG(LOG_DEBUG, 0, "No longer in seek list."); + } + + return; + } else if((seek_entry->flags & RREQ_JOIN) && + (seek_entry->flags & RREQ_REPAIR)) { + mrt_table_t *mrt; + mrt = mrt_table_find(seek_entry->grp_addr); + + if(mrt) { + /* Done merging, might have worked. */ + DEBUG(LOG_DEBUG, 0, "Route discovery for merge timed out. Clearing in_repair."); + mrt->in_repair = 0; + + } else { + DEBUG(LOG_DEBUG, 0, "Bad dest_addr:%d in seek_list.", + ip_to_str(seek_entry->grp_addr)); + } + } +#endif /* MAODV */ packet_queue_drop(seek_entry->dest_addr); DEBUG(LOG_DEBUG, 0, "NO ROUTE FOUND!"); @@ -113,7 +189,7 @@ #endif repair_rt = rt_table_find(seek_entry->dest_addr); - seek_list_remove(seek_entry); + seek_list_remove(seek_list_find(seek_entry->dest_addr)); /* If this route has been in repair, then we should timeout the route at this point. */ @@ -173,6 +249,31 @@ precursor_list_destroy(rt); } +#ifdef MAODV +void NS_CLASS multicast_route_expire_timeout( void * arg ) +{ + mrt_table_t *mrt; + + mrt = (mrt_table_t *) arg; + + if ( !mrt ) { + log( LOG_WARNING, 0, __FUNCTION__, "arg was NULL, ignoring timeout!" ); + return; + } + + DEBUG( LOG_DEBUG, 0, "Multicast Route %s DOWN, seqno = %d", + ip_to_str( mrt->grp_addr ), mrt->grp_seqno ); + +/* + CHECK: Remove after creating valid flag. + + mrt_table_invalidate( mrt ); + mrt_nexthop_remove_all( mrt ); +*/ + + return; +} +#endif void NS_CLASS route_expire_timeout(void *arg) { @@ -242,6 +343,9 @@ #endif } neighbor_link_break(rt); +#ifdef MAODV + mcast_neighbor_link_break(rt); +#endif } } diff -urNb aodv-uu-0.7.2/aodv_timeout.h maodv-umd-0.7.2/aodv_timeout.h --- aodv-uu-0.7.2/aodv_timeout.h Thu May 22 19:11:35 2003 +++ maodv-umd-0.7.2/aodv_timeout.h Wed Jun 25 17:46:09 2003 @@ -31,6 +31,7 @@ void route_delete_timeout(void *arg); void local_repair_timeout(void *arg); void route_discovery_timeout(void *arg); +void multicast_route_expire_timeout(void *arg); void route_expire_timeout(void *arg); void hello_timeout(void *arg); void rrep_ack_timeout(void *arg); diff -urNb aodv-uu-0.7.2/defs.h maodv-umd-0.7.2/defs.h --- aodv-uu-0.7.2/defs.h Mon Jun 9 06:43:40 2003 +++ maodv-umd-0.7.2/defs.h Wed Jun 25 17:46:09 2003 @@ -27,13 +27,16 @@ #include #include #include +#include #ifndef NS_PORT #include + #include #include #include #include + #endif #include @@ -94,6 +97,9 @@ u_int32_t ipaddr; /* The local IP address */ u_int32_t netmask; /* The netmask we use */ u_int32_t broadcast; +#ifdef MAODV + int injectfd; /* Handle to IP injection device for this interface */ +#endif }; struct host_info { @@ -161,7 +167,6 @@ #endif - /* Two macros to simplify retriving of a dev_info struct. Either using an ifindex or a device number (index into devs array). */ #define DEV_IFINDEX(ifindex) (this_host.devs[ifindex2devindex(ifindex)]) @@ -179,6 +184,12 @@ #define AODV_RERR 3 #define AODV_RREP_ACK 4 +#ifdef MAODV +/* multicast types */ +#define MAODV_MACT 5 +#define MAODV_GRPH 6 +#endif /* MAODV */ + /* A generic AODV packet header struct... */ #ifdef NS_PORT struct AODV_msg { @@ -211,6 +222,13 @@ #define RREQ_EXT 2 #define RREP_EXT 2 #define RREP_HELLO_NEIGHBOR_SET_EXT 3 + +#ifdef MAODV +/* MAODV Extension types */ +#define RREQ_GRP_REBUILD_EXT 4 +#define RREQ_GRP_MERGE_EXT 9 +#define RREP_GRP_MERGE_EXT 9 +#endif /* MAODV */ /* An generic AODV extensions header */ typedef struct { diff -urNb aodv-uu-0.7.2/icmp.c maodv-umd-0.7.2/icmp.c --- aodv-uu-0.7.2/icmp.c Mon Oct 7 11:42:20 2002 +++ maodv-umd-0.7.2/icmp.c Wed Jun 25 17:46:09 2003 @@ -33,7 +33,12 @@ char icmp_send_buf[ICMP_BUFSIZE]; int icmp_socket; +/* Used in igmp.c's IGMP injection function */ +#ifdef MAODV +unsigned short cksum(unsigned short *w, int len) +#else static unsigned short cksum(unsigned short *w, int len) +#endif { int sum = 0; unsigned short answer = 0; diff -urNb aodv-uu-0.7.2/icmp.h maodv-umd-0.7.2/icmp.h --- aodv-uu-0.7.2/icmp.h Wed Jun 19 10:46:31 2002 +++ maodv-umd-0.7.2/icmp.h Wed Jun 25 17:46:09 2003 @@ -24,5 +24,9 @@ void icmp_init(); int icmp_send_host_unreachable(char *data, int len); +#ifdef MAODV +/* MAODV packet injection needs an IP checksum function */ +unsigned short cksum(unsigned short *w, int len); +#endif /* MAODV */ #endif diff -urNb aodv-uu-0.7.2/igmp.c maodv-umd-0.7.2/igmp.c --- aodv-uu-0.7.2/igmp.c Wed Dec 31 19:00:00 1969 +++ maodv-umd-0.7.2/igmp.c Mon Jun 30 16:00:00 2003 @@ -0,0 +1,218 @@ +#ifdef MAODV + +/***************************************************************************** + * + * Copyright (C) 2003 CSHCN, University of Maryland. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Authors: Dionysus Blazakis + * Jonathan Polley + * Dan Rusk + * Manish Karir + * Jonathan McGee + * + *****************************************************************************/ + +#ifdef NS_PORT +#include "aodv-uu.h" +#else +#include +#include "aodv_socket.h" +#include "params.h" +#include "seek_list.h" +#include "defs.h" +#include "debug.h" +#include "multicast_routing_table.h" +#include "igmp.h" +#include "icmp.h" +#include "aodv_rreq.h" +#include "maodv_mact.h" +#include "packet_queue.h" +#endif + +static void maodv_join(u_int32_t grp_addr){ + mrt_table_t *group_rec; + + group_rec=mrt_table_find(grp_addr); + + if(group_rec==NULL){ + group_rec=mrt_table_insert(grp_addr, 0, 0, 0, 255, 0); + } + + if(group_rec->is_gateway) { + /* Gateway code has joined or is in the process of doing so */ + group_rec->is_member = 1; + } else if(!group_rec->is_router){ + /* no route to group, so let's find one. */ + rreq_route_discovery(grp_addr, RREQ_JOIN, NULL, 0); + }else if(!group_rec->is_member){ + /* I'm routing, so I just need to reactivate my membership */ + group_rec->is_member=1; + } +} + +static void maodv_leave(u_int32_t grp_addr){ + mrt_table_t *group_rec; + + group_rec=mrt_table_find(grp_addr); + + /* don't leave if not in the group */ + if(group_rec==NULL || !group_rec->is_router) + return; + + /* leave group */ + group_rec->is_member=0; + + /* If gateway mode is enabled, make sure the gateway flag is set */ + if(this_host.gateway_mode) { + group_rec->is_gateway = 1; + } + + if(group_rec->is_gateway) { + /* Only prune if no up or down stream */ + if((group_rec->activated_downstream_cnt == 0) + && (group_rec->activated_upstream_cnt == 0)) { + group_rec->am_leader = 0; + group_rec->is_gateway = 0; + mrt_table_stop_routing(group_rec); + + /* remove any pending RREQs (or other packets) for this group */ + seek_list_remove(seek_list_find(grp_addr)); + packet_queue_drop(grp_addr); + + /* flush all nexthops */ + mrt_nexthop_remove_all(group_rec); + } + } else if(group_rec->am_leader){ + if(group_rec->activated_downstream_cnt>0){ + /* do have downstreams, so make one new leader */ + mact_make_downstream_leader(group_rec); + } + group_rec->am_leader=0; + mrt_table_stop_routing(group_rec); + }else if(group_rec->activated_downstream_cnt==0){ + /* no downs, prune self and invalidate route */ + mrt_nexthop_t *upstream; + + upstream=mrt_table_get_activated_upstream(group_rec); + if(upstream != NULL){ + mact_send(MACT_PRUNE, 1, grp_addr, upstream->addr,1); + mrt_nexthop_deactivate(group_rec, upstream->addr); + } + mrt_table_stop_routing(group_rec); + + /* remove any pending RREQs (or other packets) for this group */ + seek_list_remove(seek_list_find(grp_addr)); + packet_queue_drop(grp_addr); + + /* flush all nexthops */ + mrt_nexthop_remove_all(group_rec); + } + /* otherwise I must keep route valid so I keep routing */ +} + +static void maodv_query(IGMP* pkt, int ifindex) { + mrt_table_t *tblentry; + int n; + + /* Iterate through all the multicast routing entries */ + for(n = 0; n < MRT_TABLESIZE; n++) { + tblentry = mrt_tbl.tbl[n]; + + while(tblentry) { + igmp_sendreply(tblentry, ifindex); + tblentry = tblentry->next; + } + } +} + +void igmp_process( IGMP *pkt, int ifindex ) +{ + u_int32_t grp_addr; + DEBUG(LOG_DEBUG, 0, "IGMP packet out. Dropped."); + + grp_addr=ntohl(pkt->igmp_group.s_addr); + + switch( pkt->igmp_type ) { + case IGMP_V1_MEMBERSHIP_REPORT: + case IGMP_V2_MEMBERSHIP_REPORT: + DEBUG(LOG_DEBUG, 0, "IGMP_REPORT"); + + /* may not do anything if we already have a valid route. */ + maodv_join( grp_addr ); + + break; + case IGMP_V2_LEAVE_GROUP: + DEBUG(LOG_DEBUG, 0, "IGMP_LEAVE"); + + /* it may not actually prune, but at least un-member me. */ + maodv_leave( grp_addr ); + + break; + case IGMP_MEMBERSHIP_QUERY: + DEBUG(LOG_DEBUG, 0, "IGMP_QUERY"); + + /* Terrestrial multicast router is asking for list of groups */ + maodv_query( pkt, ifindex ); + + break; + default: + DEBUG(LOG_DEBUG, 0, "IGMP_UNKNOWN [0x%x]", pkt->igmp_type ); + break; + } +} + +void igmp_sendreply(mrt_table_t* mrt, int ifindex) { + char szBuffer[sizeof(struct iphdr) + sizeof(struct igmphdr)]; + struct iphdr* ip = (struct iphdr*)szBuffer; + struct igmphdr* igmp = (struct igmphdr*)(szBuffer + sizeof(struct iphdr)); + int injectfd = DEV_IFINDEX(ifindex).injectfd, err; + + if(!mrt->nexthops || !mrt->is_router) { + /* Nobody listening, so don't send */ + return; + } + + if(injectfd != -1) { + ip->version = IPVERSION; + ip->ihl = sizeof(struct iphdr) >> 2; + ip->tos = 0; + ip->tot_len = htons(sizeof(szBuffer)); + ip->id = 1; + ip->frag_off = 0; + ip->ttl = 1; + ip->protocol = IPPROTO_IGMP; + ip->saddr = htonl(mrt->nexthops->addr); + ip->daddr = htonl(mrt->grp_addr); + ip->check = 0; + ip->check = cksum((unsigned short*)ip, sizeof(struct iphdr)); + igmp->type = IGMP_V1_MEMBERSHIP_REPORT; + igmp->code = 0; + igmp->group = ip->daddr; + igmp->csum = 0; + igmp->csum = cksum((unsigned short*)igmp, sizeof(struct igmphdr)); + + DEBUG(LOG_DEBUG, 0, "Injecting IGMP REPORT for %s from %s on %s", + ip_to_str(ntohl(ip->daddr)), ip_to_str(ntohl(ip->saddr)), + DEV_IFINDEX(ifindex).ifname); + err = write(injectfd, szBuffer, sizeof(szBuffer)); + if(err < sizeof(szBuffer)) { + perror("write"); + } + } +} + +#endif /* MAODV */ diff -urNb aodv-uu-0.7.2/igmp.h maodv-umd-0.7.2/igmp.h --- aodv-uu-0.7.2/igmp.h Wed Dec 31 19:00:00 1969 +++ maodv-umd-0.7.2/igmp.h Wed Jun 25 17:46:09 2003 @@ -0,0 +1,47 @@ +/***************************************************************************** + * + * Copyright (C) 2003 CSHCN, University of Maryland. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Authors: Dionysus Blazakis + * Jonathan Polley + * Dan Rusk + * Manish Karir + * Jonathan McGee + * + *****************************************************************************/ + +#ifndef IGMP_H +#define IGMP_H + +#ifndef NS_NO_GLOBALS + +#include "defs.h" +#include "multicast_routing_table.h" +#include + +#define IGMP struct igmp + +#endif /* NS_NO_GLOBALS */ + +#ifndef NS_NO_DECLARATIONS + +void igmp_process( IGMP * buff, int ifindex ); +void igmp_sendreply( mrt_table_t * mrt, int ifindex ); + +#endif /* NS_NO_DECLARATIONS */ + +#endif /* IGMP_H */ diff -urNb aodv-uu-0.7.2/k_mroute.c maodv-umd-0.7.2/k_mroute.c --- aodv-uu-0.7.2/k_mroute.c Wed Dec 31 19:00:00 1969 +++ maodv-umd-0.7.2/k_mroute.c Thu Jul 17 18:03:42 2003 @@ -0,0 +1,239 @@ +#ifdef MAODV + +/***************************************************************************** + * + * Copyright (C) 2003 CSHCN, University of Maryland. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Authors: Dionysus Blazakis + * Jonathan Polley + * Dan Rusk + * Manish Karir + * + *****************************************************************************/ + +#include "k_mroute.h" +#include /* perror */ +#include +#include +#include +#include +#include + +/* Yanked from debug.h during a battle with the includes. */ +#include +void log(int, int, const char *, char *, ...); + +int multicast_socket = -1; + +/* much of this code was taken from Dinesh's kernel MAODV + implementation and cleaned up for user space. + + also, smc_route v.0.92 provided a good user space reference. */ + +/* + * kernel_mrt_init( ) + * Create and initialize the multicast socket for communication with the kernel. + */ +int kernel_mrt_init( void ) +{ + int error; + int enable = 1; + + multicast_socket = socket( AF_INET, SOCK_RAW, IPPROTO_IGMP ); + + /* error creating socket? */ + if ( multicast_socket < 0 ) { + log(LOG_WARNING, 0, __FUNCTION__, + "Failed to create socket."); + return -1; + } + + error = setsockopt( multicast_socket, IPPROTO_IP, MRT_INIT, + (int *) &enable, sizeof( enable ) ); + if ( error < 0 ) { + log(LOG_WARNING, 0, __FUNCTION__, + "Error starting kernel multicast routing."); + return -1; + } + + log(LOG_DEBUG, 0, __FUNCTION__, + "Got the multicast kernel route socket!"); + + return 0; +} + +/* + * kernel_mrt_clean_up( ) + * Close the socket and clean up the virtual interfaces. + */ +int kernel_mrt_clean_up( void ) +{ + if(multicast_socket != -1) { + + int error = setsockopt( multicast_socket, IPPROTO_IP, MRT_DONE, + (char *) NULL, 0 ); + if ( error < 0 ) { + log(LOG_WARNING, 0, __FUNCTION__, + "Error finishing (MRT_DONE) kernel multicast routing."); + return -1; + } + + close( multicast_socket ); + + log(LOG_DEBUG, 0, __FUNCTION__, + "Killed multicast socket!"); + + } /* if(multicast_socket != -1) { */ + return 0; +} + +/* + * kernel_mrt_vif_add( addr, index ) + * Adds a virtual interface from ip "addr" as index "index". + */ +int kernel_mrt_vif_add( u_int32_t this_ip, int index ) +{ + if(multicast_socket != -1) { + + struct vifctl vc; + int error; + + /* taken from smcroute-0.92 */ + vc.vifc_vifi = index; + vc.vifc_flags = 0; + vc.vifc_threshold = 1; + vc.vifc_rate_limit = 0; + + vc.vifc_lcl_addr.s_addr = htonl(this_ip); + vc.vifc_rmt_addr.s_addr = INADDR_ANY; + + error = setsockopt( multicast_socket, IPPROTO_IP, MRT_ADD_VIF, + (char *)&vc, sizeof(vc) ); + if ( error < 0 ) { + perror("ERROR! " ); + log(LOG_WARNING, 0, __FUNCTION__, + "Error creating virtual interface for kernel multicast routing[%d]." , error ); + return -1; + } + + log(LOG_DEBUG, 0, __FUNCTION__, + "Added virtual interface."); + + } /* if(multicast_socket != -1) { */ + return 0; +} + +/* + * kernel_mrt_vif_del( addr, index ) + * Deletes a virtual interface at from ip "addr" as index "index". + */ +int kernel_mrt_vif_del( u_int32_t this_ip, int index ) +{ + if(multicast_socket != -1) { + + struct vifctl vc; + int error; + + vc.vifc_vifi = (vifi_t) index; + vc.vifc_flags = 0; + // Is the threshold value 0 or 1??? - Dinesh + vc.vifc_threshold = 0; + vc.vifc_rate_limit = 0; + + vc.vifc_lcl_addr.s_addr = htonl(this_ip); + vc.vifc_rmt_addr.s_addr = INADDR_ANY; + + error = setsockopt( multicast_socket, IPPROTO_IP, MRT_DEL_VIF, + (char *)&vc, sizeof(vc) ); + if ( error < 0 ) { + log(LOG_WARNING, 0, __FUNCTION__, + "Error deleting virtual interface for kernel multicast routing."); + return -1; + } + + } /* if(multicast_socket != -1) { */ + return 0; +} + +/* + * kernel_mrt_add_route( source, grp, vif ) + * Add a multicast route to the kernel routing cache. + */ +int kernel_mrt_add_route( u_int32_t src, u_int32_t grp, int index ) +{ + if(multicast_socket != -1) { + + struct mfcctl mc; + int error; + + mc.mfcc_origin.s_addr = htonl(src); + mc.mfcc_mcastgrp.s_addr = htonl(grp); + mc.mfcc_parent = (vifi_t) index; + memset(mc.mfcc_ttls, 0, sizeof(mc.mfcc_ttls)); + mc.mfcc_ttls[index] = 2; /* CHECK: this seems odd... */ + + error = setsockopt( multicast_socket, IPPROTO_IP, MRT_ADD_MFC, + (char *) ( &mc ), sizeof( mc ) ); + + if ( error < 0 ) { + perror( "ERROR " ); + log(LOG_WARNING, 0, __FUNCTION__, + "Error adding route for kernel multicast routing."); + return -1; + } + + log(LOG_DEBUG, 0, __FUNCTION__, + "Added multicast route cache entry."); + + } /* if(multicast_socket != -1) { */ + return 0; +} + +/* + * kernel_mrt_del_route( source, grp, vif ) + * Delete a multicast route from the kernel routing cache. + */ +int kernel_mrt_del_route( u_int32_t src, u_int32_t grp, int index ) +{ + if(multicast_socket != -1) { + + struct mfcctl mc; + int error; + + /* CHECK: ttls are diff in Dinesh's code... intentional? */ + mc.mfcc_origin.s_addr = htonl(src); + mc.mfcc_mcastgrp.s_addr = htonl(grp); + mc.mfcc_parent = (vifi_t) index; + mc.mfcc_ttls[index] = 1; + + error = setsockopt( multicast_socket, IPPROTO_IP, MRT_DEL_MFC, + (char *) ( &mc ), sizeof( struct mfcctl ) ); + + if ( error < 0 ) { + log(LOG_WARNING, 0, __FUNCTION__, + "Error deleting route for kernel multicast routing."); + return -1; + } + + log(LOG_DEBUG, 0, __FUNCTION__, + "Removed multicast route cache entry."); + + } /* if(multicast_socket != -1) { */ + return 0; +} + +#endif /* MAODV */ diff -urNb aodv-uu-0.7.2/k_mroute.h maodv-umd-0.7.2/k_mroute.h --- aodv-uu-0.7.2/k_mroute.h Wed Dec 31 19:00:00 1969 +++ maodv-umd-0.7.2/k_mroute.h Wed Jun 25 17:46:09 2003 @@ -0,0 +1,38 @@ +/***************************************************************************** + * + * Copyright (C) 2003 CSHCN, University of Maryland. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Authors: Dionysus Blazakis + * Jonathan Polley + * Dan Rusk + * Manish Karir + * + *****************************************************************************/ + +#ifndef K_MROUTE_H +#define K_MROUTE_H + +#include + +int kernel_mrt_init( void ); +int kernel_mrt_clean_up( void ); +int kernel_mrt_vif_add( u_int32_t this_ip, int index ); +int kernel_mrt_vif_del( u_int32_t this_ip, int index ); +int kernel_mrt_add_route( u_int32_t src, u_int32_t grp, int index ); +int kernel_mrt_del_route( u_int32_t src, u_int32_t grp, int index ); + +#endif /* K_MROUTE_H */ diff -urNb aodv-uu-0.7.2/kaodv.c maodv-umd-0.7.2/kaodv.c --- aodv-uu-0.7.2/kaodv.c Wed Nov 6 08:48:46 2002 +++ maodv-umd-0.7.2/kaodv.c Fri Dec 5 17:42:32 2003 @@ -117,6 +117,12 @@ /* Check which hook the packet is on... */ switch (hooknum) { case NF_IP_PRE_ROUTING: +#ifdef MAODV + /* Pass incoming IGMP (since MAODV might have generated it) */ + if((*skb)->nh.iph->protocol == IPPROTO_IGMP) { + break; + } +#endif /* Loop through all AODV enabled interfaces and see if the packet * is bound to any of them. */ for (i = 0; i < nif; i++) @@ -124,7 +130,12 @@ (*skb)->nfmark = 3; goto queue; } - break; + + /* Gateway mode requirement */ + (*skb)->nfmark = 4; + goto queue; + goto accept; + case NF_IP_LOCAL_OUT: for (i = 0; i < nif; i++) if (ifindices[i] == out->ifindex) { @@ -132,6 +143,7 @@ goto queue; } break; + case NF_IP_POST_ROUTING: /* Re-route all packets before sending on interface. This will make sure queued packets are routed on a newly installed diff -urNb aodv-uu-0.7.2/kinject.c maodv-umd-0.7.2/kinject.c --- aodv-uu-0.7.2/kinject.c Wed Dec 31 19:00:00 1969 +++ maodv-umd-0.7.2/kinject.c Thu Jul 17 18:03:45 2003 @@ -0,0 +1,280 @@ +/***************************************************************************** + * + * Copyright (C) 2003 CSHCN, University of Maryland. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Authors: Jonathan McGee + * + *****************************************************************************/ +#include + +#include +#include +#include +#include +#include + +#define CONFIG_PROC_FS +#include + +#include +#include +#include + +/* Root for our network output entries */ +static struct proc_dir_entry *proc_netwrite = NULL; + +/* Linked list of installed proc entries */ +struct proc_netwrite_entry { + struct proc_netwrite_entry *next; + struct proc_dir_entry *entry; + const char *devname; + struct net_device *dev; +}; + +static struct proc_netwrite_entry *proc_netwrite_entries = NULL; + +/* + * Injecting packets into the IP stack + */ +static int proc_netwrite_write(struct file *file, const char *buffer, + unsigned long count, void *data) { + struct sk_buff *skb = NULL; + struct iphdr *ip = (struct iphdr*)buffer; + struct net_device *dev = NULL; + + /* Do some sanity checking */ + if(data == NULL) { + printk(KERN_INFO __FILE__ ": %ld bytes written but no output " + "device!\n", count); + return -EPIPE; + } + + /* Check data for basic sanity */ + if((count < sizeof(struct iphdr)) || (ip->version != 4) + || (count > 0xFFFF)) { + printk(KERN_INFO __FILE__ ": Packet so illegal, it's gonna be " + "ignored.\n"); + return -EIO; + } + + /* Get our device */ + dev = ((struct proc_netwrite_entry*)data)->dev; + if(dev == NULL) { + printk(KERN_DEBUG __FILE__ ": Odd, lost the output device.\n"); + return -EPIPE; + } + + /* Make sure it's up */ + if(!netif_running(dev)) { + printk(KERN_INFO __FILE__ ": Packet sent to down device %s\n", + dev->name); + return -EIO; + } + + /* Create packet for sending */ + skb = dev_alloc_skb(count); + if(skb == NULL) { + printk(KERN_INFO __FILE__ ": Out of memory, cannot create sk_buff\n"); + return -ENOMEM; + } + + /* Initialize data structure as necessary */ + ip = (struct iphdr*)skb_put(skb, count); + memcpy(ip, buffer, count); + + skb->h.raw = NULL; + skb->nh.iph = ip; + skb->mac.raw = NULL; + + skb->pkt_type = PACKET_HOST; + skb->protocol = __constant_htons(ETH_P_IP); + skb->dev = dev; + + skb->ip_summed = CHECKSUM_NONE; + skb->len = count; + do_gettimeofday(&skb->stamp); + + /* "Receive" data */ + printk(KERN_DEBUG __FILE__ ": Feeding a %ld byte packet into the stack\n", + count); + ip_rcv(skb, skb->dev, NULL); + return count; +} + +/* + * List behavior + */ + +/* Add an item to the list */ +static int proc_netwrite_addentry(struct net_device *dev) { + struct proc_netwrite_entry *newentry; + struct proc_dir_entry *newprocentry; + + /* Attempt to create proc entry */ + newprocentry = create_proc_entry(dev->name, S_IFREG|S_IRUGO|S_IWUSR, + proc_netwrite); + if(newprocentry == NULL) { + return 1; + } + + /* Allocate memory for data structure */ + newentry = kmalloc(sizeof(struct proc_netwrite_entry), GFP_ATOMIC); + if(newentry == NULL) { + remove_proc_entry(dev->name, proc_netwrite); + return 1; + } + + /* Initialize */ + newentry->next = NULL; + newentry->entry = newprocentry; + newentry->devname = dev->name; + newentry->dev = dev; + newprocentry->data = newentry; + newprocentry->write_proc = proc_netwrite_write; + + /* Add to list */ + if(proc_netwrite_entries == NULL) { + /* Empty list */ + proc_netwrite_entries = newentry; + } else { + /* Find end of list and link in */ + struct proc_netwrite_entry *head = proc_netwrite_entries; + for(; head->next; head = head->next); + head->next = newentry; + } + + return 0; +} + +/* Add all currently installed net devices to the list */ +static int proc_netwrite_addallentries() { + int err, errall = 0; + struct net_device *curr = dev_base; + + while(curr) { + err = proc_netwrite_addentry(curr); + curr = curr->next; + if(err) { + errall = err; + } + } + + return errall; +} + +/* Remove from list */ +static int proc_netwrite_removeentry(struct net_device *dev) { + struct proc_netwrite_entry *prev, *curr; + + /* Locate entry in list */ + prev = NULL; + curr = proc_netwrite_entries; + while(curr && (curr->dev != dev)) { + prev = curr; + curr = curr->next; + } + + /* If we found it, remove it */ + if(curr) { + /* Remove from list */ + if(prev) { + prev->next = curr->next; + } else { + proc_netwrite_entries = curr->next; + } + /* Remove proc entry */ + curr->entry->data = NULL; + remove_proc_entry(curr->devname, proc_netwrite); + /* Clear it out in case proc file still open */ + curr->dev = NULL; + curr->devname = NULL; + kfree(curr); + } + + return 0; +} + +/* Remove all entries in the list */ +static int proc_netwrite_removeallentries() { + while(proc_netwrite_entries != NULL) { + proc_netwrite_removeentry(proc_netwrite_entries->dev); + } + + return 0; +} + +/* + * Keep our /proc up to date with network devices + */ +int on_device_notify(struct notifier_block *self, unsigned long event, void *v) { + struct net_device *dev = (struct net_device*)v; + switch(event) { + case NETDEV_REGISTER: + /* New device added to kernel */ + proc_netwrite_addentry(dev); + break; + + case NETDEV_UNREGISTER: + /* Device being removed from kernel */ + proc_netwrite_removeentry(dev); + break; + } + return NOTIFY_DONE; +} + +struct notifier_block device_event_notifier = { + on_device_notify, + NULL, + 0 +}; + +/* + * Called when the module is inserted in the kernel. + */ +int init_module() +{ + /* Create directory to hold our nodes */ + proc_netwrite = proc_mkdir("inject", proc_net); + if(proc_netwrite == NULL) { + /* Return failure if couldn't create the node */ + return 1; + } + /* Create the nodes for currently installed devices */ + proc_netwrite_addallentries(); + /* Be notified on device changes */ + register_netdevice_notifier(&device_event_notifier); + return 0; +} + +/* + * Called when removing the module from memory... + */ +void cleanup_module() +{ + /* Deregister entry into device notification */ + unregister_netdevice_notifier(&device_event_notifier); + /* Remove existing devices */ + proc_netwrite_removeallentries(); + /* Remove node directory */ + remove_proc_entry("inject", proc_net); +} + +MODULE_DESCRIPTION("MAODV Gateway kernel support."); +MODULE_AUTHOR("Jonathan McGee"); +#ifdef MODULE_LICENSE +MODULE_LICENSE("GPL"); +#endif diff -urNb aodv-uu-0.7.2/main.c maodv-umd-0.7.2/main.c --- aodv-uu-0.7.2/main.c Tue May 27 12:32:58 2003 +++ maodv-umd-0.7.2/main.c Mon Jun 30 13:53:46 2003 @@ -43,6 +43,11 @@ #include "aodv_hello.h" #include "packet_input.h" #include "packet_queue.h" +#ifdef MAODV +#include "multicast_routing_table.h" +#include "multicast_packet_cache.h" +#include "k_mroute.h" +#endif #ifdef USE_IW_SPY #include "link_qual.h" @@ -59,7 +64,7 @@ int receive_n_hellos = 0; int hello_jittering = 1; int optimized_hellos = 0; -int ratelimit = 1; /* Option for rate limiting RREQs and RERRs. */ +int ratelimit = 0; /* Option for rate limiting RREQs and RERRs. */ char *progname; int wait_on_reboot = 1; int hello_qual_threshold = 12; @@ -191,36 +196,6 @@ return 0; } -int find_default_gw(void) -{ - FILE *route; - char buf[100], *l; - - route = fopen("/proc/net/route", "r"); - - if (route == NULL) { - perror("open /proc/net/route"); - exit(-1); - } - - while (fgets(buf, sizeof(buf), route)) { - l = strtok(buf, " \t"); - l = strtok(NULL, " \t"); - if (l != NULL) { - if (strcmp("00000000", l) == 0) { - l = strtok(NULL, " \t"); - l = strtok(NULL, " \t"); - if (strcmp("0003", l) == 0) { - fclose(route); - return 1; - } - } - } - } - fclose(route); - return 0; -} - /* * Returns information on a network interface given its name... */ @@ -293,6 +268,17 @@ sprintf(buf, "/sbin/insmod kaodv.o ifname=%s &>/dev/null", ifname); system(buf); +#ifdef MAODV + if(internet_gw_mode) { + memset(buf, '0', 64); + if(stat("./kinject.o", &st) < 0) + sprintf(buf, "/sbin/modprobe kinject &>/dev/null"); + else + sprintf(buf, "/sbin/insmod kinject.o &>/dev/null"); + system(buf); + } +#endif + /* Check result */ m = fopen("/proc/modules", "r"); while (fgets(buf, sizeof(buf), m)) { @@ -318,6 +304,9 @@ void remove_modules(void) { system("/sbin/modprobe -r kaodv &>/dev/null"); +#ifdef MAODV + system("/sbin/modprobe -r kinject &>/dev/null"); +#endif system("/sbin/modprobe -r ip_queue &>/dev/null"); } @@ -411,6 +400,12 @@ DEV_IFINDEX(ifreq.ifr_ifindex).ipaddr = ntohl(ina->sin_addr.s_addr); + #ifdef MAODV + /* CHECK */ + kernel_mrt_vif_add( DEV_IFINDEX(ifreq.ifr_ifindex).ipaddr, 0 ); + + #endif + /* Get netmask of interface... */ ina = get_if_info(iface, SIOCGIFNETMASK); if (ina == NULL) @@ -426,6 +421,11 @@ DEV_IFINDEX(ifreq.ifr_ifindex).enabled = 1; +#ifdef MAODV + /* No injection socket yet openned */ + DEV_IFINDEX(ifreq.ifr_ifindex).injectfd = -1; +#endif + if (this_host.nif >= MAX_NR_INTERFACES) break; @@ -442,15 +442,19 @@ exit(-1); } if (internet_gw_mode) { - if (find_default_gw()) { log(LOG_NOTICE, 0, __FUNCTION__, "Internet gateway mode enabled!"); this_host.gateway_mode = 1; - } else { - this_host.gateway_mode = 0; - sprintf(buf, "/sbin/route add default gw 127.0.0.1 dev lo"); - system(buf); } + +#ifdef MAODV + /* Open up injection for interfaces when in gateway mode */ + if(this_host.gateway_mode) { + for(i = 0; i < this_host.nif; i++) { + sprintf(buf, "/proc/net/inject/%s", this_host.devs[i].ifname); + this_host.devs[i].injectfd = open(buf, O_WRONLY); } + } +#endif } /* This signal handler ensures clean exits */ @@ -594,8 +598,18 @@ /* Initialize data structures and services... */ rt_table_init(); log_init(); - packet_queue_init(); +#ifdef MAODV + if(!internet_gw_mode) { + kernel_mrt_init(); + } +#endif + host_init(ifname); +#ifdef MAODV + mrt_table_init(); + init_packet_cache(); +#endif + packet_queue_init(); packet_input_init(); aodv_socket_init(); #ifdef USE_IW_SPY @@ -665,11 +679,29 @@ static void cleanup(void) { + int i; + DEBUG(LOG_DEBUG, 0, "CLEANING UP!"); - if (internet_gw_mode && !this_host.gateway_mode) - system("/sbin/route del default"); + +#ifdef MAODV + /* Close the injection sockets prior to unloading kinject.o */ + for(i = 0; i < this_host.nif; i++) { + if(this_host.devs[i].injectfd != -1) { + close(this_host.devs[i].injectfd); + this_host.devs[i].injectfd = -1; + } + } +#endif + remove_modules(); rt_table_destroy(); +#ifdef MAODV + mrt_table_destroy(); + + /* CHECK: What interface? should we cycle through and fins a nice interface? */ + kernel_mrt_vif_del( DEV_IFINDEX(0).ipaddr, 0 ); + kernel_mrt_clean_up(); +#endif packet_input_cleanup(); packet_queue_destroy(); aodv_socket_cleanup(); diff -urNb aodv-uu-0.7.2/maodv_ext.h maodv-umd-0.7.2/maodv_ext.h --- aodv-uu-0.7.2/maodv_ext.h Wed Dec 31 19:00:00 1969 +++ maodv-umd-0.7.2/maodv_ext.h Wed Jun 25 17:46:09 2003 @@ -0,0 +1,98 @@ +/***************************************************************************** + * + * Copyright (C) 2003 CSHCN, University of Maryland. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Authors: Dionysus Blazakis + * Jonathan Polley + * Dan Rusk + * Manish Karir + * + *****************************************************************************/ + +#ifndef MAODV_EXT_H +#define MAODV_EXT_H + +#ifndef NS_NO_GLOBALS +#include + +#include "defs.h" + +typedef struct _grp_leader_ext_t { + u_int8_t type; + u_int8_t length; + u_int32_t grp_leader_addr; + u_int32_t prev_hop_addr; +} grp_leader_ext; + +typedef struct _grp_rebuild_ext_t { + u_int8_t type; + u_int8_t length; + u_int16_t grp_hcnt; +} grp_rebuild_ext; + +typedef struct _grp_info_ext_t { + u_int8_t type; + u_int8_t length; + u_int32_t grp_hcnt; + u_int32_t grp_leader_addr; +} grp_info_ext; + +/* See note below. */ +typedef struct _grp_merge_ext_t { + u_int8_t type; + u_int8_t length; + u_int16_t res; + u_int32_t grp_addr; + u_int32_t grp_seqno; +} grp_merge_ext; + +#define GRP_LEADER_EXT (grp_leader_ext) +#define GRP_LEADER_EXT_SIZE ( sizeof(GRP_LEADER_EXT) ) +#define GLE_TYPE ( 3 ) + /* 2 = size of header */ +#define GLE_LENGTH (GRP_LEADER_EXT_SIZE - 2) + +#define GRP_REBUILD_EXT grp_rebuild_ext +#define GRP_REBUILD_EXT_SIZE ( sizeof(GRP_REBUILD_EXT) ) +#define GRE_TYPE ( 4 ) + /* 2 = size of header */ +#define GRE_LENGTH (GRP_REBUILD_EXT_SIZE - 2) + +#define GRP_INFO_EXT (grp_info_ext) +#define GRP_INFO_EXT_SIZE ( sizeof(GRP_INFO_EXT) ) +#define GIE_TYPE ( 5 ) + /* 2 = size of header */ +#define GIE_LENGTH (GRP_INFO_EXT_SIZE - 2) + +/* NOTE: This is a non-standard extension. The draft is + unclear about the tree merge process. We have created + a new extension for our tree merge. The type number + was chosen in an attempt to avoid collisions with any + future extensions. */ +#define GRP_MERGE_EXT grp_merge_ext +#define GRP_MERGE_EXT_SIZE ( sizeof(GRP_MERGE_EXT) ) +#define GME_TYPE ( 9 ) + /* 2 = size of header */ +#define GME_LENGTH (GRP_MERGE_EXT_SIZE - 2) + +#endif /* NS_NO_GLOBALS */ + +#ifndef NS_NO_DECLARATIONS + +#endif /* NS_NO_DECLARATIONS */ + +#endif /* MAODV_MACT_H */ diff -urNb aodv-uu-0.7.2/maodv_grph.c maodv-umd-0.7.2/maodv_grph.c --- aodv-uu-0.7.2/maodv_grph.c Wed Dec 31 19:00:00 1969 +++ maodv-umd-0.7.2/maodv_grph.c Mon Jun 30 13:53:47 2003 @@ -0,0 +1,226 @@ +#ifdef MAODV + +/***************************************************************************** + * + * Copyright (C) 2003 CSHCN, University of Maryland. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Authors: Dionysus Blazakis + * Jonathan Polley + * Dan Rusk + * Manish Karir + * Jonathan McGee + * + *****************************************************************************/ + +#ifdef NS_PORT +#include "aodv-uu.h" +#else +#include +#include "maodv_grph.h" +#include "aodv_socket.h" +#include "params.h" +#include "seek_list.h" +#include "defs.h" +#include "debug.h" +#include "multicast_routing_table.h" +#include "aodv_rreq.h" +#endif + +GRPH *grph_create(u_int8_t flags, u_int8_t hcnt, u_int32_t grp_leader_addr, u_int32_t grp_addr, u_int32_t grp_seqno) +{ + GRPH *grph; + + grph=(GRPH *)aodv_socket_new_msg(); + + grph->type=MAODV_GRPH; + grph->res1=0; + grph->res2=0; + grph->hcnt=hcnt; + grph->grp_leader_addr=htonl(grp_leader_addr); + grph->grp_addr=htonl(grp_addr); + grph->grp_seqno=htonl(grp_seqno); + + if(flags & GRPH_UPDATE) + grph->u=1; + if(flags & GRPH_OFFMTREE) + grph->o=1; + + DEBUG(LOG_DEBUG, 0, "Assembled GRPH %s", ip_to_str(grp_addr)); + if(grph->u){ + DEBUG(LOG_DEBUG, 0, "GRPH->u set"); + } + + return grph; +} + +void grph_send(u_int8_t flags, u_int8_t hcnt, u_int32_t grp_addr, u_int32_t grp_seqno) +{ + GRPH *grph; + int i; + /* ttl is one, packets get rebroadcast at each step */ + int ttl = NET_DIAMETER; + + for(i=0; igrp_addr))); + + grph = (GRPH *) aodv_socket_queue_msg((AODV_msg *) grph, GRPH_SIZE); + grph->hcnt++; + for(i=0; igrp_addr))); + + upstream=mrt_table_get_activated_upstream(mrt); + if(upstream != NULL){ + rt=rt_table_find(upstream->addr); + grph->hcnt++; + grph = (GRPH *) aodv_socket_queue_msg((AODV_msg *) grph, GRPH_SIZE); + aodv_socket_send((AODV_msg *)grph, upstream->addr, GRPH_SIZE, ttl, &DEV_IFINDEX(rt->ifindex)); + } +} + +void grph_process(GRPH *grph, u_int32_t src_addr, int ttl) +{ + mrt_table_t *mrt; + u_int32_t grp_addr; + u_int32_t grp_leader_addr; + u_int32_t grp_seqno; + int do_forward=0, do_forward_ucast=0; + u_int8_t new_hcnt; + + grp_addr=ntohl(grph->grp_addr); + grp_leader_addr=ntohl(grph->grp_leader_addr); + grp_seqno=ntohl(grph->grp_seqno); + new_hcnt=grph->hcnt+1; + + mrt=mrt_table_find(grp_addr); + if(mrt==NULL){ + mrt=mrt_table_insert(grp_addr, grp_leader_addr, grp_seqno, 0, new_hcnt, 0); + do_forward=1; + } + + if(mrt->is_router){ + mrt_nexthop_t *upstream; + upstream=mrt_table_get_activated_upstream(mrt); + + /* group leader doens't need to process grph */ + /* nor do I care about offmtree packets if I'm on the tree */ + if(mrt->am_leader){ + if(mrt->grp_leader_addr != grp_leader_addr){ + /* initiate tree merge */ + /* Check IP's */ + if ( ( mrt->grp_leader_addr < grp_leader_addr ) && + ( !mrt->in_repair ) ){ + /* my IP is less than his ;( */ + /* initiate route discovery with all the flags */ + DEBUG(LOG_DEBUG, 0, "Initiating tree merge for %s.", ip_to_str(grp_addr)); + + mrt->in_repair = 1; + rreq_route_discovery( grp_leader_addr, + RREQ_JOIN | RREQ_REPAIR | RREQ_DEST_ONLY, + NULL, mrt->grp_addr ); + } + } + }else if(!grph->o){ + if(upstream != NULL && src_addr==upstream->addr){ + mrt->leader_hcnt=new_hcnt; + mrt->grp_seqno=grp_seqno; + + if(grph->u || mrt->grp_leader_addr!=grp_leader_addr){ + mrt_table_set_leader(mrt, grp_leader_addr, new_hcnt); + } + do_forward=1; + } + } + + if(!mrt->am_leader && grp_leader_addr != mrt->grp_leader_addr){ + /* if you get a grph for a different leader.... */ + /* unicast it to your upstream */ + do_forward_ucast=1; + } + }else{ + /* if not on the tree, you can be less discriminating about + your information */ + grph->o=1; + /* potential method for forwarding grph */ + if(grp_seqno>mrt->grp_seqno || + (grp_seqno==mrt->grp_seqno && new_hcntleader_hcnt)){ + do_forward=1; + } + if(mrt->grp_leader_addr!=grp_leader_addr || + (mrt->grp_leader_addr==grp_leader_addr && new_hcntleader_hcnt)){ + mrt_table_set_leader(mrt, grp_leader_addr, new_hcnt); + do_forward=1; + } + /* and finally update our sequence number */ + mrt->grp_seqno=grp_seqno; + + } + + if(do_forward && ttl>1){ + grph_forward(grph, --ttl); + } + + if(do_forward_ucast && ttl>1){ + grph_forward_ucast(mrt, grph, --ttl); + } + + if(this_host.gateway_mode && !mrt->is_router) { + /* In Gateway mode, we want a piece of every group */ + mrt->is_gateway = 1; + rreq_route_discovery( grp_addr, RREQ_JOIN, NULL, 0 ); + } +} + +void grph_send_callback(mrt_table_t *mrt){ + int flags=0; + if(mrt->grph_update_cnt>0){ + flags=GRPH_UPDATE; + mrt->grph_update_cnt--; + } + if(mrt->am_leader){ + grph_send(flags, 0, mrt->grp_addr, ++mrt->grp_seqno); + + timer_set_timeout(&(mrt->grph_timer), GROUP_HELLO_INTERVAL); + } +} + +#endif /* MAODV */ diff -urNb aodv-uu-0.7.2/maodv_grph.h maodv-umd-0.7.2/maodv_grph.h --- aodv-uu-0.7.2/maodv_grph.h Wed Dec 31 19:00:00 1969 +++ maodv-umd-0.7.2/maodv_grph.h Wed Jun 25 17:46:09 2003 @@ -0,0 +1,84 @@ +/***************************************************************************** + * + * Copyright (C) 2003 CSHCN, University of Maryland. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Authors: Dionysus Blazakis + * Jonathan Polley + * Dan Rusk + * Manish Karir + * + *****************************************************************************/ + +#ifndef MAODV_GRPH_H +#define MAODV_GRPH_H + +#ifndef NS_NO_GLOBALS +#include + +#include "defs.h" +#include "multicast_routing_table.h" + +/* GRPH Flags: */ +#define GRPH_UPDATE 0x2 +#define GRPH_OFFMTREE 0x1 + +typedef struct _grph_t { + u_int8_t type; +# if __BYTE_ORDER == __LITTLE_ENDIAN + u_int8_t res1:6; + u_int8_t o:1; + u_int8_t u:1; +# elif __BYTE_ORDER == __BIG_ENDIAN + u_int8_t u:1; + u_int8_t o:1; + u_int8_t res1:6; +# else +# error "Adjust your defines" +# endif + u_int8_t res2; + u_int8_t hcnt; + u_int32_t grp_leader_addr; + u_int32_t grp_addr; + u_int32_t grp_seqno; +} grph_t; + +#define GRPH grph_t +#define GRPH_SIZE sizeof(grph_t) + +#endif /* NS_NO_GLOBALS */ + +#ifndef NS_NO_DECLARATIONS +GRPH *grph_create(u_int8_t flags, + u_int8_t hcnt, + u_int32_t grp_leader_addr, + u_int32_t grp_addr, + u_int32_t grp_seqno); + +void grph_send(u_int8_t flags, + u_int8_t hcnt, + u_int32_t grp_addr, + u_int32_t grp_seqno); + +void grph_forward(GRPH * GRPH, int ttl); + +void grph_process(GRPH * GRPH, u_int32_t src, int ttl); + +void grph_send_callback(mrt_table_t *mrt); + +#endif /* NS_NO_DECLARATIONS */ + +#endif /* MAODV_GRPH_H */ diff -urNb aodv-uu-0.7.2/maodv_mact.c maodv-umd-0.7.2/maodv_mact.c --- aodv-uu-0.7.2/maodv_mact.c Wed Dec 31 19:00:00 1969 +++ maodv-umd-0.7.2/maodv_mact.c Mon Jun 30 13:53:47 2003 @@ -0,0 +1,302 @@ +#ifdef MAODV + +/***************************************************************************** + * + * Copyright (C) 2003 CSHCN, University of Maryland. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Authors: Dionysus Blazakis + * Jonathan Polley + * Dan Rusk + * Manish Karir + * Jonathan McGee + * + *****************************************************************************/ + +#ifdef NS_PORT +#include "aodv-uu.h" +#else +#include +#include "maodv_mact.h" +#include "maodv_grph.h" +#include "aodv_socket.h" +#include "params.h" +#include "seek_list.h" +#include "defs.h" +#include "debug.h" +#include "multicast_routing_table.h" +#include "packet_queue.h" +#endif + +MACT *mact_create(u_int8_t flags, u_int8_t hcnt, u_int32_t src_addr, + u_int32_t grp_addr) +{ + MACT *mact; + + mact=(MACT *)aodv_socket_new_msg(); + + mact->type=MAODV_MACT; + mact->res1=0; + mact->res2=0; + mact->hcnt=hcnt; + mact->grp_addr=htonl(grp_addr); + mact->src_addr=htonl(src_addr); + mact->src_seqno=htonl(++this_host.seqno); + + /* handle flags */ + if(flags & MACT_JOIN) + mact->j=1; + if(flags & MACT_PRUNE) + mact->p=1; + if(flags & MACT_GRPL) + mact->g=1; + if(flags & MACT_UPDATE) + mact->u=1; + if(flags & MACT_REBOOT) + mact->r=1; + + DEBUG(LOG_DEBUG, 0, "Assembled MACT %s", ip_to_str(grp_addr)); + + return mact; +} + +void mact_send(u_int8_t flags, u_int8_t hcnt, u_int32_t grp_addr, u_int32_t dst_addr, int ttl) +{ + MACT *mact; + rt_table_t *route; + int i; + + route=rt_table_find(dst_addr); + i=route->ifindex; + mact=mact_create(flags, hcnt, DEV_IFINDEX(i).ipaddr, grp_addr); + + aodv_socket_send((AODV_msg *)mact, dst_addr, MACT_SIZE, ttl, &DEV_IFINDEX(i)); +} + +void mact_mcast(u_int8_t flags, u_int8_t hcnt, u_int32_t grp_addr, int ttl) +{ + MACT *mact; + mrt_table_t *group_rec; + mrt_nexthop_t *nexthop; + rt_table_t *route; + /* prevent sending packet twice on an iface */ + static char ifmask[MAX_NR_INTERFACES]; + int i; + + bzero(ifmask, sizeof(ifmask)*sizeof(char)); + + group_rec=mrt_table_find(grp_addr); + nexthop=group_rec->nexthops; + + /* an attempt to send multicast packets right. + * destination is group address + * only send one per interface you are currently multicasting to group on + */ + while(nexthop!=NULL) { + route=rt_table_find(nexthop->addr); + i=route->ifindex; + if (!DEV_IFINDEX(i).enabled) + continue; + if (!ifmask[i]) { + mact=mact_create(flags, hcnt, DEV_IFINDEX(i).ipaddr, grp_addr); + aodv_socket_send((AODV_msg *)mact, grp_addr, MACT_SIZE, ttl, &DEV_IFINDEX(i)); + ifmask[i]=1; + } + nexthop=nexthop->next; + } +} + +void mact_process(MACT *mact) +{ + u_int32_t src_addr, grp_addr, src_seqno; + u_int8_t hcnt; + mrt_table_t *group_rec; + + src_addr=ntohl(mact->src_addr); + grp_addr=ntohl(mact->grp_addr); + src_seqno=ntohl(mact->src_seqno); + hcnt=mact->hcnt; + + group_rec=mrt_table_find(grp_addr); + + if(group_rec == NULL) { + /* shouldn't happen */ + return; + } + + if(mact->j) { + /* JOIN */ + /* sender wants to join specified group with us as next hop. + * if we are already in group, then fine, else need to + * pseudo-join ourselves. + */ + mrt_nexthop_t *nh; + + nh=mrt_nexthop_find(group_rec, src_addr); + if(nh==NULL){ + nh=mrt_nexthop_add(group_rec, src_addr, MRT_DOWNSTREAM, src_seqno); + } + if(nh->activated){ + mrt_nexthop_deactivate(group_rec, nh->addr); + } + if ( nh->direction==MRT_UPSTREAM) { + nh->direction=MRT_DOWNSTREAM; + } + mrt_nexthop_activate(group_rec, src_addr); + DEBUG(LOG_DEBUG, 0, "activated downstream %s", ip_to_str(src_addr)); + + /* check if we are not leader and yet have no upstream*/ + if(!group_rec->am_leader && group_rec->activated_upstream_cnt==0) { + /* not leader and no upstream, so activate one */ + mact_activate_best_upstream(group_rec); + } + + + }else if(mact->p) { + /* PRUNE */ + mrt_nexthop_t *nexthop; + + DEBUG(LOG_DEBUG, 0, "Entered mact->p handler"); + + nexthop=mrt_table_get_activated_upstream(group_rec); + if(nexthop!=NULL && nexthop->addr==src_addr){ + DEBUG(LOG_DEBUG, 0, "\tUpstream sent prune"); + /* deactivate said upstream in our records */ + mrt_nexthop_deactivate(group_rec, nexthop->addr); + /* upstream sent us prune */ + /* if member, become leader, else leave and make a downstream */ + if(group_rec->is_member || (group_rec->is_gateway + && group_rec->activated_downstream_cnt > 0)){ + mrt_table_become_leader(group_rec); + }else{ + mact_make_downstream_leader(group_rec); + } + } + + /* if no other downstreams and not listening ourselves, prune self */ + else if(!group_rec->is_member + && (!group_rec->is_gateway || group_rec->activated_upstream_cnt == 0) + && (group_rec->activated_downstream_cnt == 1)) { + mrt_nexthop_t *upstream; + /* Gateway code can create non-member leaders */ + group_rec->is_gateway = 0; + group_rec->am_leader = 0; + upstream=mrt_table_get_activated_upstream(group_rec); + DEBUG(LOG_DEBUG, 0, "\tDownstream sent prune, prune self"); + if(upstream != NULL){ + mact_send(MACT_PRUNE, 1, grp_addr, upstream->addr,1); + mrt_nexthop_deactivate(group_rec, upstream->addr); + } + mrt_table_stop_routing(group_rec); + }else{ + DEBUG(LOG_DEBUG, 0, "\tDownstream sent prune, stay on tree"); + } + + /* remove them */ + mrt_nexthop_deactivate(group_rec, src_addr); + } else if(mact->g) { + /* GR/OUP LEADER + * + * my upstream may send it to me. + * either I become leader or I promote a child + */ + + /* node who sent it has me marked as its upstream now */ + mrt_nexthop_t *node; + node=mrt_table_get_activated_upstream(group_rec); + if(node!=NULL){ + node->direction=MRT_DOWNSTREAM; + group_rec->activated_upstream_cnt--; + group_rec->activated_downstream_cnt++; + } + + if(group_rec->is_member) { + /* declare myself leader */ + /* TODO: might need to set U flag on first one */ + + mrt_table_become_leader(group_rec); + } else { + /* send a notice to a downstream making it leader */ + mact_make_downstream_leader(group_rec); + } + } else if(mact->u) { + /* UPDATE */ + } else if(mact->r) { + /* REBOOT */ + } +} + +mrt_nexthop_t *mact_activate_best_upstream(mrt_table_t *mrt){ + mrt_nexthop_t *besthop=NULL; + + besthop=mrt_table_get_best_upstream(mrt); + + /* and activate it */ + if(besthop!=NULL){ + mrt_table_start_routing(mrt); + + mrt_nexthop_activate(mrt, besthop->addr); + mact_send(MACT_JOIN, 1, mrt->grp_addr, besthop->addr, 1); + DEBUG(LOG_DEBUG, 0, "activated upstream %s", ip_to_str(besthop->addr)); + + if ( seek_list_remove(seek_list_find(mrt->grp_addr) ) ) { + mcast_packet_queue_send( mrt->grp_addr ); + } + } + + return besthop; +} + +void mact_make_downstream_leader(mrt_table_t *group_rec){ + mrt_nexthop_t *downstream; + DEBUG(LOG_DEBUG, 0, "Entered mact_make_downstream_leader"); + + if(group_rec->activated_downstream_cnt==0){ + DEBUG(LOG_DEBUG, 0, "No downstreams to make leader! Clearing flags"); + mrt_table_stop_routing(group_rec); + group_rec->is_gateway = 0; + return; + } + + downstream=group_rec->nexthops; + while(downstream->direction!=MRT_DOWNSTREAM || !downstream->activated){ + downstream=downstream->next; + } + + if(group_rec->activated_downstream_cnt==1){ + /* one child, make him leader */ + DEBUG(LOG_DEBUG, 0, "\tEntered one child version"); + mact_send(MACT_PRUNE, 0, group_rec->grp_addr, downstream->addr,1); + mrt_nexthop_deactivate(group_rec, downstream->addr); + mrt_table_stop_routing(group_rec); + + /* remove any pending RREQs (or other packets) for this group */ + seek_list_remove(seek_list_find(group_rec->grp_addr)); + packet_queue_drop(group_rec->grp_addr); + + /* flush all nexthops */ + mrt_nexthop_remove_all(group_rec); + }else{ + /* send a 'G' mact to an arbitrary child, then make it upstream */ + DEBUG(LOG_DEBUG, 0, "\tEntered many child version (where you stay as router)"); + mact_send(MACT_GRPL, 0, group_rec->grp_addr, downstream->addr,1); + downstream->direction=MRT_UPSTREAM; + group_rec->activated_downstream_cnt--; + group_rec->activated_upstream_cnt++; + } +} + +#endif /* MAODV */ diff -urNb aodv-uu-0.7.2/maodv_mact.h maodv-umd-0.7.2/maodv_mact.h --- aodv-uu-0.7.2/maodv_mact.h Wed Dec 31 19:00:00 1969 +++ maodv-umd-0.7.2/maodv_mact.h Wed Jun 25 17:46:10 2003 @@ -0,0 +1,98 @@ +/***************************************************************************** + * + * Copyright (C) 2003 CSHCN, University of Maryland. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Authors: Dionysus Blazakis + * Jonathan Polley + * Dan Rusk + * Manish Karir + * + *****************************************************************************/ + +#ifndef MAODV_MACT_H +#define MAODV_MACT_H + +#ifndef NS_NO_GLOBALS +#include + +#include "defs.h" +#include "multicast_routing_table.h" + +/* MACT Flags: */ +#define MACT_JOIN 0x10 +#define MACT_PRUNE 0x08 +#define MACT_GRPL 0x04 +#define MACT_UPDATE 0x02 +#define MACT_REBOOT 0x01 + +typedef struct _mact_t { + u_int8_t type; +# if __BYTE_ORDER == __LITTLE_ENDIAN + u_int8_t res1:3; + u_int8_t r:1; + u_int8_t u:1; + u_int8_t g:1; + u_int8_t p:1; + u_int8_t j:1; +# elif __BYTE_ORDER == __BIG_ENDIAN + u_int8_t j:1; + u_int8_t p:1; + u_int8_t g:1; + u_int8_t u:1; + u_int8_t r:1; + u_int8_t res1:3; +# else +# error "Adjust your defines" +# endif + u_int8_t res2; + u_int8_t hcnt; + u_int32_t grp_addr; + u_int32_t src_addr; + u_int32_t src_seqno; +} mact_t; + +#define MACT mact_t +#define MACT_SIZE sizeof(MACT) + +#endif /* NS_NO_GLOBALS */ + +#ifndef NS_NO_DECLARATIONS +MACT *mact_create(u_int8_t flags, + u_int8_t hcnt, + u_int32_t src_addr, + u_int32_t grp_addr); + +void mact_send(u_int8_t flags, + u_int8_t hcnt, + u_int32_t grp_addr, + u_int32_t dst_addr, + int ttl); + +void mact_mcast(u_int8_t flags, + u_int8_t hcnt, + u_int32_t grp_addr, + int ttl); + +void mact_process(MACT *mact); + +mrt_nexthop_t *mact_activate_best_upstream(mrt_table_t *mrt); +void mact_make_downstream_leader(mrt_table_t *mrt); + + +#endif /* NS_NO_DECLARATIONS */ + +#endif /* MAODV_MACT_H */ diff -urNb aodv-uu-0.7.2/maodv_neighbor.c maodv-umd-0.7.2/maodv_neighbor.c --- aodv-uu-0.7.2/maodv_neighbor.c Wed Dec 31 19:00:00 1969 +++ maodv-umd-0.7.2/maodv_neighbor.c Wed Jun 25 17:46:09 2003 @@ -0,0 +1,108 @@ +#ifdef MAODV + +/***************************************************************************** + * + * Copyright (C) 2003 CSHCN, University of Maryland. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Authors: Dionysus Blazakis + * Jonathan Polley + * Dan Rusk + * Manish Karir + * Jonathan McGee + * + *****************************************************************************/ + +#include "maodv_neighbor.h" +#include "routing_table.h" +#include "multicast_routing_table.h" +#include "aodv_rreq.h" +#include "maodv_mact.h" +#include "debug.h" +#include "params.h" + +void mcast_neighbor_link_break(rt_table_t *rt){ + mrt_table_t *mrt; + mrt_nexthop_t *nexthop; + int i; + + /* determine which, if any, groups the broken node is in */ + for(i=0; idest_addr); + + /* only care about activated routes */ + if(nexthop!=NULL && nexthop->activated){ + int nh_dir=nexthop->direction; + + mrt_nexthop_remove(mrt, nexthop->addr); + if(nh_dir==MRT_UPSTREAM){ + mrt->is_broken = 1; + + /* we lost our upstream, find a new one */ + rreq_route_discovery(mrt->grp_addr, + RREQ_JOIN|RREQ_GRP_REBUILD, NULL, 0); + }else{ + /* we lost our downstream, wait to see if he returns */ + mrt_nexthop_remove(mrt, nexthop->addr); + + if(!mrt->is_member && mrt->activated_downstream_cnt==0){ + DEBUG(LOG_DEBUG, 0, "setting prune dangle timer"); + + /* set timeout to prune self if downstream doesn't + * reconnect */ + mrt->prune_timer.handler = (timeout_func_t) &mcast_prune_dangle; + mrt->prune_timer.data = &mrt; + + /* 20 seconds of rebuild time. */ + timer_set_timeout( &mrt->prune_timer, PRUNE_TIMEOUT ); + } + } + }else if(nexthop!=NULL && !nexthop->activated){ + mrt_nexthop_remove(mrt, nexthop->addr); + } + + mrt=mrt->next; + } + } +} + +/* mcast_prune_dangle + * if you become a router only with no downstream nodes, (dangling) then + * prune self after a timeout */ +void mcast_prune_dangle( mrt_table_t *mrt ) { + mrt_nexthop_t * upstream; + + DEBUG(LOG_DEBUG, 0, "in prune dangle timer"); + if ( mrt->activated_downstream_cnt == 0 && !mrt->is_member + && (!mrt->is_gateway || (mrt->activated_upstream_cnt == 0))) { + /* prune me */ + + upstream = mrt_table_get_activated_upstream( mrt ); + DEBUG( LOG_DEBUG, 0, "Pruning myself after a reasonable timeout." ); + + if(upstream != NULL){ + mact_send( MACT_PRUNE, 1, mrt->grp_addr, upstream->addr, 1 ); + mrt_nexthop_deactivate( mrt, upstream->addr ); + } + + mrt_table_stop_routing(mrt); + } +} + +#endif diff -urNb aodv-uu-0.7.2/maodv_neighbor.h maodv-umd-0.7.2/maodv_neighbor.h --- aodv-uu-0.7.2/maodv_neighbor.h Wed Dec 31 19:00:00 1969 +++ maodv-umd-0.7.2/maodv_neighbor.h Wed Jun 25 17:46:10 2003 @@ -0,0 +1,38 @@ +/***************************************************************************** + * + * Copyright (C) 2003 CSHCN, University of Maryland. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Authors: Dionysus Blazakis + * Jonathan Polley + * Dan Rusk + * Manish Karir + * + *****************************************************************************/ + +#ifndef MAODV_NEIGHBOR_H +#define MAODV_NEIGHBOR_H + +#include "routing_table.h" +#include "multicast_routing_table.h" + +void mcast_neighbor_link_break(rt_table_t *rt); +/* mcast_prune_dangle + * if you become a router only with no downstream nodes, (dangling) then + * prune self after a timeout */ +void mcast_prune_dangle( mrt_table_t *mrt ); + +#endif diff -urNb aodv-uu-0.7.2/maodv_rrep.c maodv-umd-0.7.2/maodv_rrep.c --- aodv-uu-0.7.2/maodv_rrep.c Wed Dec 31 19:00:00 1969 +++ maodv-umd-0.7.2/maodv_rrep.c Wed Jun 25 17:46:10 2003 @@ -0,0 +1,191 @@ +#ifdef MAODV + +/***************************************************************************** + * + * Copyright (C) 2003 CSHCN, University of Maryland. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Authors: Dionysus Blazakis + * Jonathan Polley + * Dan Rusk + * Manish Karir + * + *****************************************************************************/ + +#include "defs.h" +#include "debug.h" +#include "maodv_rrep.h" +#include "routing_table.h" +#include "multicast_routing_table.h" +#include "aodv_socket.h" +#include "aodv_rreq.h" +#include "aodv_rrep.h" +#include "packet_queue.h" + +/* + * maodv_rrep_process( lots of stuff ) + * Processes an rrep that has already been sanity checked and is + * responding to a multicast group. + */ +void maodv_rrep_process( RREP *rrep, int rreplen, u_int32_t ip_src, + u_int32_t ip_dst, int ip_ttl, unsigned int ifindex, int size ) +{ + mrt_nexthop_t * upstream; + mrt_table_t * mrt; + rt_table_t * rev_rt; + u_int32_t rrep_orig, rrep_dest, rrep_seqno, rrep_lifetime; + mrt_orig_t *orig; + + DEBUG( LOG_DEBUG, 0, "Inside RREP process." ); + + rrep_dest = ntohl(rrep->dest_addr); + rrep_seqno = ntohl(rrep->dest_seqno); + rrep_orig = ntohl(rrep->orig_addr); + rrep_lifetime = ntohl(rrep->lifetime); + + rev_rt = rt_table_find( rrep_orig ); + mrt = mrt_table_find( rrep_dest ); + + if ( !mrt ) { + log(LOG_WARNING, 0, __FUNCTION__, + "No multicast route to group %s found in RREP.", + ip_to_str( rrep_dest ) ); + return; + } + + upstream = mrt_nexthop_find(mrt, ip_src); + if(upstream == NULL){ + DEBUG( LOG_DEBUG, 0, "Created nexthop." ); + upstream = mrt_nexthop_add( mrt, ip_src, MRT_UPSTREAM, rrep_seqno ); + } else { + /* update seqno */ + DEBUG( LOG_DEBUG, 0, "Had nexthop, updated seqno." ); + upstream->grp_seqno = rrep_seqno; + } + + /* add the originator to the originator list if not there already */ + orig=mrt_origlist_find(mrt, rrep_orig); + if(orig==NULL){ + DEBUG(LOG_DEBUG, 0, "originator not in list, adding"); + orig=mrt_origlist_add(mrt, rrep_orig); + } + + DEBUG(LOG_DEBUG, 0, "originator seqno: %d hcnt: %d", orig->grp_seqno, + orig->grp_hcnt); + + /* rrep is propagated if the prior rreq had a lower + sequence number or the sequence numbers are equal and the + incoming rrep has a smaller hopcount */ + if ( ( ( orig->grp_seqno < rrep_seqno ) || + ( ( orig->grp_seqno == rrep_seqno ) && + ( orig->grp_hcnt > rrep->hcnt ) ) ) ){ + + DEBUG( LOG_DEBUG, 0, "Forwardable/acceptable rrep." ); + + mrt->grp_seqno = rrep_seqno; + orig->grp_seqno=rrep_seqno; + orig->grp_hcnt = rrep->hcnt; + + if ( !upstream->activated ) { + upstream->direction = MRT_UPSTREAM; + upstream->grp_hcnt = rrep->hcnt; + } + + if ( rrep_orig != DEV_IFINDEX(ifindex).ipaddr ) + maodv_rrep_forward( rrep, rev_rt, mrt, --ip_ttl, size ); + } else { + DEBUG( LOG_DEBUG, 0,"mrt->grp_seqno: %d\trrep_seqno: %d", + mrt->grp_seqno, rrep_seqno ); + } +} + +void maodv_rrep_forward( RREP * rrep, rt_table_t * rev_rt, + mrt_table_t * fwd_rt, int ttl, int size ) +{ + mrt_nexthop_t * upstream; + + if (!fwd_rt || !rev_rt) { + DEBUG(LOG_WARNING, 0, "Could not forward RERR because of NULL route!"); + return; + } + + if (!rrep) { + DEBUG(LOG_WARNING, 0, "No RREP to forward!"); + return; + } + + DEBUG(LOG_DEBUG, 0, "Forwarding RREP to %s", ip_to_str(rev_rt->next_hop)); + + rrep = (RREP *) aodv_socket_queue_msg((AODV_msg *) rrep, size); + upstream = mrt_table_get_best_upstream( fwd_rt ); + + /* Update the hopcount */ + if(!fwd_rt->is_router){ + rrep->hcnt++; + } + + aodv_socket_send((AODV_msg *) rrep, rev_rt->next_hop, size, ttl, + &DEV_IFINDEX(rev_rt->ifindex)); + + /* TODO: timing code... */ +/* rt_table_update_timeout(rev_rt, ACTIVE_ROUTE_TIMEOUT); */ +} + +void maodv_rrep_send( rt_table_t * rev_rt, mrt_table_t * fwd_rt ) +{ + RREP *rrep; + u_int8_t rrep_flags = 0; + u_int32_t dest, lifetime; + int hcnt; + + /* CHECK: we do not use this... */ + lifetime = 0x0ffffffff; + + if (!rev_rt) { + DEBUG(LOG_WARNING, 0, "Can't send RREP, rev_rt = NULL!"); + return; + } + + if (!fwd_rt) { + DEBUG(LOG_WARNING, 0, "Can't send RREP, fwd_rt = NULL!"); + return; + } + + DEBUG(LOG_DEBUG, 0, "[maodv] sending rrep."); + + dest = fwd_rt->grp_addr; + + hcnt = 0; + + /* TODO: timeout code... */ + /* + gettimeofday(&now, NULL); + lifetime = timeval_diff(&fwd_rt->rt_timer.timeout, &now); + */ + + DEBUG(LOG_DEBUG, 0, "[maodv] Sending RREP to %s about %s->%s", + ip_to_str(rev_rt->next_hop), ip_to_str(rev_rt->dest_addr), + ip_to_str(dest)); + + rrep = rrep_create(rrep_flags, 0, hcnt, dest, fwd_rt->grp_seqno, + rev_rt->dest_addr, lifetime, 0 ); + + aodv_socket_send((AODV_msg *) rrep, rev_rt->next_hop, RREP_SIZE, MAXTTL, + &DEV_IFINDEX(rev_rt->ifindex)); + +} + +#endif /* MAODV */ diff -urNb aodv-uu-0.7.2/maodv_rrep.h maodv-umd-0.7.2/maodv_rrep.h --- aodv-uu-0.7.2/maodv_rrep.h Wed Dec 31 19:00:00 1969 +++ maodv-umd-0.7.2/maodv_rrep.h Wed Jun 25 17:46:10 2003 @@ -0,0 +1,41 @@ +/***************************************************************************** + * + * Copyright (C) 2003 CSHCN, University of Maryland. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Authors: Dionysus Blazakis + * Jonathan Polley + * Dan Rusk + * Manish Karir + * + *****************************************************************************/ + +#ifndef MAODV_RREP_H +#define MAODV_RREP_H + +#include "routing_table.h" +#include "multicast_routing_table.h" +#include "aodv_rrep.h" + +void maodv_rrep_process( RREP *rrep, int rreplen, u_int32_t ip_src, + u_int32_t ip_dst, int ip_ttl, unsigned int ifindex, int size ); + +void maodv_rrep_forward( RREP * rrep, rt_table_t * rev_rt, + mrt_table_t * fwd_rt, int ttl, int size ); + +void maodv_rrep_send( rt_table_t * rev_rt, mrt_table_t * fwd_rt ); + +#endif diff -urNb aodv-uu-0.7.2/maodv_rreq.c maodv-umd-0.7.2/maodv_rreq.c --- aodv-uu-0.7.2/maodv_rreq.c Wed Dec 31 19:00:00 1969 +++ maodv-umd-0.7.2/maodv_rreq.c Wed Jun 25 17:46:10 2003 @@ -0,0 +1,175 @@ +#ifdef MAODV + +/***************************************************************************** + * + * Copyright (C) 2003 CSHCN, University of Maryland. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Authors: Dionysus Blazakis + * Jonathan Polley + * Dan Rusk + * Manish Karir + * + *****************************************************************************/ + +#include "defs.h" +#include "debug.h" +#include "maodv_rreq.h" +#include "maodv_rrep.h" +#include "multicast_routing_table.h" +#include "aodv_socket.h" +#include "aodv_rreq.h" +#include "aodv_rrep.h" +#include "maodv_ext.h" + +/* + * maodv_rreq_process( lots of stuff ) + * Processes an rreq that has already been sanity checked and is + * headed for a multicast group. + */ +void maodv_rreq_process( RREQ *rreq, int rreqlen, u_int32_t ip_src, + u_int32_t ip_dst, int ip_ttl, unsigned int ifindex, + GRP_REBUILD_EXT *grb_ext, int size ) +{ + mrt_table_t * mrt; + rt_table_t * rev_rt; + u_int32_t rreq_orig, rreq_dest, rreq_orig_seqno, rreq_dest_seqno; + u_int32_t rreq_id, rreq_new_hcnt; + mrt_nexthop_t * nh; + mrt_orig_t *orig; + + DEBUG( LOG_DEBUG, 0, "Inside RREP process." ); + + rreq_id = ntohl(rreq->rreq_id); + rreq_dest = ntohl(rreq->dest_addr); + rreq_dest_seqno = ntohl(rreq->dest_seqno); + rreq_orig = ntohl(rreq->orig_addr); + rreq_orig_seqno = ntohl(rreq->orig_seqno); + rreq_new_hcnt = rreq->hcnt + 1; + + mrt = mrt_table_find( rreq_dest ); + if ( mrt==NULL ) { + /* no route found */ + DEBUG(LOG_DEBUG, 0, "MRREQ: No mrt found." ); + mrt = mrt_table_insert( rreq_dest, 0, rreq_dest_seqno, + ifindex, 255, 0 ); + } + + /* add nexthop downstream */ + nh = mrt_nexthop_find( mrt, rreq_orig ); + if ( nh == NULL ) { + mrt_nexthop_add( mrt, ip_src, MRT_DOWNSTREAM, rreq_dest_seqno ); + } + + /* add the originator to the originator list if not there already */ + orig=mrt_origlist_find(mrt, rreq_orig); + if(orig==NULL){ + DEBUG(LOG_DEBUG, 0, "originator not in list, adding"); + orig=mrt_origlist_add(mrt, rreq_orig); + } + DEBUG(LOG_DEBUG, 0, "originator seqno: %d hcnt: %d", orig->grp_seqno, orig->grp_hcnt); + + if ( rreq->j ) { + /* a Join request */ + DEBUG(LOG_DEBUG, 0, "MRREQ: [j] Join." ); + + if ( !mrt->is_router) { + DEBUG(LOG_DEBUG, 0, "MRREQ: [j] Found a mrt, but not on the tree."); + } else if ( mrt->grp_seqno < rreq_dest_seqno ) { + DEBUG(LOG_DEBUG, 0, "MRREQ: [j] Found a mrt, but it is old. %d < %d", mrt->grp_seqno, rreq_dest_seqno ); + mrt->grp_seqno = rreq_dest_seqno; + } else { + if(grb_ext==NULL || mrt->leader_hcnt<=grb_ext->grp_hcnt){ + DEBUG(LOG_DEBUG, 0, "MRREQ: [j] Should send RREP!" ); + + /* send rrep */ + rev_rt = rt_table_find( rreq_orig ); + orig->grp_seqno=mrt->grp_seqno; + orig->grp_hcnt=0; + maodv_rrep_send( rev_rt, mrt ); + + /* done! get out */ + return; + }else{ + DEBUG(LOG_DEBUG, 0, "had repair extension, bad hopcount, do nothing"); + } + } + } else { + /* non-Join request */ + DEBUG(LOG_DEBUG, 0, "MRREQ: [] non-Join." ); + + if ( mrt->grp_seqno < rreq_dest_seqno ) { + DEBUG(LOG_DEBUG, 0, "MRREQ: [] Found a mrt, but it is old." ); + /* update sequence number in our table */ + mrt->grp_seqno = rreq_dest_seqno; + } else if ( mrt->is_router ) { + DEBUG(LOG_DEBUG, 0, "MRREQ: [] Should send RREP!" ); + + /* send rrep */ + rev_rt = rt_table_find( rreq_orig ); + orig->grp_seqno=mrt->grp_seqno; + orig->grp_hcnt=0; + maodv_rrep_send( rev_rt, mrt ); + + /* we're done! */ + return; + } + } + + /* if we get this far, no RREP has been sent. */ + + /* now, forward RREQ */ + /* if rreq has unknown seqno and our table has a known one + (not zero), then update packet seqno field. or if ours + is just bigger. + CHECK: this may not be the way to do this */ + if ( ( mrt->grp_seqno > rreq_dest_seqno ) || + ( rreq->u && mrt->grp_seqno ) ) { + rreq->u = 0; + rreq->dest_seqno = htonl( mrt->grp_seqno ); + } + + /* send it back out */ + maodv_rreq_forward( rreq, --ip_ttl, size ); +} + +/* + * maodv_rreq_forward( RREQ * rreq, int ttl, int size ) + * Forwards a route request. + */ +void maodv_rreq_forward( RREQ * rreq, int ttl, int size ) +{ + int i; + /* FORWARD the RREQ if the TTL allows it. */ + DEBUG(LOG_DEBUG, 0, "[maodv] forwarding RREQ src=%s, rreq_id=%lu", + ip_to_str(ntohl(rreq->orig_addr)), ntohl(rreq->rreq_id)); + + /* Queue the received message in the send buffer */ + rreq = (RREQ *) aodv_socket_queue_msg((AODV_msg *) rreq, size); + + rreq->hcnt++; /* Increase hopcount to account for + * intermediate route */ + + /* Send out on all interfaces */ + for (i = 0; i < MAX_NR_INTERFACES; i++) { + if (!DEV_NR(i).enabled) + continue; + aodv_socket_send((AODV_msg *) rreq, AODV_BROADCAST, size, ttl, + &DEV_NR(i)); + } +} + +#endif /* MAODV */ diff -urNb aodv-uu-0.7.2/maodv_rreq.h maodv-umd-0.7.2/maodv_rreq.h --- aodv-uu-0.7.2/maodv_rreq.h Wed Dec 31 19:00:00 1969 +++ maodv-umd-0.7.2/maodv_rreq.h Wed Jun 25 17:46:10 2003 @@ -0,0 +1,39 @@ +/***************************************************************************** + * + * Copyright (C) 2003 CSHCN, University of Maryland. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Authors: Dionysus Blazakis + * Jonathan Polley + * Dan Rusk + * Manish Karir + * + *****************************************************************************/ + +#ifndef MAODV_RREQ_H +#define MAODV_RREQ_H + +#include "defs.h" +#include "aodv_rreq.h" +#include "maodv_ext.h" + +void maodv_rreq_process( RREQ *rreq, int rreqlen, u_int32_t ip_src, + u_int32_t ip_dst, int ip_ttl, unsigned int ifindex, + GRP_REBUILD_EXT *grb_ext, int size ); + +void maodv_rreq_forward( RREQ * rreq, int ttl, int size ); + +#endif /* MAODV_RREQ_H */ diff -urNb aodv-uu-0.7.2/multicast_packet_cache.c maodv-umd-0.7.2/multicast_packet_cache.c --- aodv-uu-0.7.2/multicast_packet_cache.c Wed Dec 31 19:00:00 1969 +++ maodv-umd-0.7.2/multicast_packet_cache.c Wed Jun 25 17:46:10 2003 @@ -0,0 +1,80 @@ +#ifdef MAODV + +/***************************************************************************** + * + * Copyright (C) 2003 CSHCN, University of Maryland. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Authors: Matthew Impett + * + * + *****************************************************************************/ + +#include "multicast_packet_cache.h" + +void init_packet_cache(void) +{ + int i; + int j; + for(i=0; i< HASHBUCKETS; i++) + { + packet_cache[i].packet_cache_write_index = 0; + for(j=0; j < MAX_PACKET_CACHE; j++) + { + packet_cache[i].ip_src[j] = 0; + packet_cache[i].ip_id[j] = 0; + packet_cache[i].ip_hook[j] = 0; + } + } +} + +/* This function returns 1 if a duplicate packet has not been + found and returns 0 if a duplicate packet has not been found and adds + that packet to the packet cache. */ +int check_duplicate(u_int32_t src, u_int16_t id, u_int8_t hook) +{ + u_int8_t hash_value; + int i; + int j = 0; + hash_value = packet_hashfunction(src); + + for(i=0; i< MAX_PACKET_CACHE; i++) + { + if( (packet_cache[hash_value].ip_src[i] == src) && + (packet_cache[hash_value].ip_id[i] == id) && + (packet_cache[hash_value].ip_hook[i] == hook) ) + { + /* Found a duplicate packet.... Drop it */ + return 0; + } + } + + /* Not found the packet in the cache... Add it to the packet cache */ + + j = packet_cache[hash_value].packet_cache_write_index ; + packet_cache[hash_value].ip_src[j] = src; + packet_cache[hash_value].ip_id[j] = id; + packet_cache[hash_value].ip_hook[j] = hook; + packet_cache[hash_value].packet_cache_write_index = (j+1)%(MAX_PACKET_CACHE); + return 1; +} + +u_int8_t packet_hashfunction(u_int32_t addr) +{ + return ((addr >> 24) % HASHBUCKETS); +} + +#endif /* MAODV */ diff -urNb aodv-uu-0.7.2/multicast_packet_cache.h maodv-umd-0.7.2/multicast_packet_cache.h --- aodv-uu-0.7.2/multicast_packet_cache.h Wed Dec 31 19:00:00 1969 +++ maodv-umd-0.7.2/multicast_packet_cache.h Wed Jun 25 17:46:10 2003 @@ -0,0 +1,54 @@ +/***************************************************************************** + * + * Copyright (C) 2003 CSHCN, University of Maryland. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Authors: Matthew Impett + * + * + *****************************************************************************/ + +/********************************************************************** + The following packet cache has been obtained from Matthew Impett's + TORA implementation code..... + **********************************************************************/ + +#ifndef MULTICAST_PACKET_CACHE_H +#define MULTICAST_PACKET_CACHE_H + +#include "defs.h" + +#define HASHBUCKETS 10 /* number of buckets for entries */ +#define MAX_PACKET_CACHE 10 /* # of packets for each hash bucket */ + +/* This structure is used to hold a little cache of recently forwarded + packets which we can use to detect duplicate packets. */ +struct pack_cache +{ + u_int32_t ip_src[MAX_PACKET_CACHE]; + u_int16_t ip_id[MAX_PACKET_CACHE]; + u_int8_t ip_hook[MAX_PACKET_CACHE]; + int packet_cache_write_index; +}; + +struct pack_cache packet_cache[HASHBUCKETS]; +void init_packet_cache(void); +u_int8_t packet_hashfunction(u_int32_t addr); +int check_duplicate(u_int32_t source, u_int16_t id, + u_int8_t hook); + +#endif /* MULTICAST_PACKET_CACHE_H */ + diff -urNb aodv-uu-0.7.2/multicast_routing_table.c maodv-umd-0.7.2/multicast_routing_table.c --- aodv-uu-0.7.2/multicast_routing_table.c Wed Dec 31 19:00:00 1969 +++ maodv-umd-0.7.2/multicast_routing_table.c Wed Jun 25 17:46:10 2003 @@ -0,0 +1,983 @@ +#ifdef MAODV + +/***************************************************************************** + * + * Copyright (C) 2003 CSHCN, University of Maryland. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Authors: Dionysus Blazakis + * Jonathan Polley + * Dan Rusk + * Manish Karir + * Jonathan McGee + * + *****************************************************************************/ + +#include +#include +#include +#include +#include + +#include "multicast_routing_table.h" + +#include "igmp.h" +#include "aodv_timeout.h" +#include "packet_queue.h" +#include "aodv_rerr.h" +#include "aodv_hello.h" +#include "aodv_socket.h" +#include "k_route.h" +#include "k_mroute.h" +#include "timer_queue.h" +#include "defs.h" +#include "debug.h" +#include "params.h" +#include "seek_list.h" +#include "maodv_mact.h" +#include "maodv_grph.h" + +static struct timer mrt_debug_timer; + +struct multicast_routing_table mrt_tbl; + +inline static unsigned int hashing(u_int32_t addr); + +/* + Local static functions +*/ + +/* + hashing( addr ) + A VERY simple "hash" function. Taskes the multicast address as + a key and hacks off the most significant bits. (how many bits it + masks off depends on the size of the hash table. look at the + MRT_TABLEMASK define) This becomes an index into the hash table. + +*/ +inline static unsigned int hashing(u_int32_t addr) +{ + return( addr & MRT_TABLEMASK ); +} + +/* + * Public functions + */ + +/* + * mrt_table_init( ) + * Create an empty table with 0 entries. + */ +void mrt_table_init() +{ + int index; + int fd; + + mrt_tbl.num_entries = 0; + + /* init buckets with null pointers. */ + for( index = 0; index < MRT_TABLESIZE; index++ ) { + mrt_tbl.tbl[index] = NULL; + } + + /* CHECK: add in with other log code? not yet... */ + + /* every 10 seconds? */ + mrt_debug_timer.handler = (timeout_func_t) &mrt_table_dump; + mrt_debug_timer.data = NULL; + + fd = open( "nh_log", O_RDWR | O_CREAT | O_TRUNC, S_IROTH | + S_IWUSR | S_IRUSR | S_IRGRP ); + + close ( fd ); + + fd = open( "mrt_log", O_RDWR | O_CREAT | O_TRUNC, S_IROTH | + S_IWUSR | S_IRUSR | S_IRGRP ); + + close ( fd ); + + mrt_table_dump(); +} + +/* + * mrt_table_destroy( ) + * Destroy table and each entry. + */ +void mrt_table_destroy() +{ + int index; + mrt_table_t *curr; + mrt_table_t *dead; + + for( index = 0; index < MRT_TABLESIZE; index++ ) { + curr = mrt_tbl.tbl[index]; + + while( curr ) { + dead = curr; + curr = curr->next; + + /* TODO: Timeout multicast routes. + timer_remove( &dead->mrt_timer ); */ + + mrt_nexthop_remove_all( dead ); + + mrt_sources_remove_all( dead ); + free( dead ); + } + + /* safety */ + mrt_tbl.tbl[index] = NULL; + } + + mrt_tbl.num_entries = 0; +} + +/* + * mrt_table_insert( route info ) + * This creates a route with NO next hop info. Any next hop info must be + * added with other function calls. + */ +mrt_table_t *mrt_table_insert(u_int32_t grp_addr, u_int32_t grp_leader_addr, + u_int32_t grp_seqno, + unsigned int ifindex, + u_int8_t leader_hcnt, + u_int8_t is_member) +{ + mrt_table_t *new_entry; + int index; + + /* if it's already in the table, we can't add it */ + if ( mrt_table_find( grp_addr ) ) { + return NULL; + } + + index = hashing( grp_addr ); + + new_entry = (mrt_table_t *) malloc( sizeof( mrt_table_t ) ); + if ( !new_entry ) { + /* go down if theres no memory? probably best idea */ + fprintf( stderr, "multicast_routing_table.c: Cannot allocate memory for route.\n" ); + exit( -1 ); + } + + new_entry->grp_addr = grp_addr; + new_entry->grp_leader_addr = grp_leader_addr; + new_entry->grp_seqno = grp_seqno; + new_entry->am_leader = 0; /* false... i am not leader! */ + + new_entry->ifindex = ifindex; + new_entry->leader_hcnt = leader_hcnt; + new_entry->is_member = is_member; + new_entry->is_router = 0; /* false */ + new_entry->is_broken = 0; /* false */ + new_entry->in_repair = 0; /* false */ + new_entry->is_gateway = 0; /* false */ + + /* initialize timers */ + + /* TODO: Timeout routes. + new_entry->mrt_timer.handler = &multicast_route_expire_timeout; + new_entry->mrt_timer.data = new_entry; */ + + /* empty next hop list */ + new_entry->nexthops = NULL; + new_entry->activated_upstream_cnt = 0; + new_entry->activated_downstream_cnt = 0; + + new_entry->sources = NULL; + new_entry->origlist = NULL; + + /* make me first, so next will be whoever is currently top of bucket */ + new_entry->next = mrt_tbl.tbl[index]; + mrt_tbl.tbl[index] = new_entry; + mrt_tbl.num_entries++; + /* CHECK: add kernel route entry */ + + /* grph timer */ + new_entry->grph_timer.handler=(timeout_func_t) &grph_send_callback; + new_entry->grph_timer.data=new_entry; + + /* start new timer */ + + /* TODO: Timeout routes. + DEBUG(LOG_INFO, 0, "New timer for %s, life=%d", + ip_to_str(new_entry->grp_addr), ACTIVE_ROUTE_TIMEOUT ); + + timer_set_timeout( &new_entry->mrt_timer, ACTIVE_ROUTE_TIMEOUT ); + */ + + return new_entry; +} + +/* + * mrt_table_update_timeout( route, lifetime ) + * Resets the route timeout. Renews the lease in the route table. + */ +NS_INLINE mrt_table_t *mrt_table_update_timeout(mrt_table_t * mrt, + u_int32_t lifetime) +{ + struct timeval new_timeout; + + /* make sure route tp update is somewhat legal. */ + if ( !mrt ) { + log(LOG_WARNING, 0, __FUNCTION__, + "Attempting to update NULL route."); + + return NULL; + } + + gettimeofday( &new_timeout, NULL ); + timeval_add_msec( &new_timeout, lifetime ); + + /* TODO: Timeout routes. + if ( timeval_diff( &mrt->mrt_timer.timeout, &new_timeout ) < 0 ) { + timer_set_timeout( &mrt->mrt_timer, lifetime ); + } + */ + + return mrt; +} + +/* + * mrt_table_find( group address ) + * This looks up an entry in the routing table. If none is found, + * NULL is returned. Otherwise a pointer to the entry is returned. + */ +mrt_table_t *mrt_table_find(u_int32_t grp_addr) +{ + mrt_table_t *curr; + int index; + + index = hashing( grp_addr ); + curr = mrt_tbl.tbl[index]; + + /* If nothing is in the bucket the group address hashes to, + return NULL. It's definitely not here. */ + if ( !curr ) { + return NULL; + } + + while( curr ) { + if ( curr->grp_addr == grp_addr ) { + break; + } + + curr = curr->next; + } + + return curr; +} + +/* + * mrt_table_delete( group addr ) + * Delete a route from the routing table. + */ +void mrt_table_delete(u_int32_t grp_addr) +{ + int index; + mrt_table_t * curr, * prev; + + index = hashing( grp_addr ); + + curr = mrt_tbl.tbl[index]; + prev = NULL; + + if ( !curr ) { + log(LOG_WARNING, 0, __FUNCTION__, + "Attempting to delete an unknown route."); + return; + } + + while( curr ) { + if ( curr->grp_addr == grp_addr ) { + break; + } + + prev = curr; + curr = curr->next; + } + + if ( !curr ) { + log(LOG_WARNING, 0, __FUNCTION__, + "Attempting to delete an unknown route."); + return; + } + + /* CHECK: Remove entry from kernel routing table. */ + /* TODO: Timeout routes. + timer_remove( &curr->mrt_timer ); */ + + mrt_nexthop_remove_all( curr ); + + if ( !prev ) { + /* Deleting the head */ + mrt_tbl.tbl[index] = NULL; + } else { + prev->next = curr->next; + } + + mrt_tbl.num_entries--; + + free( curr ); +} + +/* + * mrt_nexthop_add( multi route, nh addr, direction ) + * Adds a nexthop entry into a routes information. Starts out unactivated. + */ +mrt_nexthop_t * mrt_nexthop_add(mrt_table_t * mrt, u_int32_t addr, + u_int8_t direction, u_int32_t grp_seqno) +{ + mrt_nexthop_t *newhop; + + if ( !mrt ) { + log(LOG_WARNING, 0, __FUNCTION__, + "Attempting to add a next hop to an unknown route."); + return NULL; + } + + newhop = mrt_nexthop_find( mrt, addr ); + if ( newhop ) { /* if it's already there, update it? */ + return newhop; + } + + newhop = (mrt_nexthop_t *) malloc( sizeof( mrt_nexthop_t ) ); + if ( !newhop ) { + fprintf( stderr, "multicast_routing_table.c: Error allocating nexthop entry.\n" ); + exit( -1 ); + } + + newhop->addr = addr; + newhop->direction = direction; + newhop->activated = 0; /* 0 == FALSE */ + newhop->grp_hcnt = 0xff; /* start with infinite hcnt */ + newhop->grp_seqno=grp_seqno; + + newhop->next = mrt->nexthops; + mrt->nexthops = newhop; + + return newhop; +} + +/* + * mrt_nexthop_remove( route, addr ) + * Remove a nexthop entry from a kernel route info. + */ +void mrt_nexthop_remove(mrt_table_t * mrt, u_int32_t addr ) +{ + mrt_nexthop_t * curr, * prev; + + if ( !mrt ) { + log(LOG_WARNING, 0, __FUNCTION__, + "Attempting to remove a next hop from an unknown route."); + return; + } + + curr = mrt->nexthops; + prev = NULL; + + if ( !curr ) { + log(LOG_WARNING, 0, __FUNCTION__, + "Attempting to remove a next hop [%s] that doesn't exist.", + ip_to_str( addr ) ); + return; + } + + while( curr ) { + if ( curr->addr == addr ) { + break; + } + + prev = curr; + curr = curr->next; + } + + if ( !curr ) { + log(LOG_WARNING, 0, __FUNCTION__, + "Attempting to remove a next hop that doesn't exist."); + return; + } + + mrt_nexthop_deactivate(mrt, addr); + + if ( !prev ) { + mrt->nexthops = curr->next; + } else { + prev->next = curr->next; + } + + free( curr ); +} + +/* + * mrt_nexthop_activated( route, addr, on/off ) + * Sets a certain nexthop flag indicating if this route is active or not. + */ +void mrt_nexthop_activate(mrt_table_t * mrt, u_int32_t addr) +{ + FILE *nh_log; + mrt_nexthop_t *curr; + + if ( !mrt ) { + log(LOG_WARNING, 0, __FUNCTION__, + "Attempting to activate a next hop for a NULL route."); + return; + } + + curr = mrt->nexthops; + + while( curr ) { + if ( curr->addr == addr ) { + break; + } + + curr = curr->next; + } + + if ( !curr ) { + log(LOG_WARNING, 0, __FUNCTION__, + "Attempting to activate a next hop that doesn't exist."); + return; + } + + curr->activated = 1; + + if ( curr->direction == MRT_UPSTREAM ) { + mrt->activated_upstream_cnt++; + } else if ( curr->direction == MRT_DOWNSTREAM ) { + mrt->activated_downstream_cnt++; + } + + nh_log=fopen("nh_log", "a"); + fprintf(nh_log, "ACTIVATE: %x %x\n", mrt->grp_addr, addr); + fclose(nh_log); +} + +/* + * mrt_nexthop_deactivate( route, addr ) + * Sets a certain nexthop flag indicating if this route is active or not. + */ +void mrt_nexthop_deactivate(mrt_table_t * mrt, u_int32_t addr) +{ + FILE *nh_log; + mrt_nexthop_t *curr; + + if ( !mrt ) { + log(LOG_WARNING, 0, __FUNCTION__, + "Attempting to activate a next hop for a NULL route."); + return; + } + + curr = mrt->nexthops; + + while( curr ) { + if ( curr->addr == addr ) { + break; + } + + curr = curr->next; + } + + if ( !curr ) { + log(LOG_WARNING, 0, __FUNCTION__, + "Attempting to deactivate a next hop that doesn't exist."); + return; + } + + if(curr->activated == 1){ + if ( curr->direction == MRT_UPSTREAM ) { + mrt->activated_upstream_cnt--; + } else if ( curr->direction == MRT_DOWNSTREAM ) { + mrt->activated_downstream_cnt--; + } + + curr->activated=0; + + nh_log=fopen("nh_log", "a"); + fprintf(nh_log, "DEACTIVATE: %x %x\n", mrt->grp_addr, addr); + fclose(nh_log); + } +} + +/* + * mrt_nexthop_get_upstream( table entry ) + * Returns pointer to activated upstream next hop. + */ +mrt_nexthop_t *mrt_table_get_activated_upstream(mrt_table_t * mrt) +{ + mrt_nexthop_t *curr; + + if ( !mrt ) { + log(LOG_WARNING, 0, __FUNCTION__, + "Attempting to get an upstream for a NULL route."); + return NULL; + } + + curr = mrt->nexthops; + + while( curr ) { + if ( ( curr->activated ) && ( curr->direction == MRT_UPSTREAM ) ) { + break; + } + + curr = curr->next; + } + + return curr; +} + +/* + * mrt_nexthop_remove_all( table entry ) + * Destroys every entry in next_hop list for a multicast route. + */ +void mrt_nexthop_remove_all(mrt_table_t * mrt) +{ + mrt_nexthop_t *curr, *dead; + + curr = mrt->nexthops; + + while( curr ) { + dead = curr; + curr = curr->next; + + free( dead ); + } + + /* easier to debug if it's NULL instead of garbage */ + mrt->nexthops = NULL; + mrt->activated_upstream_cnt = 0; + mrt->activated_downstream_cnt = 0; +} + +/* + * mrt_sources_find( table entry, source ) + * Finds an entry in source list for a multicast route. + */ +mrt_src_t *mrt_sources_find(mrt_table_t * mrt, u_int32_t src) +{ + mrt_src_t *curr; + + if ( !mrt ) { + log(LOG_WARNING, 0, __FUNCTION__, + "Attempting to find a source to an unknown route."); + return NULL; + } + + curr = mrt->sources; + + while( curr ) { + if ( curr->src_addr == src ) { + break; + } + + curr = curr->next; + } + + return curr; +} + +/* + * mrt_sources_add( table entry, source ) + * Adds an entry in source list for a multicast route. + */ +void mrt_sources_add(u_int32_t src, u_int32_t dest) +{ + mrt_table_t *mrt; + mrt_src_t *newsrc; + + mrt = mrt_table_find( dest ); + if ( !mrt ) { + log(LOG_WARNING, 0, __FUNCTION__, + "Attempting to add a source to an unknown route."); + return; + } + + newsrc = mrt_sources_find( mrt, src ); + if ( newsrc ) { /* if it's already there, update it? */ + return; + } + + newsrc = (mrt_src_t *) malloc( sizeof( mrt_src_t ) ); + if ( !newsrc ) { + /* if no memory... quit */ + fprintf( stderr, "multicast_routing_table.c: Error allocating source entry.\n" ); + exit( -1 ); + } + + kernel_mrt_add_route( src, dest, 0 ); + + newsrc->src_addr = src; + newsrc->next = mrt->sources; + mrt->sources = newsrc; +} + +/* + * mrt_sources_remove_all( table entry ) + * Destroys every entry in source list for a multicast route. + */ +void mrt_sources_remove_all(mrt_table_t * mrt) +{ + mrt_src_t *curr, *dead; + + curr = mrt->sources; + + while( curr ) { + dead = curr; + curr = curr->next; + + kernel_mrt_del_route( dead->src_addr, mrt->grp_addr, 0 ); + + free( dead ); + } + + /* easier to debug if it's NULL instead of garbage */ + mrt->sources = NULL; +} + +/* + * mrt_origlist_find( table entry, orig ) + * Finds an entry in originator list for a multicast route. + */ +mrt_orig_t *mrt_origlist_find(mrt_table_t * mrt, u_int32_t orig) +{ + mrt_orig_t *curr; + + if ( !mrt ) { + log(LOG_WARNING, 0, __FUNCTION__, + "Attempting to find a source to an unknown route."); + return NULL; + } + + curr = mrt->origlist; + + while( curr ) { + if ( curr->orig_addr == orig ) { + break; + } + + curr = curr->next; + } + + return curr; +} + +/* + * mrt_origlist_add( table entry, orig, seqno, hcnt ) + * Adds an entry in originator list for a multicast route. + */ +mrt_orig_t * mrt_origlist_add(mrt_table_t *mrt, u_int32_t orig ) +{ + mrt_orig_t *neworig; + + if ( !mrt ) { + log(LOG_WARNING, 0, __FUNCTION__, + "Attempting to add a source to an unknown route."); + return NULL; + } + + neworig = mrt_origlist_find( mrt, orig ); + if ( neworig ) { /* if it's already there, update it? */ + return neworig; + } + + neworig = (mrt_orig_t *) malloc( sizeof( mrt_orig_t ) ); + if ( !neworig ) { + fprintf( stderr, "multicast_routing_table.c: Error allocating orig entry.\n" ); + exit( -1 ); + } + + neworig->orig_addr = orig; + neworig->grp_seqno = 0; + neworig->grp_hcnt = 0xff; + neworig->next = mrt->origlist; + neworig->up = mrt; + mrt->origlist = neworig; + + /* do timeout stuff */ + neworig->cleanup_timer.handler = (timeout_func_t) &mrt_origlist_remove; + neworig->cleanup_timer.data = neworig; + timer_set_timeout( &( neworig->cleanup_timer ), RREP_WAIT_TIME ); + + return neworig; +} + +/* + * mrt_origlist_remove( orig entry ) + * For the timeout callback. Removes a single entry in the list. + */ +void mrt_origlist_remove(mrt_orig_t *entry) +{ + mrt_orig_t * curr = NULL, * prev = NULL; + + DEBUG( LOG_DEBUG, 0, "In origlist timeout." ); + + if ( !entry ) { + log(LOG_WARNING, 0, __FUNCTION__, + "Attempting to remove a orig entry that didn't exist."); + return; + } + + timer_remove( &( entry->cleanup_timer ) ); + + if ( !( entry->up ) ) { + log(LOG_WARNING, 0, __FUNCTION__, + "Attempting to remove a orig entry that didn't have a mrt."); + return; + } + + prev = NULL; + curr = entry->up->origlist; + + while( (curr) && (curr != entry) ) { + prev = curr; + curr = curr->next; + } + + if ( prev == NULL ) { + if ( curr == NULL ) { + /* empty list */ + DEBUG( LOG_DEBUG, 0, "Tried to remove from empty list." ); + return; + } else { + /* first element remove */ + DEBUG( LOG_DEBUG, 0, "Removed first element" ); + entry->up->origlist = NULL; + free( entry ); + } + } else { + if ( curr == NULL ) { + /* empty list */ + DEBUG( LOG_DEBUG, 0, "Tried to remove an unknown entry." ); + return; + } else { + /* somewhere in the middle or last element */ + DEBUG( LOG_DEBUG, 0, "Removed middle or last element."); + prev->next = curr->next; + free( entry ); + } + } +} + +/* + * mrt_table_set_leader( route, leader addr, leader hops ) + * Sets the leader and hopcount of a particular route entry (a multicast group). + */ +void mrt_table_set_leader(mrt_table_t * mrt, u_int32_t grp_leader_addr, u_int8_t leader_hcnt) +{ + if ( !mrt ) { + log(LOG_WARNING, 0, __FUNCTION__, + "Attempting to set the leader of a route that doesn't exist."); + return; + } + + mrt->grp_leader_addr = grp_leader_addr; + mrt->leader_hcnt = leader_hcnt; +} + +/* + * mrt_table_set_leader_hcnt( route, leader hops ) + * Sets only the hopcount to the leader. Leader remains the same. + */ +void mrt_table_set_leader_hopcount(mrt_table_t * mrt, u_int8_t leader_hcnt) +{ + if ( !mrt ) { + log(LOG_WARNING, 0, __FUNCTION__, + "Attempting to set the hop count of a route that doesn't exist."); + return; + } + + mrt->leader_hcnt = leader_hcnt; +} + +/* + * mrt_table_set_membership( route, boolean (memeber or not) ) + * Sets our flag true if we're a member of the group to which this is a route. + */ +void mrt_table_set_membership(mrt_table_t * mrt, u_int8_t ismember) +{ + if ( !mrt ) { + log(LOG_WARNING, 0, __FUNCTION__, + "Attempting to set membership of a route that doesn't exist."); + return; + } + + mrt->is_member = ismember; +} + +/* + * mrt_table_dump( ) + * Prints the routing table + */ +void mrt_table_dump(void) +{ + int index; + mrt_table_t * curr; + mrt_nexthop_t * hops; + mrt_orig_t * origs; + FILE *log; + struct timeval now; + struct tm *time; + + log=fopen("mrt_log", "a"); + if(log==NULL){ + perror("mrt_table_dump"); + } + + /* reset timer */ + timer_set_timeout( &( mrt_debug_timer ), 5000 ); + + gettimeofday(&now, NULL); + time = localtime(&now.tv_sec); + + fprintf( log, "\n# Entries: %d Time: %02d:%02d:%02d.%03ld\n", mrt_tbl.num_entries, + time->tm_hour, time->tm_min, time->tm_sec, now.tv_usec / 1000 ); + for ( index = 0; index < MRT_TABLESIZE; index++ ) + { + curr = mrt_tbl.tbl[index]; + while ( curr ) { + fprintf( log, "\t* * * * * * * * * * * * * * *\n" ); + fprintf( log, "\tGroup Addr[%s]\tLeader Addr[%s]\n", + ip_to_str( curr->grp_addr ), + ip_to_str( curr->grp_leader_addr ) ); + fprintf( log, "\tSeq #[%d]\tLeader Hop Count[%d]\n", + curr->grp_seqno, curr->leader_hcnt ); + fprintf( log, "\tMembership[%d]", curr->is_member ); + fprintf( log, "\tRouter[%d]\tLeader[%d]\n", curr->is_router, + curr->am_leader ); + fprintf( log, "\tBroken[%d]\tRepairing[%d]", curr->is_broken, + curr->in_repair ); + fprintf( log, "\tGateway[%d]\n", curr->is_gateway ); + fprintf( log, "\tAct. Up. Count[%d]\tAct. Down. Count[%d]\n", + curr->activated_upstream_cnt, + curr->activated_downstream_cnt ); + fprintf( log, "\tNext Hops\n" ); + hops = curr->nexthops; + while( hops ) { + fprintf( log, "\t\t* * * * * * * *\n\t\tAddr[%s]\n", + ip_to_str( hops->addr ) ); + fprintf( log, "\t\tActivated[%d]\tDirection[%c]\n", + hops->activated, + ( ( hops->direction == MRT_UPSTREAM ) ? ( 'U' ) : ( 'D' ) ) ); + fprintf( log, "\t\tGroup Hopcount[%d]\tGroup Seq#[%d]\n", + hops->grp_hcnt, hops->grp_seqno ); + hops = hops->next; + } + fprintf( log, "\tOriginator List\n" ); + origs = curr->origlist; + while( origs ){ + fprintf( log, "\t\t* * * * * * * *\n\t\tAddr[%s]\n", + ip_to_str( origs->orig_addr ) ); + fprintf( log, "\t\tOrig Hopcount[%d]\tOrig Seq#[%d]\n", + origs->grp_hcnt, origs->grp_seqno ); + origs = origs->next; + } + curr = curr->next; + } + } + + fclose( log ); +} + +void mrt_table_become_leader(mrt_table_t *mrt){ + int i=0; + /* CHECK: better way to select interface */ + /* set first enabled interface's ip as the group leader ip */ + for(i=0; igrp_leader_addr=this_host.devs[i].ipaddr; + } + } + if(!mrt->is_gateway) { + mrt->is_member=1; + } + mrt->am_leader = 1; /* wahoo i'm now the REAL leader */ + mrt->grp_seqno=0; + mrt->leader_hcnt=0; + mrt->grph_update_cnt=1; + + /* mrt->is_router=1; */ + mrt_table_start_routing(mrt); + + /* send a hello */ + grph_send_callback(mrt); +} + +mrt_nexthop_t *mrt_table_get_best_upstream(mrt_table_t *mrt){ + mrt_nexthop_t *nexthop, *besthop=NULL; + + nexthop=mrt->nexthops; + + while(nexthop!=NULL) { + /* Before qualifying to be a upstream best hop, the next + hop must first, in fact be upstream. + - if that is true, then the current nexthop will take the + besthop position if either: + - there is not current besthop + - sequence number is greater than curr besthop + - seq no are equal, but we have a lesser hop count + */ + if(nexthop->direction == MRT_UPSTREAM && + (besthop == NULL || + (nexthop->grp_seqno > besthop->grp_seqno || + (nexthop->grp_seqno == besthop->grp_seqno && + nexthop->grp_hcnt < besthop->grp_hcnt) ) ) ) { + besthop=nexthop; + } + nexthop=nexthop->next; + } + + return besthop; +} + +mrt_nexthop_t *mrt_nexthop_find(mrt_table_t *mrt, uint32_t addr){ + mrt_nexthop_t *nexthop; + + nexthop=mrt->nexthops; + + while(nexthop!=NULL && nexthop->addr!=addr) { + nexthop=nexthop->next; + } + + return nexthop; +} + +void mrt_table_start_routing(mrt_table_t *mrt){ + FILE *nh_log; + + mrt->is_router=1; + + nh_log=fopen("nh_log", "a"); + fprintf(nh_log, "JOIN: %x\n", mrt->grp_addr); + fclose(nh_log); + + if(this_host.gateway_mode) { + /* If in gateway mode, notify multicast router */ + mrt->is_gateway = 1; + igmp_sendreply(mrt, dev_indices[0]); + } +} + +void mrt_table_stop_routing(mrt_table_t *mrt){ + FILE *nh_log; + + mrt->is_router=0; + + nh_log=fopen("nh_log", "a"); + fprintf(nh_log, "LEAVE: %x\n", mrt->grp_addr); + fclose(nh_log); +} + +#endif /* MAODV */ diff -urNb aodv-uu-0.7.2/multicast_routing_table.h maodv-umd-0.7.2/multicast_routing_table.h --- aodv-uu-0.7.2/multicast_routing_table.h Wed Dec 31 19:00:00 1969 +++ maodv-umd-0.7.2/multicast_routing_table.h Wed Jun 25 17:46:10 2003 @@ -0,0 +1,153 @@ +/***************************************************************************** + * + * Copyright (C) 2003 CSHCN, University of Maryland. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Authors: Dionysus Blazakis + * Jonathan Polley + * Dan Rusk + * Manish Karir + * Jonathan McGee + * + *****************************************************************************/ + +#ifndef MULTICAST_ROUTING_TABLE_H +#define MULTICAST_ROUTING_TABLE_H + +#ifndef NS_NO_GLOBALS +#include "defs.h" + +typedef struct mrt_table mrt_table_t; + +#define MRT_UPSTREAM 1 +#define MRT_DOWNSTREAM 2 + +/* struct for next hops */ +typedef struct _mrt_nexthop_t { + u_int32_t addr; + u_int8_t activated; + u_int8_t direction; + u_int8_t grp_hcnt; /* only for use with upstream hops */ + u_int32_t grp_seqno; /* only for use with upstream hops */ + struct _mrt_nexthop_t *next; +} mrt_nexthop_t; + +typedef struct _mrt_src_t { + u_int32_t src_addr; + struct _mrt_src_t *next; +} mrt_src_t; + +typedef struct _mrt_orig_t { + u_int32_t orig_addr; + u_int32_t grp_seqno; + u_int8_t grp_hcnt; + struct timer cleanup_timer; + + mrt_table_t * up; + struct _mrt_orig_t * next; +} mrt_orig_t; + +/* Route table entries */ +struct mrt_table { + u_int32_t grp_addr; + u_int32_t grp_leader_addr; + u_int32_t grp_seqno; + u_int8_t am_leader; /* are we the group leader? */ + + unsigned int ifindex; + u_int8_t leader_hcnt; + u_int8_t is_member; + u_int8_t is_router; + u_int8_t is_broken; + u_int8_t in_repair; + u_int8_t is_gateway; + + struct timer mrt_timer; + struct timer grph_timer; + struct timer mact_timer; /* send mact to our upstream */ + struct timer prune_timer; + + mrt_nexthop_t *nexthops; + u_int8_t activated_upstream_cnt; + u_int16_t activated_downstream_cnt; + + mrt_src_t * sources; + mrt_orig_t * origlist; + + char grph_update_cnt; /* for if the next grph is to be an update */ + + struct mrt_table *next; +}; + + +#define MRT_TABLESIZE 64 /* Must be a power of 2 */ +#define MRT_TABLEMASK (MRT_TABLESIZE - 1) + +struct multicast_routing_table { + unsigned int num_entries; + mrt_table_t *tbl[MRT_TABLESIZE]; +}; + +#endif /* NS_NO_GLOBALS */ + +#ifndef NS_NO_DECLARATIONS + +extern struct multicast_routing_table mrt_tbl; + +void mrt_table_init(); +void mrt_table_destroy(); +mrt_table_t *mrt_table_insert(u_int32_t grp_addr, u_int32_t grp_leader_addr, + u_int32_t grp_seqno, + unsigned int ifindex, + u_int8_t leader_hcnt, + u_int8_t is_member); + +NS_INLINE mrt_table_t *mrt_table_update_timeout(mrt_table_t * mrt, + u_int32_t lifetime); +mrt_table_t *mrt_table_find(u_int32_t grp_addr); +void mrt_table_delete(u_int32_t grp_addr); +mrt_nexthop_t *mrt_table_get_activated_upstream(mrt_table_t * mrt); +mrt_nexthop_t *mrt_table_get_best_upstream(mrt_table_t *mrt); + +mrt_nexthop_t *mrt_nexthop_add(mrt_table_t * mrt, u_int32_t addr, + u_int8_t direction, u_int32_t grp_seqno); +void mrt_nexthop_remove(mrt_table_t * mrt, u_int32_t addr ); +void mrt_nexthop_activate(mrt_table_t * mrt, u_int32_t addr); +void mrt_nexthop_deactivate(mrt_table_t * mrt, u_int32_t addr); +void mrt_nexthop_remove_all(mrt_table_t * mrt); +mrt_nexthop_t *mrt_nexthop_find(mrt_table_t *mrt, uint32_t addr); + +mrt_src_t *mrt_sources_find(mrt_table_t * mrt, u_int32_t src); +void mrt_sources_add(u_int32_t src, u_int32_t dest); +void mrt_sources_remove_all(mrt_table_t * mrt); + +mrt_orig_t * mrt_origlist_find(mrt_table_t *mrt, u_int32_t orig); +mrt_orig_t * mrt_origlist_add(mrt_table_t *mrt, u_int32_t orig); +void mrt_origlist_remove(mrt_orig_t *entry); + +void mrt_table_set_leader(mrt_table_t * mrt, u_int32_t grp_leader_addr, u_int8_t leader_hcnt); +void mrt_table_set_leader_hopcount(mrt_table_t * mrt, u_int8_t leader_hcnt); +void mrt_table_become_leader(mrt_table_t *mrt); + +void mrt_table_set_membership(mrt_table_t * mrt, u_int8_t ismember); +void mrt_table_start_routing(mrt_table_t *mrt); +void mrt_table_stop_routing(mrt_table_t *mrt); + +void mrt_table_dump(void); + +#endif /* NS_NO_DECLARATIONS */ + +#endif /* MULTICAST_ROUTING_TABLE_H */ diff -urNb aodv-uu-0.7.2/packet_input.c maodv-umd-0.7.2/packet_input.c --- aodv-uu-0.7.2/packet_input.c Mon Jun 2 19:20:10 2003 +++ maodv-umd-0.7.2/packet_input.c Fri Dec 5 17:42:32 2003 @@ -29,6 +29,18 @@ #include #include +/* SOCK_RAW refuses to cooperate... */ +#include +#include /* for the glibc version number */ +#if __GLIBC__ >= 2 && __GLIBC_MINOR >= 1 +#include +#include /* the L2 protocols */ +#else +#include +#include +#include /* The L2 protocols */ +#endif + #include "defs.h" #include "debug.h" #include "routing_table.h" @@ -44,6 +56,12 @@ #include "packet_queue.h" #include "packet_input.h" +#ifdef MAODV +#include "igmp.h" +#include "multicast_routing_table.h" +#include "multicast_packet_cache.h" +#endif + #define BUFSIZE 2048 extern int internet_gw_mode, wait_on_reboot, optimized_hellos, llfeedback; @@ -58,6 +76,24 @@ /* Set this if you want lots of debug printouts: */ /* #define DEBUG_PACKET */ +/* from + "Internetworking with TCP/IP: Volume II" + Second Edition + Douglas E. Comer, David L. Stevens */ +static u_int16_t my_ip_csum( unsigned short *buf, int nshorts ) +{ + u_int32_t sum; + + for( sum = 0; nshorts > 0; nshorts-- ) { + sum += *buf++; + } + + sum = ( sum >> 16 ) + ( sum & 0xffff ); + sum += (sum >> 16 ); + + return ~sum; +} + #ifndef NS_PORT static void die(struct ipq_handle *h) { @@ -104,11 +140,26 @@ static void packet_input(int fd) #endif { - rt_table_t *fwd_rt, *rev_rt, *next_hop_rt, *expired_rt = NULL; + rt_table_t *fwd_rt = NULL, *rev_rt, *next_hop_rt, *expired_rt = NULL; u_int32_t dest_addr, src_addr; u_int8_t rreq_flags = 0; unsigned int ifindex; struct ip_data *ipd = NULL; +#ifdef MAODV + /* This is to "hack" around the Linux UDP ip->id field which + remains zero unless you fragment a IP packet. Not likely. + + We just change the ip->id for each packet leaving + destined for a multicast address. There is really no + other way to work this in Linux. The source code states + that Linux was never intened to have a router + host for + multicast IP. + + The ip-id is needed to cache multicast packets to avoid + flooding a multicast packet around the network for ttl + hops. */ + static u_int16_t staticid = 0; +#endif #ifdef NS_PORT ifindex = NS_IFINDEX; // Always use ns interface @@ -164,10 +215,20 @@ if (pkt->hook == 0) dev_name = pkt->indev_name; - else if (pkt->hook == 3) + else if ((pkt->hook == 3) || (pkt->hook == 4)) dev_name = pkt->outdev_name; - else + else { dev_name = NULL; + } + + if (dev_name) { + ifindex = name2index(dev_name); + if (ifindex < 0) { + DEBUG(LOG_ERR, 0, "name2index error!"); + ifindex = 0; + } + } else + ifindex = 0; /* We know from kaodv.c that this is an IP packet */ ip = (struct iphdr *) pkt->payload; @@ -200,28 +261,30 @@ #endif break; +#ifdef MAODV + case IPPROTO_IGMP: + if(pkt->hook == 3) { + igmp_process((IGMP*)((char*)ip + (ip->ihl << 2)), ifindex); + + /* drop the packet after processing */ + status = ipq_set_verdict(h, pkt->packet_id, NF_DROP, 0, NULL); + if(status < 0) + die(h); + return; + } + break; +#endif } #ifdef DEBUG_PACKET DEBUG(LOG_INFO, 0, "pkt to %s", ip_to_str(dest_addr)); #endif - if (dev_name) { - ifindex = name2index(dev_name); - if (ifindex < 0) { - DEBUG(LOG_ERR, 0, "name2index error!"); - return; - } - } else - ifindex = 0; #endif /* NS_PORT */ /* If the packet is not interesting we just let it go through... */ if (dest_addr == AODV_BROADCAST || - dest_addr == DEV_IFINDEX(ifindex).broadcast || - ((internet_gw_mode && this_host.gateway_mode) - && ((dest_addr & DEV_IFINDEX(ifindex).netmask) != - DEV_IFINDEX(ifindex).broadcast))) { + dest_addr == DEV_IFINDEX(ifindex).broadcast) { #ifdef NS_PORT sendPacket(p, 0, 0.0); #else @@ -230,8 +293,14 @@ } /* Find the entry of the neighboring node and the destination (if any). */ - rev_rt = rt_table_find(src_addr); fwd_rt = rt_table_find(dest_addr); + /* If captured because of gateway mode, do not try to construct a + * reverse route. */ + if((pkt->mark == 4) && (pkt->hook == 0)) { + rev_rt = NULL; + } else { + rev_rt = rt_table_find(src_addr); + } /* UPDATE TIMERS on active forward and reverse routes... */ @@ -263,6 +332,155 @@ rt_table_update_timeout(next_hop_rt, ACTIVE_ROUTE_TIMEOUT); } +#ifdef MAODV + if(IN_MULTICAST(dest_addr)){ + u_int8_t *pay; + u_int32_t size; + mrt_table_t *mrt=mrt_table_find(dest_addr); + + if(mrt==NULL || (!mrt->is_router && DEV_IFINDEX(ifindex).ipaddr!=src_addr)){ + /* we got a packet for which we have no entry */ + status = ipq_set_verdict(h, pkt->packet_id, NF_DROP, 0, NULL); + if (status < 0) + die(h); + return; + } + /* note: this is like an else... note the return */ + + if ( (pkt->mark == 4) || this_host.gateway_mode) { + /* Gateway mode relays packets itself since it can't control the + * multicast routing tables. */ + if((!this_host.gateway_mode + && src_addr == DEV_IFINDEX(ifindex).ipaddr) + || (ip->id == 0)) { + /* from our LOCAL_OUT hook. let's change the ip->id field */ + staticid++; + ip->id = htons(staticid); + + /* now recalculate the chksum... wahoo! */ + /* CHECK: this could be more intelligent... */ + ip->check = 0; + ip->check = my_ip_csum( (unsigned short *) ip, ip->ihl * 2 ); + } + } + + if(!mrt->is_router || mrt->is_broken ){ + /* we have an invalid route, do discovery. */ + size = pkt->data_len; + pay = (u_int8_t *) malloc( pkt->data_len ); + if ( pay == NULL ) { + perror( "in packet_input for multicast local out buffer." ); + exit( -1 ); + } + memcpy( pay, pkt->payload, size ); + + rreq_flags = rreq_flags | RREQ_JOIN; + mcast_packet_queue_add(pkt->packet_id, dest_addr, size, pay); + + check_duplicate( src_addr, ip->id, pkt->hook ); + + goto mcast_route_discovery; + + }else{ + /* route is valid, packet wants out, send the packet along its + * way */ + if ( !check_duplicate( src_addr, ip->id, pkt->hook ) ) { + status = ipq_set_verdict(h, pkt->packet_id, NF_DROP, 0, NULL); + if (status < 0) + die(h); + return; + } else { + mrt_sources_add( src_addr, dest_addr ); + mrt_table_update_timeout(mrt, ACTIVE_ROUTE_TIMEOUT); + + /* In gateway mode, we need to duplicate the packet ourselves + * since OSPF is handling the route table and we can't ask it + * to duplicate on this interface. */ + if(this_host.gateway_mode && (pkt->hook == 0) && (ip->ttl > 1) + && (src_addr != DEV_IFINDEX(ifindex).ipaddr)) { + /* The injection of raw ip packets when a multicast route + * exists for the destination appears broken. This is a + * workaround until a better solution can be found. */ +#if 1 + int sock = socket(PF_PACKET, SOCK_DGRAM, htonl(ETH_P_IP)); + struct sockaddr_ll sll; + + /* Decrement TTL, since the raw socket will recalculate + * the IP checksum, don't worry about it */ + ip->ttl--; + ip->check = 0; + ip->check = my_ip_csum((unsigned short *) ip, ip->ihl * 2); + + /* Repeat packet */ + memset(&sll, 0, sizeof(sll)); + sll.sll_family = AF_PACKET; + sll.sll_addr[0] = 1; + sll.sll_addr[1] = 0; + sll.sll_addr[2] = 0x5E; + sll.sll_addr[3] = (dest_addr >> 16) & 0x7F; + sll.sll_addr[4] = (dest_addr >> 8) & 0xFF; + sll.sll_addr[5] = (dest_addr & 0xFF); + sll.sll_halen = 6; + sll.sll_ifindex = ifindex; + sll.sll_protocol = htons(ETH_P_IP); + if(sendto(sock, pkt->payload, pkt->data_len, 0, + (struct sockaddr*)&sll, sizeof(sll)) < 0) { + printf("ifindex = %d, devname = %s\n", ifindex, dev_name); + perror("send_raw"); + } + + /* Reincrement the checksum so we don't have a bad + * checksum or drop the packet. */ + ip->ttl++; + ip->check = 0; + ip->check = my_ip_csum((unsigned short *) ip, ip->ihl * 2); + close(sock); +#else /* #if 0 */ + /* This was an attempt at using the raw IP facilities to + * repeat the IP packets. Somewhere in the Linux IP + * stack it was improperly clobbering the source IP. This + * only occured when a route for the multicast group + * appeared in the multicast routing table. */ + int sock = socket(PF_INET, SOCK_RAW, IPPROTO_RAW); + struct sockaddr_in sin; + int flag; + + /* Decrement TTL, since the raw socket will recalculate + * the IP checksum, don't worry about it */ + ip->ttl--; + flag = -1; + setsockopt(sock, SOL_IP, IP_HDRINCL, &flag, sizeof(flag)); + /* Repeat packet */ + memset(&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_port = ip->protocol; + sin.sin_addr.s_addr = htonl(src_addr); + if(sendto(sock, pkt->payload, pkt->data_len, MSG_DONTROUTE, + (struct sockaddr*)&sin, sizeof(sin)) < 0) { + perror("send_raw"); + } + + /* Reincrement the checksum so we don't have a bad + * checksum or drop the packet. */ + ip->ttl++; + close(sock); +#endif /* #if 0 */ + } + + status = ipq_set_verdict( h, pkt->packet_id, NF_ACCEPT, + pkt->data_len, pkt->payload); + if(status < 0) + die(h); + + /* we did our own accept! */ + /* goto accept; */ + return; + } + /***** never gets here... look above ****/ + } + } +#endif + /* OK, the timeouts have been updated. Now see if either: 1. The packet is for this node -> ACCEPT. 2. The packet is not for this node -> Send RERR (someone want's this node to forward packets @@ -271,6 +489,13 @@ /* If the packet is destined for this node, then just accept it. */ if (dest_addr == DEV_IFINDEX(ifindex).ipaddr) goto accept; + /* If in gateway mode and packet is headed to a different subnet, see + * if we have a wired route for it */ + if (this_host.gateway_mode && ((dest_addr & DEV_IFINDEX(ifindex).netmask) + != (DEV_IFINDEX(ifindex).ipaddr & DEV_IFINDEX(ifindex).netmask))) { + if(get_route_metric(htonl(dest_addr)) != -1) + goto accept; + } if (!fwd_rt || fwd_rt->state == INVALID || (fwd_rt->hcnt == 1 && (fwd_rt->flags & RT_UNIDIR))) { @@ -290,10 +515,10 @@ #else #define PACKET_IS_INBOUND pkt->hook == 0 #endif - if (PACKET_IS_INBOUND) { - + if (PACKET_IS_INBOUND && (pkt->mark != 4)) { u_int32_t rerr_dest; RERR *rerr; + #ifdef NS_PORT DEBUG(LOG_DEBUG, 0, "No route, src=%s dest=%s prev_hop=%s - DROPPING!", @@ -347,6 +572,10 @@ #else packet_queue_add(pkt->packet_id, dest_addr); +#ifdef MAODV + mcast_route_discovery: +#endif /* MAODV */ + /* Already seeking the destination? Then do not allocate any memory or generate a RREQ. */ if (seek_list_find(dest_addr)) @@ -370,7 +599,7 @@ if (fwd_rt && (fwd_rt->flags & RT_REPAIR)) rreq_local_repair(expired_rt, src_addr, ipd); else - rreq_route_discovery(dest_addr, rreq_flags, ipd); + rreq_route_discovery(dest_addr, rreq_flags, ipd, 0); return; diff -urNb aodv-uu-0.7.2/packet_queue.c maodv-umd-0.7.2/packet_queue.c --- aodv-uu-0.7.2/packet_queue.c Tue May 27 10:41:15 2003 +++ maodv-umd-0.7.2/packet_queue.c Wed Jun 25 17:46:10 2003 @@ -34,6 +34,10 @@ #include "timer_queue.h" #include "aodv_timeout.h" +#ifdef MAODV +#include "multicast_routing_table.h" +#endif + extern struct ipq_handle *h; #endif @@ -69,6 +73,9 @@ #else ipq_set_verdict(h, qp->id, NF_DROP, 0, NULL); #endif /* NS_PORT */ + if(qp->payload != NULL) { + free(qp->payload); + } free(qp); count++; } @@ -96,6 +103,9 @@ ipq_set_verdict(h, qp->id, NF_DROP, 0, NULL); #endif /* NS_PORT */ + if(qp->payload) { + free(qp->payload); + } free(qp); count++; PQ.len--; @@ -108,6 +118,7 @@ return count; } + /* Buffer a packet in a FIFO queue. Implemented as a linked list, where we add elements at the end and remove at the beginning.... */ @@ -153,6 +164,9 @@ #endif qp->dest_addr = dest_addr; + qp->payload = NULL; + qp->size = 0; + gettimeofday(&qp->q_time, NULL); list_add_tail(&PQ.head, &qp->l); @@ -168,6 +182,43 @@ #endif } +void mcast_packet_queue_add(unsigned long id, u_int32_t dest_addr, + u_int32_t s, u_int8_t *pay) +{ + struct q_pkt *qp; + + if (PQ.len >= MAX_QUEUE_LENGTH) { + DEBUG(LOG_DEBUG, 0, "MAX Queue length reached. Removing first pkt in queue"); + if(!list_empty(&PQ.head)) { + qp = (struct q_pkt *)PQ.head.next; + + list_detach(PQ.head.next); + ipq_set_verdict(h, qp->id, NF_DROP, 0, NULL); + PQ.len--; + if ( qp->payload ) + free( qp->payload ); + free(qp); + } + } + + if ((qp = (struct q_pkt *) malloc(sizeof(struct q_pkt))) == NULL) { + fprintf(stderr, "Malloc failed!\n"); + exit(-1); + } + + qp->id = id; + qp->dest_addr = dest_addr; + + qp->payload = pay; + qp->size = s; + + gettimeofday(&qp->q_time, NULL); + list_add_tail(&PQ.head, &qp->l); + + PQ.len++; +} + + int NS_CLASS packet_queue_drop(u_int32_t dest_addr) { int count = 0; @@ -183,6 +234,9 @@ #else ipq_set_verdict(h, qp->id, NF_DROP, 0, NULL); #endif + if(qp->payload != NULL) { + free(qp->payload); + } free(qp); count++; PQ.len--; @@ -226,7 +280,9 @@ #else ipq_set_verdict(h, qp->id, NF_ACCEPT, 0, NULL); #endif /* NS_PORT */ - + if(qp->payload) { + DEBUG(LOG_DEBUG, 0, "Sent a multicast queued packet from wrong function."); + } free(qp); count++; PQ.len--; @@ -249,3 +305,59 @@ return count; } + +#ifdef MAODV + +int NS_CLASS mcast_packet_queue_send(u_int32_t dest_addr) +{ + int count = 0; + list_t *pos, *tmp; + mrt_table_t *mrt; +#ifdef NS_PORT + double delay = 0; +#define ARP_DELAY 0.005 +#endif + + mrt = mrt_table_find(dest_addr); + + if (!mrt || !mrt->is_router ) + return -1; + + list_foreach_safe(pos, tmp, &PQ.head) { + struct q_pkt *qp = (struct q_pkt*)pos; + + if (qp->dest_addr == dest_addr) { + list_detach(pos); + ipq_set_verdict(h, qp->id, NF_ACCEPT, qp->size, + qp->payload); + + if ( qp->payload ) { + free( qp->payload ); + } + free(qp); + count++; + PQ.len--; + } + } + + /* Update rt timeouts */ + if (dest_addr != DEV_IFINDEX(mrt->ifindex).ipaddr) { + /* TODO: CHECK: Update multicast route table timer. */ + /* rt_table_update_timeout(rt, ACTIVE_ROUTE_TIMEOUT); */ + + /* + next_hop_rt = rt_table_find(rt->next_hop); + + if (next_hop_rt && next_hop_rt->state == VALID && + next_hop_rt->dest_addr != rt->dest_addr) + rt_table_update_timeout(next_hop_rt, ACTIVE_ROUTE_TIMEOUT); + */ + } + + DEBUG(LOG_INFO, 0, "SENT %d packets to %s qlen=%u", + count, ip_to_str(dest_addr), PQ.len); + + return count; +} + +#endif /* MAODV */ diff -urNb aodv-uu-0.7.2/packet_queue.h maodv-umd-0.7.2/packet_queue.h --- aodv-uu-0.7.2/packet_queue.h Thu May 22 19:11:35 2003 +++ maodv-umd-0.7.2/packet_queue.h Thu Jul 17 18:03:51 2003 @@ -26,7 +26,7 @@ #include "defs.h" #include "list.h" -#define MAX_QUEUE_LENGTH 100 +#define MAX_QUEUE_LENGTH 20 #define MAX_QUEUE_TIME 10000 /* Maximum time packets can be queued (ms) */ #define GARBAGE_COLLECT_TIME 1000 /* Interval between running the * garbage collector (ms) */ @@ -40,6 +40,8 @@ #else unsigned long id; #endif + u_int8_t * payload; + u_int32_t size; }; struct packet_queue { @@ -58,6 +60,11 @@ #else void packet_queue_add(unsigned long id, u_int32_t dest_addr); #endif + +int mcast_packet_queue_send(u_int32_t dest_addr); +void mcast_packet_queue_add(unsigned long id, u_int32_t dest_addr, + u_int32_t s, u_int8_t *pay); + void packet_queue_init(); void packet_queue_destroy(); int packet_queue_drop(u_int32_t dest_addr); diff -urNb aodv-uu-0.7.2/params.h maodv-umd-0.7.2/params.h --- aodv-uu-0.7.2/params.h Mon Nov 11 11:57:21 2002 +++ maodv-umd-0.7.2/params.h Wed Jun 25 17:46:10 2003 @@ -33,12 +33,12 @@ #define DELETE_PERIOD ACTIVE_ROUTE_TIMEOUT #else /* HELLO messages are used: */ -#define ACTIVE_ROUTE_TIMEOUT 3000 +#define ACTIVE_ROUTE_TIMEOUT 3500 #define DELETE_PERIOD K * max(ACTIVE_ROUTE_TIMEOUT, ALLOWED_HELLO_LOSS * HELLO_INTERVAL) #define TTL_START 2 #endif -#define ALLOWED_HELLO_LOSS 2 +#define ALLOWED_HELLO_LOSS 3 /* If expanding ring search is used, BLACKLIST_TIMEOUT should be?: */ #define BLACKLIST_TIMEOUT RREQ_RETRIES * NET_TRAVERSAL_TIME + (TTL_THRESHOLD - TTL_START)/TTL_INCREMENT + 1 + RREQ_RETRIES #define HELLO_INTERVAL 1000 @@ -57,5 +57,10 @@ #define TIMEOUT_BUFFER 2 #define TTL_INCREMENT 2 #define TTL_THRESHOLD 7 + +/* MAODV params */ +#define GROUP_HELLO_INTERVAL 5000 +#define RREP_WAIT_TIME 10000 +#define PRUNE_TIMEOUT 2 * RREP_WAIT_TIME #endif diff -urNb aodv-uu-0.7.2/routing_table.c maodv-umd-0.7.2/routing_table.c --- aodv-uu-0.7.2/routing_table.c Tue May 27 12:32:58 2003 +++ maodv-umd-0.7.2/routing_table.c Wed Jun 25 17:46:10 2003 @@ -39,6 +39,8 @@ #include "seek_list.h" #endif /* NS_PORT */ +#include + static unsigned int hashing(u_int32_t * addr, hash_value * hash); #ifndef NS_PORT @@ -156,6 +158,8 @@ rt_tbl.num_entries++; + /* trying to track weird route bug */ + assert(!(dest_addr == DEV_NR(0).ipaddr == next)); DEBUG(LOG_INFO, 0, "Inserting %s (bucket %d) next hop %s", ip_to_str(dest_addr), index, ip_to_str(next)); diff -urNb aodv-uu-0.7.2/seek_list.c maodv-umd-0.7.2/seek_list.c --- aodv-uu-0.7.2/seek_list.c Thu May 22 19:11:35 2003 +++ maodv-umd-0.7.2/seek_list.c Wed Jun 25 17:46:10 2003 @@ -47,7 +47,9 @@ seek_list_t *NS_CLASS seek_list_insert(u_int32_t dest_addr, u_int32_t dest_seqno, int ttl, u_int8_t flags, - struct ip_data *ipd) + struct ip_data *ipd, + u_int16_t grp_hcnt, + u_int32_t grp_addr ) { seek_list_t *entry; @@ -62,6 +64,8 @@ entry->reqs = 0; entry->ttl = ttl; entry->ipd = ipd; + entry->grp_hcnt = grp_hcnt; + entry->grp_addr = grp_addr; entry->seek_timer.handler = &NS_CLASS route_discovery_timeout; entry->seek_timer.data = entry; @@ -72,6 +76,32 @@ return entry; } +#ifdef MAODV +int NS_CLASS seek_list_remove_mcast(u_int32_t dest_addr, u_int32_t grp_addr) +{ + list_t *pos; + + list_foreach(pos, &seekhead) { + seek_list_t *entry = (seek_list_t *)pos; + + if ((entry->dest_addr == dest_addr) && (entry->grp_addr == grp_addr)) { + list_detach(&entry->l); + + /* Make sure any timers are removed */ + timer_remove(&entry->seek_timer); + + if (entry->ipd) + free(entry->ipd); + + free(entry); + return 1; + } + } + + return 0; +} +#endif + int NS_CLASS seek_list_remove(seek_list_t *entry) { if (!entry) @@ -101,6 +131,27 @@ } return NULL; } + +#ifdef MAODV +/* note: This function call seems misleading at first because + most of the time a multicast RREQ should be destined for + a group, but tree merge is destined for the leader and contains + the group information in an extension. */ +seek_list_t *NS_CLASS seek_list_find_mcast(u_int32_t dest_addr, + u_int32_t grp_addr) +{ + list_t *pos; + + list_foreach(pos, &seekhead) { + seek_list_t *entry = (seek_list_t *)pos; + + if ((entry->dest_addr == dest_addr) && (entry->grp_addr == grp_addr)) { + return entry; + } + } + return NULL; +} +#endif #ifdef SEEK_LIST_DEBUG void NS_CLASS seek_list_print() diff -urNb aodv-uu-0.7.2/seek_list.h maodv-umd-0.7.2/seek_list.h --- aodv-uu-0.7.2/seek_list.h Thu May 22 19:11:35 2003 +++ maodv-umd-0.7.2/seek_list.h Wed Jun 25 17:46:10 2003 @@ -44,15 +44,25 @@ u_int8_t flags; /* The flags we are using for resending the RREQ */ int reqs; int ttl; + u_int16_t grp_hcnt; + u_int32_t grp_addr; struct timer seek_timer; } seek_list_t; #endif /* NS_NO_GLOBALS */ #ifndef NS_NO_DECLARATIONS seek_list_t *seek_list_insert(u_int32_t dest_addr, u_int32_t dest_seqno, - int ttl, u_int8_t flags, struct ip_data *ipd); + int ttl, u_int8_t flags, struct ip_data *ipd, + u_int16_t grp_hcnt, u_int32_t grp_addr); int seek_list_remove(seek_list_t *entry); seek_list_t *seek_list_find(u_int32_t dest_addr); + +#ifdef MAODV +seek_list_t *seek_list_find_mcast(u_int32_t dest_addr, + u_int32_t grp_addr); +int NS_CLASS seek_list_remove_mcast(u_int32_t dest_addr, + u_int32_t grp_addr); +#endif #ifdef NS_PORT #ifdef SEEK_LIST_DEBUG