diff --new-file --recursive --context=3 --minimal -x '*.[ao]' -x '*.nam' -x '*.tr' -x '*.cache' -x core -x '*.core' ns-2.27-ORIG/common/packet.cc ns-2.27/common/packet.cc
*** ns-2.27-ORIG/common/packet.cc	2005-03-11 11:38:20.000000000 +0100
--- ns-2.27/common/packet.cc	2005-03-11 11:39:19.000000000 +0100
***************
*** 52,57 ****
--- 52,58 ----
  PacketHeaderClass::PacketHeaderClass(const char* classname, int hdrlen) : 
  	TclClass(classname), hdrlen_(hdrlen), offset_(0)
  {
+ 
  }
  
  
diff --new-file --recursive --context=3 --minimal -x '*.[ao]' -x '*.nam' -x '*.tr' -x '*.cache' -x core -x '*.core' ns-2.27-ORIG/common/packet.h ns-2.27/common/packet.h
*** ns-2.27-ORIG/common/packet.h	2005-03-11 11:38:20.000000000 +0100
--- ns-2.27/common/packet.h	2005-03-11 11:39:19.000000000 +0100
***************
*** 161,166 ****
--- 161,170 ----
  	PT_SMAC,
  
  	// insert new packet types here
+ 	
+ 	// OLSR packet type
+ 	PT_OLSR,
+ 	
  	PT_NTYPE // This MUST be the LAST one
  };
  
***************
*** 250,255 ****
--- 254,262 ----
  		// smac
  		name_[PT_SMAC]="smac";
  
+ 		// OLSR
+ 		name_[PT_OLSR]="OLSR";
+ 
  		name_[PT_NTYPE]= "undefined";
  	}
  	const char* name(packet_t p) const { 
diff --new-file --recursive --context=3 --minimal -x '*.[ao]' -x '*.nam' -x '*.tr' -x '*.cache' -x core -x '*.core' ns-2.27-ORIG/Makefile ns-2.27/Makefile
*** ns-2.27-ORIG/Makefile	2005-03-11 11:38:20.000000000 +0100
--- ns-2.27/Makefile	2005-03-11 11:39:10.000000000 +0100
***************
*** 248,253 ****
--- 248,254 ----
  	dsr/simplecache.o dsr/sr_forwarder.o \
  	aodv/aodv_logs.o aodv/aodv.o \
  	aodv/aodv_rtable.o aodv/aodv_rqueue.o \
+ 	olsr/OLSR.o olsr/OLSR_state.o olsr/OLSR_rtable.o olsr/OLSR_printer.o \
  	common/ns-process.o \
  	satellite/satgeometry.o satellite/sathandoff.o \
  	satellite/satlink.o satellite/satnode.o \
diff --new-file --recursive --context=3 --minimal -x '*.[ao]' -x '*.nam' -x '*.tr' -x '*.cache' -x core -x '*.core' ns-2.27-ORIG/olsr/OLSR.cc ns-2.27/olsr/OLSR.cc
*** ns-2.27-ORIG/olsr/OLSR.cc	1970-01-01 01:00:00.000000000 +0100
--- ns-2.27/olsr/OLSR.cc	2005-03-11 11:38:59.000000000 +0100
***************
*** 0 ****
--- 1,2065 ----
+ /***************************************************************************
+  *   Copyright (C) 2004 by Francisco J. Ros                                *
+  *   fjrm@dif.um.es                                                        *
+  *                                                                         *
+  *   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.             *
+  ***************************************************************************/
+ 
+ ///
+ /// \file	OLSR.cc
+ /// \brief	Implementation of OLSR agent and related classes.
+ ///
+ /// This is the main file of this software because %OLSR's behaviour is
+ /// implemented here.
+ ///
+ 
+ #include <olsr/OLSR.h>
+ #include <olsr/OLSR_pkt.h>
+ #include <olsr/OLSR_printer.h>
+ #include <math.h>
+ #include <limits.h>
+ #include <address.h>
+ #include <ip.h>
+ #include <cmu-trace.h>
+ #include <map>
+ 
+ /// Length (in bytes) of UDP header.
+ #define UDP_HDR_LEN	8
+ 
+ ///
+ /// \brief Function called by MAC layer when cannot deliver a packet.
+ ///
+ /// \param p Packet which couldn't be delivered.
+ /// \param arg OLSR agent passed for a callback.
+ ///
+ static void
+ olsr_mac_failed_callback(Packet *p, void *arg) {
+   ((OLSR*)arg)->mac_failed(p);
+ }
+ 
+ 
+ /********** TCL Hooks **********/
+ 
+ 
+ int OLSR_pkt::offset_;
+ static class OLSRHeaderClass : public PacketHeaderClass {
+ public:
+ 	OLSRHeaderClass() : PacketHeaderClass("PacketHeader/OLSR", sizeof(OLSR_pkt)) {
+ 		bind_offset(&OLSR_pkt::offset_);
+ 	}
+ } class_rtProtoOLSR_hdr;
+ 
+ static class OLSRClass : public TclClass {
+ public:
+ 	OLSRClass() : TclClass("Agent/OLSR") {}
+ 	TclObject* create(int argc, const char*const* argv) {
+ 		// argv has the following structure:
+ 		// <tcl-object> <tcl-object> Agent/OLSR create-shadow <id>
+ 		// e.g: _o17 _o17 Agent/OLSR create-shadow 0
+ 		// argv[4] is the address of the node
+ 		assert(argc == 5);
+ 		return new OLSR((nsaddr_t)Address::instance().str2addr(argv[4]));
+ 	}
+ } class_rtProtoOLSR;
+ 
+ ///
+ /// \brief Interface with TCL interpreter.
+ ///
+ /// From your TCL scripts or shell you can invoke commands on this OLSR
+ /// routing agent thanks to this function. Currently you can call "start",
+ /// "print_rtable", "print_linkset", "print_nbset", "print_nb2hopset",
+ /// "print_mprset", "print_mprselset" and "print_topologyset" commands.
+ ///
+ /// \param argc Number of arguments.
+ /// \param argv Arguments.
+ /// \return TCL_OK or TCL_ERROR.
+ ///
+ int
+ OLSR::command(int argc, const char*const* argv) {
+ 	if (argc == 2) {
+ 		// Starts all timers
+ 		if (strcasecmp(argv[1], "start") == 0) {
+ 			hello_timer_.resched(0.0);
+ 			tc_timer_.resched(0.0);
+ 			mid_timer_.resched(0.0);
+ 			
+ 			return TCL_OK;
+     		}
+ 		// Prints routing table
+ 		else if (strcasecmp(argv[1], "print_rtable") == 0) {
+ 			if (logtarget_ != NULL) {
+ 				sprintf(logtarget_->pt_->buffer(), "P %f _%d_ Routing Table",
+ 					CURRENT_TIME,
+ 					OLSR::node_id(ra_addr()));
+ 				logtarget_->pt_->dump();
+ 				rtable_.print(logtarget_);
+ 			}
+ 			else {
+ 				fprintf(stdout, "%f _%d_ If you want to print this routing table "
+ 					"you must create a trace file in your tcl script",
+ 					CURRENT_TIME,
+ 					OLSR::node_id(ra_addr()));
+ 			}
+ 			return TCL_OK;
+ 		}
+ 		// Prints link set
+ 		else if (strcasecmp(argv[1], "print_linkset") == 0) {
+ 			if (logtarget_ != NULL) {
+ 				sprintf(logtarget_->pt_->buffer(), "P %f _%d_ Link Set",
+ 					CURRENT_TIME,
+ 					OLSR::node_id(ra_addr()));
+ 				logtarget_->pt_->dump();
+ 				OLSR_printer::print_linkset(logtarget_, linkset());
+ 			}
+ 			else {
+ 				fprintf(stdout, "%f _%d_ If you want to print this link set "
+ 					"you must create a trace file in your tcl script",
+ 					CURRENT_TIME,
+ 					OLSR::node_id(ra_addr()));
+ 			}
+ 			return TCL_OK;
+ 		}
+ 		// Prints neighbor set
+ 		else if (strcasecmp(argv[1], "print_nbset") == 0) {
+ 			if (logtarget_ != NULL) {
+ 				sprintf(logtarget_->pt_->buffer(), "P %f _%d_ Neighbor Set",
+ 					CURRENT_TIME,
+ 					OLSR::node_id(ra_addr()));
+ 				logtarget_->pt_->dump();
+ 				OLSR_printer::print_nbset(logtarget_, nbset());
+ 			}
+ 			else {
+ 				fprintf(stdout, "%f _%d_ If you want to print this neighbor set "
+ 					"you must create a trace file in your tcl script",
+ 					CURRENT_TIME,
+ 					OLSR::node_id(ra_addr()));
+ 			}
+ 			return TCL_OK;
+ 		}
+ 		// Prints 2-hop neighbor set
+ 		else if (strcasecmp(argv[1], "print_nb2hopset") == 0) {
+ 			if (logtarget_ != NULL) {
+ 				sprintf(logtarget_->pt_->buffer(), "P %f _%d_ Neighbor2hop Set",
+ 					CURRENT_TIME,
+ 					OLSR::node_id(ra_addr()));
+ 				logtarget_->pt_->dump();
+ 				OLSR_printer::print_nb2hopset(logtarget_, nb2hopset());
+ 			}
+ 			else {
+ 				fprintf(stdout, "%f _%d_ If you want to print this neighbor2hop set "
+ 					"you must create a trace file in your tcl script",
+ 					CURRENT_TIME,
+ 					OLSR::node_id(ra_addr()));
+ 			}
+ 			return TCL_OK;
+ 		}
+ 		// Prints MPR set
+ 		else if (strcasecmp(argv[1], "print_mprset") == 0) {
+ 			if (logtarget_ != NULL) {
+ 				sprintf(logtarget_->pt_->buffer(), "P %f _%d_ MPR Set",
+ 					CURRENT_TIME,
+ 					OLSR::node_id(ra_addr()));
+ 				logtarget_->pt_->dump();
+ 				OLSR_printer::print_mprset(logtarget_, mprset());
+ 			}
+ 			else {
+ 				fprintf(stdout, "%f _%d_ If you want to print this mpr set "
+ 					"you must create a trace file in your tcl script",
+ 					CURRENT_TIME,
+ 					OLSR::node_id(ra_addr()));
+ 			}
+ 			return TCL_OK;
+ 		}
+ 		// Prints MPR selector set
+ 		else if (strcasecmp(argv[1], "print_mprselset") == 0) {
+ 			if (logtarget_ != NULL) {
+ 				sprintf(logtarget_->pt_->buffer(), "P %f _%d_ MPR Selector Set",
+ 					CURRENT_TIME,
+ 					OLSR::node_id(ra_addr()));
+ 				logtarget_->pt_->dump();
+ 				OLSR_printer::print_mprselset(logtarget_, mprselset());
+ 			}
+ 			else {
+ 				fprintf(stdout, "%f _%d_ If you want to print this mpr selector set "
+ 					"you must create a trace file in your tcl script",
+ 					CURRENT_TIME,
+ 					OLSR::node_id(ra_addr()));
+ 			}
+ 			return TCL_OK;
+ 		}
+ 		// Prints topology set
+ 		else if (strcasecmp(argv[1], "print_topologyset") == 0) {
+ 			if (logtarget_ != NULL) {
+ 				sprintf(logtarget_->pt_->buffer(), "P %f _%d_ Topology Set",
+ 					CURRENT_TIME,
+ 					OLSR::node_id(ra_addr()));
+ 				logtarget_->pt_->dump();
+ 				OLSR_printer::print_topologyset(logtarget_, topologyset());
+ 			}
+ 			else {
+ 				fprintf(stdout, "%f _%d_ If you want to print this topology set "
+ 					"you must create a trace file in your tcl script",
+ 					CURRENT_TIME,
+ 					OLSR::node_id(ra_addr()));
+ 			}
+ 			return TCL_OK;
+ 		}
+ 	}
+ 	else if (argc == 3) {
+ 		// Obtains the corresponding dmux to carry packets to upper layers
+ 		if (strcmp(argv[1], "port-dmux") == 0) {
+     			dmux_ = (PortClassifier*)TclObject::lookup(argv[2]);
+ 			if (dmux_ == NULL) {
+ 				fprintf(stderr, "%s: %s lookup of %s failed\n", __FILE__, argv[1], argv[2]);
+ 				return TCL_ERROR;
+ 			}
+ 			return TCL_OK;
+     		}
+ 		// Obtains the corresponding tracer
+ 		else if (strcmp(argv[1], "log-target") == 0 || strcmp(argv[1], "tracetarget") == 0) {
+ 			logtarget_ = (Trace*)TclObject::lookup(argv[2]);
+ 			if (logtarget_ == NULL)
+ 				return TCL_ERROR;
+ 			return TCL_OK;
+ 		}
+ 	}
+ 	// Pass the command up to the base class
+ 	return Agent::command(argc, argv);
+ }
+ 
+ 
+ /********** Timers **********/
+ 
+ 
+ ///
+ /// \brief Sends a HELLO message and reschedules the HELLO timer.
+ /// \param e The event which has expired.
+ ///
+ void
+ OLSR_HelloTimer::expire(Event* e) {
+ 	agent_->send_hello();
+ 	agent_->set_hello_timer();
+ }
+ 
+ ///
+ /// \brief Sends a TC message (if there exists any MPR selector) and reschedules the TC timer.
+ /// \param e The event which has expired.
+ ///
+ void
+ OLSR_TcTimer::expire(Event* e) {
+ 	if (agent_->mprselset().size() > 0)
+ 		agent_->send_tc();
+ 	agent_->set_tc_timer();
+ }
+ 
+ ///
+ /// \brief Sends a MID message (if the node has more than one interface) and resets the MID timer.
+ /// \warning Currently it does nothing because there is no support for multiple interfaces.
+ /// \param e The event which has expired.
+ ///
+ void
+ OLSR_MidTimer::expire(Event* e) {
+ #ifdef MULTIPLE_IFACES_SUPPORT
+ 	agent_->send_mid();
+ 	agent_->set_mid_timer();
+ #endif
+ }
+ 
+ ///
+ /// \brief Removes tuple_ if expired. Else timer is rescheduled to expire at tuple_->time().
+ ///
+ /// The task of actually removing the tuple is left to the OLSR agent.
+ ///
+ /// \param e The event which has expired.
+ ///
+ void
+ OLSR_DupTupleTimer::expire(Event* e) {
+ 	if (tuple_->time() < CURRENT_TIME) {
+ 		agent_->rm_dup_tuple(tuple_);
+ 		delete tuple_;
+ 		agent_->expired_timers_.push_back(this);
+ 	}
+ 	else
+ 		resched(DELAY(tuple_->time()));
+ }
+ 
+ ///
+ /// \brief Removes tuple_ if expired. Else if symmetric time
+ /// has expired then it is assumed a neighbor loss and agent_->nb_loss()
+ /// is called. In this case the timer is rescheduled to expire at
+ /// tuple_->time(). Otherwise the timer is rescheduled to expire at
+ /// the minimum between tuple_->time() and tuple_->sym_time().
+ ///
+ /// The task of actually removing the tuple is left to the OLSR agent.
+ ///
+ /// \param e The event which has expired.
+ ///
+ void
+ OLSR_LinkTupleTimer::expire(Event* e) {
+ 	double now	= CURRENT_TIME;
+ 	
+ 	if (tuple_->time() < now) {
+ 		agent_->rm_link_tuple(tuple_);
+ 		delete tuple_;
+ 		agent_->expired_timers_.push_back(this);
+ 	}
+ 	else if (tuple_->sym_time() < now) {
+ 		if (first_time_)
+ 			first_time_ = false;
+ 		else
+ 			agent_->nb_loss(tuple_);
+ 		resched(DELAY(tuple_->time()));
+ 	}
+ 	else
+ 		resched(DELAY(MIN(tuple_->time(), tuple_->sym_time())));
+ }
+ 
+ ///
+ /// \brief Removes tuple_ if expired. Else the timer is rescheduled to expire at tuple_->time().
+ ///
+ /// The task of actually removing the tuple is left to the OLSR agent.
+ ///
+ /// \param e The event which has expired.
+ ///
+ void
+ OLSR_Nb2hopTupleTimer::expire(Event* e) {
+ 	if (tuple_->time() < CURRENT_TIME) {
+ 		agent_->rm_nb2hop_tuple(tuple_);
+ 		delete tuple_;
+ 		agent_->expired_timers_.push_back(this);
+ 	}
+ 	else
+ 		resched(DELAY(tuple_->time()));
+ }
+ 
+ ///
+ /// \brief Removes tuple_ if expired. Else the timer is rescheduled to expire at tuple_->time().
+ ///
+ /// The task of actually removing the tuple is left to the OLSR agent.
+ ///
+ /// \param e The event which has expired.
+ ///
+ void
+ OLSR_MprSelTupleTimer::expire(Event* e) {
+ 	if (tuple_->time() < CURRENT_TIME) {
+ 		agent_->rm_mprsel_tuple(tuple_);
+ 		delete tuple_;
+ 		agent_->expired_timers_.push_back(this);
+ 	}
+ 	else
+ 		resched(DELAY(tuple_->time()));
+ }
+ 
+ ///
+ /// \brief Removes tuple_ if expired. Else the timer is rescheduled to expire at tuple_->time().
+ ///
+ /// The task of actually removing the tuple is left to the OLSR agent.
+ ///
+ /// \param e The event which has expired.
+ ///
+ void
+ OLSR_TopologyTupleTimer::expire(Event* e) {
+ 	if (tuple_->time() < CURRENT_TIME) {
+ 		agent_->rm_topology_tuple(tuple_);
+ 		delete tuple_;
+ 		agent_->expired_timers_.push_back(this);
+ 	}
+ 	else
+ 		resched(DELAY(tuple_->time()));
+ }
+ 
+ ///
+ /// \brief Removes tuple_ if expired. Else timer is rescheduled to expire at tuple_->time().
+ /// \warning Actually this is never invoked because there is no support for multiple interfaces.
+ /// \param e The event which has expired.
+ ///
+ void
+ OLSR_IfaceAssocTupleTimer::expire(Event* e) {
+ 	if (tuple_->time() < CURRENT_TIME) {
+ 		agent_->rm_ifaceassoc_tuple(tuple_);
+ 		delete tuple_;
+ 		agent_->expired_timers_.push_back(this);
+ 	}
+ 	else
+ 		resched(DELAY(tuple_->time()));
+ }
+ 
+ ///
+ /// \brief Sends a control packet which must bear every message in the OLSR agent's buffer.
+ ///
+ /// The task of actually sending the packet is left to the OLSR agent.
+ ///
+ /// \param e The event which has expired.
+ ///
+ void
+ OLSR_MsgTimer::expire(Event* e) {
+ 	agent_->send_pkt();
+ 	agent_->expired_timers_.push_back(this);
+ }
+ 
+ 
+ /********** OLSR class **********/
+ 
+ 
+ ///
+ /// \brief Creates necessary timers, binds TCL-available variables and do
+ /// some more initializations.
+ /// \param id Identifier for the OLSR agent. It will be used as the address
+ /// of this routing agent.
+ ///
+ OLSR::OLSR(nsaddr_t id) :	Agent(PT_OLSR),
+ 				hello_timer_(this),
+ 				tc_timer_(this),
+ 				mid_timer_(this) {
+ 
+ 	// Enable usage of some of the configuration variables from Tcl.
+ 	//
+ 	// Note: Do NOT change the values of these variables in the constructor
+ 	// after binding them! The desired default values should be set in
+ 	// ns-X.XX/tcl/lib/ns-default.tcl instead.
+ 	bind("willingness_", &willingness_);
+ 	bind("hello_ival_", &hello_ival_);
+ 	bind("tc_ival_", &tc_ival_);
+ 	bind("mid_ival_", &mid_ival_);
+ 	bind_bool("use_mac_", &use_mac_);
+ 	
+ 	// Do some initializations
+ 	ra_addr_	= id;
+ 	pkt_seq_	= OLSR_MAX_SEQ_NUM;
+ 	msg_seq_	= OLSR_MAX_SEQ_NUM;
+ 	ansn_		= OLSR_MAX_SEQ_NUM;
+ }
+ 
+ ///
+ /// \brief	This function is called whenever a packet is received. It identifies
+ ///		the type of the received packet and process it accordingly.
+ ///
+ /// If it is an %OLSR packet then it is processed. In other case, if it is a data packet
+ /// then it is forwarded.
+ ///
+ /// \param	p the received packet.
+ /// \param	h a handler (not used).
+ ///
+ void
+ OLSR::recv(Packet* p, Handler* h) {
+ 	struct hdr_cmn* ch	= HDR_CMN(p);
+ 	struct hdr_ip* ih	= HDR_IP(p);
+ 	
+ 	if (ih->saddr() == ra_addr()) {
+ 		// If there exists a loop, must drop the packet
+ 		if (ch->num_forwards() > 0) {
+ 			drop(p, DROP_RTR_ROUTE_LOOP);
+ 			return;
+ 		}
+ 		// else if this is a packet I am originating, must add IP header
+ 		else if (ch->num_forwards() == 0)
+ 			ch->size() += IP_HDR_LEN;
+ 	}
+ 	
+ 	// If it is an OLSR packet, must process it
+ 	if (ch->ptype() == PT_OLSR)
+ 		recv_olsr(p);
+ 	// Otherwise, must forward the packet (unless TTL has reached zero)
+ 	else {
+ 		ih->ttl_--;
+ 		if (ih->ttl_ == 0) {
+ 			drop(p, DROP_RTR_TTL);
+ 			return;
+ 		}
+ 		forward_data(p);
+ 	}
+ }
+ 
+ ///
+ /// \brief Processes an incoming %OLSR packet following RFC 3626 specification.
+ /// \param p received packet.
+ ///
+ void
+ OLSR::recv_olsr(Packet* p) {
+ 	struct hdr_ip* ih	= HDR_IP(p);
+ 	OLSR_pkt* op		= PKT_OLSR(p);
+ 	
+ 	// All routing messages are sent from and to port RT_PORT,
+ 	// so we check it.
+ 	assert(ih->sport() == RT_PORT);
+ 	assert(ih->dport() == RT_PORT);
+ 	
+ 	// If the packet contains no messages must be silently discarded.
+ 	// There could exist a message with an empty body, so the size of
+ 	// the packet would be pkt-hdr-size + msg-hdr-size.
+ 	if (op->pkt_len() < OLSR_PKT_HDR_SIZE + OLSR_MSG_HDR_SIZE) {
+ 		Packet::free(p);
+ 		return;
+ 	}
+ 	
+ 	assert(op->count >= 0 && op->count <= OLSR_MAX_MSGS);
+ 	for (int i = 0; i < op->count; i++) {
+ 		OLSR_msg& msg = op->msg(i);
+ 		
+ 		// If ttl is less than or equal to zero, or
+ 		// the receiver is the same as the originator,
+ 		// the message must be silently dropped
+ 		if (msg.ttl() <= 0 || msg.orig_addr() == ra_addr())
+ 			continue;
+ 		
+ 		// If the message has been processed it must not be
+ 		// processed again
+ 		bool do_forwarding = true;
+ 		OLSR_dup_tuple* duplicated = state_.find_dup_tuple(msg.orig_addr(), msg.msg_seq_num());
+ 		if (duplicated == NULL) {
+ 			// Process the message according to its type
+ 			if (msg.msg_type() == OLSR_HELLO_MSG)
+ 				process_hello(msg, ra_addr(), ih->saddr());
+ 			else if (msg.msg_type() == OLSR_TC_MSG)
+ 				process_tc(msg, ih->saddr());
+ 			else if (msg.msg_type() == OLSR_MID_MSG)
+ 				process_mid(msg, ih->saddr());
+ 			else {
+ 				debug("%f: Node %d can not process OLSR packet because does not "
+ 					"implement OLSR type (%x)\n",
+ 					CURRENT_TIME,
+ 					OLSR::node_id(ra_addr()),
+ 					msg.msg_type());
+ 			}
+ 		}
+ 		else {
+ 			// If the message has been considered for forwarding, it should
+ 			// not be retransmitted again
+ 			for (addr_list_t::iterator it = duplicated->iface_list().begin();
+ 				it != duplicated->iface_list().end();
+ 				it++) {
+ 				if (*it == ra_addr()) {
+ 					do_forwarding = false;
+ 					break;
+ 				}
+ 			}
+ 		}
+ 			
+ 		if (do_forwarding) {
+ 			// HELLO messages are never forwarded.
+ 			// TC and MID messages are forwarded using the default algorithm.
+ 			// Remaining messages are also forwarded using the default algorithm.
+ 			if (msg.msg_type() != OLSR_HELLO_MSG)
+ 				forward_default(p, msg, duplicated, ra_addr());
+ 		}
+ 
+ 	}
+ 	
+ 	// After processing all OLSR messages, we must recompute routing table
+ 	rtable_computation();
+ 	
+ 	// Release resources
+ 	release_expired_timers();	// we had to put this at some place
+ 	Packet::free(p);
+ }
+ 
+ ///
+ /// \brief Computates MPR set of a node following RFC 3626 hints.
+ ///
+ void
+ OLSR::mpr_computation() {
+ 	// MPR computation should be done for each interface. See section 8.3.1
+ 	// (RFC 3626) for details.
+ 	
+ 	state_.clear_mprset();
+ 	
+ 	nbset_t N; nb2hopset_t N2;
+ 	// N is the subset of neighbors of the node, which are
+ 	// neighbor "of the interface I"
+ 	for (nbset_t::iterator it = nbset().begin(); it != nbset().end(); it++)
+ 		if ((*it)->status() == OLSR_STATUS_SYM) // I think that we need this check
+ 			N.push_back(*it);
+ 	
+ 	// N2 is the set of 2-hop neighbors reachable from "the interface
+ 	// I", excluding:
+ 	// (i)   the nodes only reachable by members of N with willingness WILL_NEVER
+ 	// (ii)  the node performing the computation
+ 	// (iii) all the symmetric neighbors: the nodes for which there exists a symmetric
+ 	//       link to this node on some interface.
+ 	for (nb2hopset_t::iterator it = nb2hopset().begin(); it != nb2hopset().end(); it++) {
+ 		OLSR_nb2hop_tuple* nb2hop_tuple = *it;
+ 		bool ok = true;
+ 		OLSR_nb_tuple* nb_tuple = state_.find_sym_nb_tuple(nb2hop_tuple->nb_main_addr());
+ 		if (nb_tuple == NULL)
+ 			ok = false;
+ 		else {
+ 			nb_tuple = state_.find_nb_tuple(nb2hop_tuple->nb_main_addr(), OLSR_WILL_NEVER);
+ 			if (nb_tuple != NULL)
+ 				ok = false;
+ 			else {
+ 				nb_tuple = state_.find_sym_nb_tuple(nb2hop_tuple->nb2hop_addr());
+ 				if (nb_tuple != NULL)
+ 					ok = false;
+ 			}
+ 		}
+ 
+ 		if (ok)
+ 			N2.push_back(nb2hop_tuple);
+ 	}
+ 	
+ 	// 1. Start with an MPR set made of all members of N with
+ 	// N_willingness equal to WILL_ALWAYS
+ 	for (nbset_t::iterator it = N.begin(); it != N.end(); it++) {
+ 		OLSR_nb_tuple* nb_tuple = *it;
+ 		if (nb_tuple->willingness() == OLSR_WILL_ALWAYS)
+ 			state_.insert_mpr_addr(nb_tuple->nb_main_addr());
+ 	}
+ 	
+ 	// 2. Calculate D(y), where y is a member of N, for all nodes in N.
+ 	// We will do this later.
+ 	
+ 	// 3. Add to the MPR set those nodes in N, which are the *only*
+ 	// nodes to provide reachability to a node in N2. Remove the
+ 	// nodes from N2 which are now covered by a node in the MPR set.
+ 	mprset_t foundset;
+ 	std::set<nsaddr_t> deleted_addrs;
+ 	for (nb2hopset_t::iterator it = N2.begin(); it != N2.end(); it++) {
+ 		OLSR_nb2hop_tuple* nb2hop_tuple1 = *it;
+ 		
+ 		mprset_t::iterator pos = foundset.find(nb2hop_tuple1->nb2hop_addr());
+ 		if (pos != foundset.end())
+ 			continue;
+ 		
+ 		bool found = false;
+ 		for (nbset_t::iterator it2 = N.begin(); it2 != N.end(); it2++) {
+ 			if ((*it2)->nb_main_addr() == nb2hop_tuple1->nb_main_addr()) {
+ 				found = true;
+ 				break;
+ 			}
+ 		}
+ 		if (!found)
+ 			continue;
+ 		
+ 		found = false;
+ 		for (nb2hopset_t::iterator it2 = it + 1; it2 != N2.end(); it2++) {
+ 			OLSR_nb2hop_tuple* nb2hop_tuple2 = *it2;
+ 			if (nb2hop_tuple1->nb2hop_addr() == nb2hop_tuple2->nb2hop_addr()) {
+ 				foundset.insert(nb2hop_tuple1->nb2hop_addr());
+ 				found = true;
+ 				break;
+ 			}
+ 		}
+ 		if (!found) {
+ 			state_.insert_mpr_addr(nb2hop_tuple1->nb_main_addr());
+ 			
+ 			for (nb2hopset_t::iterator it2 = it + 1; it2 != N2.end(); it2++) {
+ 				OLSR_nb2hop_tuple* nb2hop_tuple2 = *it2;
+ 				if (nb2hop_tuple1->nb_main_addr() == nb2hop_tuple2->nb_main_addr()) {
+ 					deleted_addrs.insert(nb2hop_tuple2->nb2hop_addr());
+ 					it2 = N2.erase(it2);
+ 					it2--;
+ 				}
+ 			}
+ 			it = N2.erase(it);
+ 			it--;
+ 		}
+ 		
+ 		for (std::set<nsaddr_t>::iterator it2 = deleted_addrs.begin();
+ 			it2 != deleted_addrs.end();
+ 			it2++) {
+ 			for (nb2hopset_t::iterator it3 = N2.begin();
+ 				it3 != N2.end();
+ 				it3++) {
+ 				if ((*it3)->nb2hop_addr() == *it2) {
+ 					it3 = N2.erase(it3);
+ 					it3--;
+ 					// I have to reset the external iterator because it
+ 					// may have been invalidated by the latter deletion
+ 					it = N2.begin();
+ 					it--;
+ 				}
+ 			}
+ 		}
+ 		deleted_addrs.clear();
+ 	}
+ 	
+ 	// 4. While there exist nodes in N2 which are not covered by at
+ 	// least one node in the MPR set:
+ 	while (N2.begin() != N2.end()) {
+ 		// 4.1. For each node in N, calculate the reachability, i.e., the
+ 		// number of nodes in N2 which are not yet covered by at
+ 		// least one node in the MPR set, and which are reachable
+ 		// through this 1-hop neighbor
+ 		map<int, std::vector<OLSR_nb_tuple*> > reachability;
+ 		set<int> rs;
+ 		for (nbset_t::iterator it = N.begin(); it != N.end(); it++) {
+ 			OLSR_nb_tuple* nb_tuple = *it;
+ 			int r = 0;
+ 			for (nb2hopset_t::iterator it2 = N2.begin(); it2 != N2.end(); it2++) {
+ 				OLSR_nb2hop_tuple* nb2hop_tuple = *it2;
+ 				if (nb_tuple->nb_main_addr() == nb2hop_tuple->nb_main_addr())
+ 					r++;
+ 			}
+ 			rs.insert(r);
+ 			reachability[r].push_back(nb_tuple);
+ 		}
+ 		
+ 		// 4.2. Select as a MPR the node with highest N_willingness among
+ 		// the nodes in N with non-zero reachability. In case of
+ 		// multiple choice select the node which provides
+ 		// reachability to the maximum number of nodes in N2. In
+ 		// case of multiple nodes providing the same amount of
+ 		// reachability, select the node as MPR whose D(y) is
+ 		// greater. Remove the nodes from N2 which are now covered
+ 		// by a node in the MPR set.
+ 		OLSR_nb_tuple* max = NULL;
+ 		int max_r = 0;
+ 		for (set<int>::iterator it = rs.begin(); it != rs.end(); it++) {
+ 			int r = *it;
+ 			if (r > 0) {
+ 				for (std::vector<OLSR_nb_tuple*>::iterator it2 = reachability[r].begin();
+ 					it2 != reachability[r].end();
+ 					it2++) {
+ 					OLSR_nb_tuple* nb_tuple = *it2;
+ 					if (max == NULL || nb_tuple->willingness() > max->willingness()) {
+ 						max = nb_tuple;
+ 						max_r = r;
+ 					}
+ 					else if (nb_tuple->willingness() == max->willingness()) {
+ 						if (r > max_r) {
+ 							max = nb_tuple;
+ 							max_r = r;
+ 						}
+ 						else if (r == max_r) {
+ 							if (degree(nb_tuple) > degree(max)) {
+ 								max = nb_tuple;
+ 								max_r = r;
+ 							}
+ 						}
+ 					}
+ 				}
+ 			}
+ 		}
+ 		if (max != NULL) {
+ 			state_.insert_mpr_addr(max->nb_main_addr());
+ 			std::set<nsaddr_t> nb2hop_addrs;
+ 			for (nb2hopset_t::iterator it = N2.begin(); it != N2.end(); it++) {
+ 				OLSR_nb2hop_tuple* nb2hop_tuple = *it;
+ 				if (nb2hop_tuple->nb_main_addr() == max->nb_main_addr()) {
+ 					nb2hop_addrs.insert(nb2hop_tuple->nb2hop_addr());
+ 					it = N2.erase(it);
+ 					it--;
+ 				}
+ 			}
+ 			for (nb2hopset_t::iterator it = N2.begin(); it != N2.end(); it++) {
+ 				OLSR_nb2hop_tuple* nb2hop_tuple = *it;
+ 				std::set<nsaddr_t>::iterator it2 =
+ 					nb2hop_addrs.find(nb2hop_tuple->nb2hop_addr());
+ 				if (it2 != nb2hop_addrs.end()) {
+ 					it = N2.erase(it);
+ 					it--;
+ 				}
+ 			}
+ 		}
+ 	}
+ }
+ 
+ ///
+ /// \brief Creates the routing table of the node following RFC 3626 hints.
+ ///
+ void
+ OLSR::rtable_computation() {
+ 	// 1. All the entries from the routing table are removed.
+ 	rtable_.clear();
+ 	
+ 	// 2. The new routing entries are added starting with the
+ 	// symmetric neighbors (h=1) as the destination nodes.
+ 	for (nbset_t::iterator it = nbset().begin(); it != nbset().end(); it++) {
+ 		OLSR_nb_tuple* nb_tuple = *it;
+ 		if (nb_tuple->status() == OLSR_STATUS_SYM) {
+ 			bool nb_main_addr = false;
+ 			OLSR_link_tuple* lt = NULL;
+ 			for (linkset_t::iterator it2 = linkset().begin(); it2 != linkset().end(); it2++) {
+ 				OLSR_link_tuple* link_tuple = *it2;
+ 				if (get_main_addr(link_tuple->nb_iface_addr()) == nb_tuple->nb_main_addr() && link_tuple->time() >= CURRENT_TIME) {
+ 					lt = link_tuple;
+ 					rtable_.add_entry(link_tuple->nb_iface_addr(),
+ 							link_tuple->nb_iface_addr(),
+ 							link_tuple->local_iface_addr(),
+ 							1);
+ 					if (link_tuple->nb_iface_addr() == nb_tuple->nb_main_addr())
+ 						nb_main_addr = true;
+ 				}
+ 			}
+ 			if (!nb_main_addr && lt != NULL) {
+ 				rtable_.add_entry(nb_tuple->nb_main_addr(),
+ 						lt->nb_iface_addr(),
+ 						lt->local_iface_addr(),
+ 						1);
+ 			}
+ 		}
+ 	}
+ 	
+ 	// N2 is the set of 2-hop neighbors reachable from this node, excluding:
+ 	// (i)   the nodes only reachable by members of N with willingness WILL_NEVER
+ 	// (ii)  the node performing the computation
+ 	// (iii) all the symmetric neighbors: the nodes for which there exists a symmetric
+ 	//       link to this node on some interface.
+ 	for (nb2hopset_t::iterator it = nb2hopset().begin(); it != nb2hopset().end(); it++) {
+ 		OLSR_nb2hop_tuple* nb2hop_tuple = *it;
+ 		bool ok = true;
+ 		OLSR_nb_tuple* nb_tuple = state_.find_sym_nb_tuple(nb2hop_tuple->nb_main_addr());
+ 		if (nb_tuple == NULL)
+ 			ok = false;
+ 		else {
+ 			nb_tuple = state_.find_nb_tuple(nb2hop_tuple->nb_main_addr(), OLSR_WILL_NEVER);
+ 			if (nb_tuple != NULL)
+ 				ok = false;
+ 			else {
+ 				nb_tuple = state_.find_sym_nb_tuple(nb2hop_tuple->nb2hop_addr());
+ 				if (nb_tuple != NULL)
+ 					ok = false;
+ 			}
+ 		}
+ 
+ 		// 3. For each node in N2 create a new entry in the routing table
+ 		if (ok) {
+ 			OLSR_rt_entry* entry = rtable_.lookup(nb2hop_tuple->nb_main_addr());
+ 			assert(entry != NULL);
+ 			rtable_.add_entry(nb2hop_tuple->nb2hop_addr(),
+ 					entry->next_addr(),
+ 					entry->iface_addr(),
+ 					2);
+ 		}
+ 	}
+ 	
+ 	for (u_int32_t h = 2; ; h++) {
+ 		bool added = false;
+ 		
+ 		// 4.1. For each topology entry in the topology table, if its
+ 		// T_dest_addr does not correspond to R_dest_addr of any
+ 		// route entry in the routing table AND its T_last_addr
+ 		// corresponds to R_dest_addr of a route entry whose R_dist
+ 		// is equal to h, then a new route entry MUST be recorded in
+ 		// the routing table (if it does not already exist)
+ 		for (topologyset_t::iterator it = topologyset().begin();
+ 			it != topologyset().end();
+ 			it++) {
+ 			OLSR_topology_tuple* topology_tuple = *it;
+ 			OLSR_rt_entry* entry1 = rtable_.lookup(topology_tuple->dest_addr());
+ 			OLSR_rt_entry* entry2 = rtable_.lookup(topology_tuple->last_addr());
+ 			if (entry1 == NULL && entry2 != NULL && entry2->dist() == h) {
+ 				rtable_.add_entry(topology_tuple->dest_addr(),
+ 						entry2->next_addr(),
+ 						entry2->iface_addr(),
+ 						h+1);
+ 				added = true;
+ 			}
+ 		}
+ 		
+ 		// 5. For each entry in the multiple interface association base
+ 		// where there exists a routing entry such that:
+ 		//	R_dest_addr  == I_main_addr  (of the multiple interface association entry)
+ 		// AND there is no routing entry such that:
+ 		//	R_dest_addr  == I_iface_addr
+ 		// then a route entry is created in the routing table
+ 		for (ifaceassocset_t::iterator it = ifaceassocset().begin();
+ 			it != ifaceassocset().end();
+ 			it++) {
+ 			OLSR_iface_assoc_tuple* tuple = *it;
+ 			OLSR_rt_entry* entry1 = rtable_.lookup(tuple->main_addr());
+ 			OLSR_rt_entry* entry2 = rtable_.lookup(tuple->iface_addr());
+ 			if (entry1 != NULL && entry2 == NULL) {
+ 				rtable_.add_entry(tuple->iface_addr(),
+ 						entry1->next_addr(),
+ 						entry1->iface_addr(),
+ 						entry1->dist());
+ 				added = true;
+ 			}
+ 		}
+ 
+ 		if (!added)
+ 			break;
+ 	}
+ }
+ 
+ ///
+ /// \brief Processes a HELLO message following RFC 3626 specification.
+ ///
+ /// Link sensing and population of the Neighbor Set, 2-hop Neighbor Set and MPR
+ /// Selector Set are performed.
+ ///
+ /// \param msg the %OLSR message which contains the HELLO message.
+ /// \param receiver_iface the address of the interface where the message was received from.
+ /// \param sender_iface the address of the interface where the message was sent from.
+ ///
+ void
+ OLSR::process_hello(OLSR_msg& msg, nsaddr_t receiver_iface, nsaddr_t sender_iface) {
+ 	assert(msg.msg_type() == OLSR_HELLO_MSG);
+ 
+         link_sensing(msg, receiver_iface, sender_iface);
+ 	populate_nbset(msg);
+ 	populate_nb2hopset(msg);
+ 	mpr_computation();
+ 	populate_mprselset(msg);
+ }
+ 
+ ///
+ /// \brief Processes a TC message following RFC 3626 specification.
+ ///
+ /// The Topology Set is updated (if needed) with the information of
+ /// the received TC message.
+ ///
+ /// \param msg the %OLSR message which contains the TC message.
+ /// \param sender_iface the address of the interface where the message was sent from.
+ ///
+ void
+ OLSR::process_tc(OLSR_msg& msg, nsaddr_t sender_iface) {
+ 	assert(msg.msg_type() == OLSR_TC_MSG);
+ 	double now	= CURRENT_TIME;
+ 	OLSR_tc& tc	= msg.tc();
+ 	
+ 	// 1. If the sender interface of this message is not in the symmetric
+ 	// 1-hop neighborhood of this node, the message MUST be discarded.
+ 	OLSR_link_tuple* link_tuple = state_.find_sym_link_tuple(sender_iface, now);
+ 	if (link_tuple == NULL)
+ 		return;
+ 	
+ 	// 2. If there exist some tuple in the topology set where:
+ 	// 	T_last_addr == originator address AND
+ 	// 	T_seq       >  ANSN,
+ 	// then further processing of this TC message MUST NOT be
+ 	// performed.
+ 	OLSR_topology_tuple* topology_tuple =
+ 		state_.find_newer_topology_tuple(msg.orig_addr(), tc.ansn());
+ 	if (topology_tuple != NULL)
+ 		return;
+ 	
+ 	// 3. All tuples in the topology set where:
+ 	//	T_last_addr == originator address AND
+ 	//	T_seq       <  ANSN
+ 	// MUST be removed from the topology set.
+ 	state_.erase_older_topology_tuples(msg.orig_addr(), tc.ansn());
+ 
+ 	// 4. For each of the advertised neighbor main address received in
+ 	// the TC message:
+ 	for (int i = 0; i < tc.count; i++) {
+ 		assert(i >= 0 && i < OLSR_MAX_ADDRS);
+ 		nsaddr_t addr = tc.nb_main_addr(i);
+ 		// 4.1. If there exist some tuple in the topology set where:
+ 		// 	T_dest_addr == advertised neighbor main address, AND
+ 		// 	T_last_addr == originator address,
+ 		// then the holding time of that tuple MUST be set to:
+ 		// 	T_time      =  current time + validity time.
+ 		OLSR_topology_tuple* topology_tuple =
+ 			state_.find_topology_tuple(addr, msg.orig_addr());
+ 		if (topology_tuple != NULL)
+ 			topology_tuple->time() = now + OLSR::emf_to_seconds(msg.vtime());
+ 		// 4.2. Otherwise, a new tuple MUST be recorded in the topology
+ 		// set where:
+ 		//	T_dest_addr = advertised neighbor main address,
+ 		//	T_last_addr = originator address,
+ 		//	T_seq       = ANSN,
+ 		//	T_time      = current time + validity time.
+ 		else {
+ 			OLSR_topology_tuple* topology_tuple = new OLSR_topology_tuple;
+ 			topology_tuple->dest_addr()	= addr;
+ 			topology_tuple->last_addr()	= msg.orig_addr();
+ 			topology_tuple->seq()		= tc.ansn();
+ 			topology_tuple->time()		= now + OLSR::emf_to_seconds(msg.vtime());
+ 			add_topology_tuple(topology_tuple);
+ 			// Schedules topology tuple deletion
+ 			OLSR_TopologyTupleTimer* topology_timer =
+ 				new OLSR_TopologyTupleTimer(this, topology_tuple);
+ 			topology_timer->resched(DELAY(topology_tuple->time()));
+ 		}
+ 	}
+ }
+ 
+ ///
+ /// \brief Processes a MID message following RFC 3626 specification.
+ ///
+ /// The Interface Association Set is updated (if needed) with the information
+ /// of the received MID message.
+ ///
+ /// \param msg the %OLSR message which contains the MID message.
+ /// \param sender_iface the address of the interface where the message was sent from.
+ ///
+ void
+ OLSR::process_mid(OLSR_msg& msg, nsaddr_t sender_iface) {
+ 	assert(msg.msg_type() == OLSR_MID_MSG);
+ 	double now	= CURRENT_TIME;
+ 	OLSR_mid& mid	= msg.mid();
+ 	
+ 	// 1. If the sender interface of this message is not in the symmetric
+ 	// 1-hop neighborhood of this node, the message MUST be discarded.
+ 	OLSR_link_tuple* link_tuple = state_.find_sym_link_tuple(sender_iface, now);
+ 	if (link_tuple == NULL)
+ 		return;
+ 	
+ 	// 2. For each interface address listed in the MID message
+ 	for (int i = 0; i < mid.count; i++) {
+ 		bool updated = false;
+ 		for (ifaceassocset_t::iterator it = ifaceassocset().begin();
+ 			it != ifaceassocset().end();
+ 			it++) {
+ 			OLSR_iface_assoc_tuple* tuple = *it;
+ 			if (tuple->iface_addr() == mid.iface_addr(i)
+ 				&& tuple->main_addr() == msg.orig_addr()) {
+ 				tuple->time()	= now + OLSR::emf_to_seconds(msg.vtime());
+ 				updated		= true;
+ 			}			
+ 		}
+ 		if (!updated) {
+ 			OLSR_iface_assoc_tuple* tuple	= new OLSR_iface_assoc_tuple;
+ 			tuple->iface_addr()		= msg.mid().iface_addr(i);
+ 			tuple->main_addr()		= msg.orig_addr();
+ 			tuple->time()			= now + OLSR::emf_to_seconds(msg.vtime());
+ 			add_ifaceassoc_tuple(tuple);
+ 			// Schedules iface association tuple deletion
+ 			OLSR_IfaceAssocTupleTimer* ifaceassoc_timer =
+ 				new OLSR_IfaceAssocTupleTimer(this, tuple);
+ 			ifaceassoc_timer->resched(DELAY(tuple->time()));
+ 		}
+ 	}
+ }
+ 
+ ///
+ /// \brief OLSR's default forwarding algorithm.
+ ///
+ /// See RFC 3626 for details.
+ ///
+ /// \param p the %OLSR packet which has been received.
+ /// \param msg the %OLSR message which must be forwarded.
+ /// \param dup_tuple NULL if the message has never been considered for forwarding,
+ /// or a duplicate tuple in other case.
+ /// \param local_iface the address of the interface where the message was received from.
+ ///
+ void
+ OLSR::forward_default(Packet* p, OLSR_msg& msg, OLSR_dup_tuple* dup_tuple, nsaddr_t local_iface) {
+ 	double now		= CURRENT_TIME;
+ 	struct hdr_ip* ih	= HDR_IP(p);
+ 	
+ 	// If the sender interface address is not in the symmetric
+ 	// 1-hop neighborhood the message must not be forwarded
+ 	OLSR_link_tuple* link_tuple = state_.find_sym_link_tuple(ih->saddr(), now);
+ 	if (link_tuple == NULL)
+ 		return;
+ 
+ 	// If the message has already been considered for forwarding,
+ 	// it must not be retransmitted again
+ 	if (dup_tuple != NULL && dup_tuple->retransmitted()) {
+ 		debug("%f: Node %d does not forward a message received"
+ 			" from %d because it is duplicated\n",
+ 			CURRENT_TIME,
+ 			OLSR::node_id(ra_addr()),
+ 			OLSR::node_id(dup_tuple->addr()));
+ 		return;
+ 	}
+ 	
+ 	// If the sender interface address is an interface address
+ 	// of a MPR selector of this node and ttl is greater than 1,
+ 	// the message must be retransmitted
+ 	bool retransmitted = false;
+ 	if (msg.ttl() > 1) {
+ 		OLSR_mprsel_tuple* mprsel_tuple =
+ 			state_.find_mprsel_tuple(get_main_addr(ih->saddr()));
+ 		if (mprsel_tuple != NULL) {
+ 			OLSR_msg& new_msg = msg;
+ 			new_msg.ttl()--;
+ 			new_msg.hop_count()++;
+ 			// We have to introduce a random delay to avoid
+ 			// synchronization with neighbors.
+ 			enque_msg(new_msg, JITTER);
+ 			retransmitted = true;
+ 		}
+ 	}
+ 	
+ 	// Update duplicate tuple...
+ 	if (dup_tuple != NULL) {
+ 		dup_tuple->time()		= now + OLSR_DUP_HOLD_TIME;
+ 		dup_tuple->retransmitted()	= retransmitted;
+ 		dup_tuple->iface_list().push_back(local_iface);
+ 	}
+ 	// ...or create a new one
+ 	else {
+ 		OLSR_dup_tuple* new_dup = new OLSR_dup_tuple;
+ 		new_dup->addr()			= msg.orig_addr();
+ 		new_dup->seq_num()		= msg.msg_seq_num();
+ 		new_dup->time()			= now + OLSR_DUP_HOLD_TIME;
+ 		new_dup->retransmitted()	= retransmitted;
+ 		new_dup->iface_list().push_back(local_iface);
+ 		add_dup_tuple(new_dup);
+ 		// Schedules dup tuple deletion
+ 		OLSR_DupTupleTimer* dup_timer =
+ 			new OLSR_DupTupleTimer(this, new_dup);
+ 		dup_timer->resched(DELAY(new_dup->time()));
+ 	}
+ }
+ 
+ ///
+ /// \brief Forwards a data packet to the appropiate next hop indicated by the routing table.
+ ///
+ /// \param p the packet which must be forwarded.
+ ///
+ void
+ OLSR::forward_data(Packet* p) {
+ 	struct hdr_cmn* ch	= HDR_CMN(p);
+ 	struct hdr_ip* ih	= HDR_IP(p);
+ 
+ 	if (ch->direction() == hdr_cmn::UP &&
+ 		((u_int32_t)ih->daddr() == IP_BROADCAST || ih->daddr() == ra_addr())) {
+ 		dmux_->recv(p, 0);
+ 		return;
+ 	}
+ 	else {
+ 		ch->direction()	= hdr_cmn::DOWN;
+ 		ch->addr_type()	= NS_AF_INET;
+ 		if ((u_int32_t)ih->daddr() == IP_BROADCAST)
+ 			ch->next_hop()	= IP_BROADCAST;
+ 		else {
+ 			OLSR_rt_entry* entry = rtable_.lookup(ih->daddr());
+ 			if (entry == NULL) {
+ 				debug("%f: Node %d can not forward a packet destined to %d\n",
+ 					CURRENT_TIME,
+ 					OLSR::node_id(ra_addr()),
+ 					OLSR::node_id(ih->daddr()));
+ 				drop(p, DROP_RTR_NO_ROUTE);
+ 				return;
+ 			}
+ 			else {
+ 				entry = rtable_.find_send_entry(entry);
+ 				assert(entry != NULL);
+ 				ch->next_hop() = entry->next_addr();
+ 				if (use_mac()) {
+ 					ch->xmit_failure_	= olsr_mac_failed_callback;
+ 					ch->xmit_failure_data_	= (void*)this;
+ 				}
+ 			}
+ 		}
+ 
+ 		Scheduler::instance().schedule(target_, p, 0.0);
+ 	}
+ }
+ 
+ ///
+ /// \brief Enques an %OLSR message which will be sent with a delay of (0, delay].
+ ///
+ /// This buffering system is used in order to piggyback several %OLSR messages in
+ /// a same %OLSR packet.
+ ///
+ /// \param msg the %OLSR message which must be sent.
+ /// \param delay maximum delay the %OLSR message is going to be buffered.
+ ///
+ void
+ OLSR::enque_msg(OLSR_msg& msg, double delay) {
+ 	assert(delay >= 0);
+ 	
+ 	msgs_.push_back(msg);
+ 	OLSR_MsgTimer* timer = new OLSR_MsgTimer(this);
+ 	timer->resched(delay);
+ }
+ 
+ ///
+ /// \brief Creates as many %OLSR packets as needed in order to send all buffered
+ /// %OLSR messages.
+ ///
+ void
+ OLSR::send_pkt() {
+ 	int num_msgs = msgs_.size();
+ 	if (num_msgs == 0)
+ 		return;
+ 	
+ 	// Calculates the number of needed packets
+ 	int num_pkts = (num_msgs%OLSR_MAX_MSGS == 0) ? num_msgs/OLSR_MAX_MSGS :
+ 		(num_msgs/OLSR_MAX_MSGS + 1);
+ 	
+ 	for (int i = 0; i < num_pkts; i++) {
+ 		Packet* p		= allocpkt();
+ 		struct hdr_cmn* ch	= HDR_CMN(p);
+ 		struct hdr_ip* ih	= HDR_IP(p);
+ 		OLSR_pkt* op		= PKT_OLSR(p);
+ 		
+ 		op->pkt_len()		= OLSR_PKT_HDR_SIZE;
+ 		op->pkt_seq_num()	= pkt_seq();
+ 	
+ 		int j = 0;
+ 		for (std::vector<OLSR_msg>::iterator it = msgs_.begin(); it != msgs_.end(); it++) {
+ 			if (j == OLSR_MAX_MSGS)
+ 				break;
+ 			
+ 			op->pkt_body_[j++]	= *it;
+ 			op->count		= j;
+ 			op->pkt_len()		+= (*it).size();
+ 			
+ 			it = msgs_.erase(it);
+ 			it--;
+ 		}
+ 	
+ 		ch->ptype()		= PT_OLSR;
+ 		ch->direction()		= hdr_cmn::DOWN;
+ 		ch->size()		= IP_HDR_LEN + UDP_HDR_LEN + op->pkt_len();
+ 		ch->error()		= 0;
+ 		ch->next_hop()		= IP_BROADCAST;
+ 		ch->addr_type()		= NS_AF_INET;
+ 		if (use_mac()) {
+ 			ch->xmit_failure_	= olsr_mac_failed_callback;
+ 			ch->xmit_failure_data_	= (void*)this;
+ 		}
+ 
+ 		ih->saddr()	= ra_addr();
+ 		ih->daddr()	= IP_BROADCAST;
+ 		ih->sport()	= RT_PORT;
+ 		ih->dport()	= RT_PORT;
+ 		ih->ttl()	= IP_DEF_TTL;
+ 		
+ 		Scheduler::instance().schedule(target_, p, 0.0);
+ 	}
+ }
+ 
+ ///
+ /// \brief Creates a new %OLSR HELLO message which is buffered for being sent later on.
+ ///
+ void
+ OLSR::send_hello() {
+ 	OLSR_msg msg;
+ 	double now		= CURRENT_TIME;
+ 	msg.msg_type()		= OLSR_HELLO_MSG;
+ 	msg.vtime()		= OLSR::seconds_to_emf(OLSR_NEIGHB_HOLD_TIME);
+ 	msg.orig_addr()		= ra_addr();
+ 	msg.ttl()		= 1;
+ 	msg.hop_count()		= 0;
+ 	msg.msg_seq_num()	= msg_seq();
+ 	
+ 	msg.hello().reserved()		= 0;
+ 	msg.hello().htime()		= OLSR::seconds_to_emf(hello_ival());
+ 	msg.hello().willingness()	= willingness();
+ 	msg.hello().count		= 0;
+ 	
+ 	map<u_int8_t, int> linkcodes_count;
+ 	for (linkset_t::iterator it = linkset().begin(); it != linkset().end(); it++) {
+ 		OLSR_link_tuple* link_tuple = *it;
+ 		if (link_tuple->local_iface_addr() == ra_addr() && link_tuple->time() >= now) {
+ 			u_int8_t link_type, nb_type, link_code;
+ 			
+ 			// Establishes link type
+ 			if (use_mac() && link_tuple->lost_time() >= now)
+ 				link_type = OLSR_LOST_LINK;
+ 			else if (link_tuple->sym_time() >= now)
+ 				link_type = OLSR_SYM_LINK;
+ 			else if (link_tuple->asym_time() >= now)
+ 				link_type = OLSR_ASYM_LINK;
+ 			else
+ 				link_type = OLSR_LOST_LINK;
+ 			// Establishes neighbor type.
+ 			if (state_.find_mpr_addr(get_main_addr(link_tuple->nb_iface_addr())))
+ 				nb_type = OLSR_MPR_NEIGH;
+ 			else {
+ 				bool ok = false;
+ 				for (nbset_t::iterator nb_it = nbset().begin();
+ 					nb_it != nbset().end();
+ 					nb_it++) {
+ 					OLSR_nb_tuple* nb_tuple = *nb_it;
+ 					if (nb_tuple->nb_main_addr() == link_tuple->nb_iface_addr()) {
+ 						if (nb_tuple->status() == OLSR_STATUS_SYM)
+ 							nb_type = OLSR_SYM_NEIGH;
+ 						else if (nb_tuple->status() == OLSR_STATUS_NOT_SYM)
+ 							nb_type = OLSR_NOT_NEIGH;
+ 						else {
+ 							fprintf(stderr, "There is a neighbor tuple"
+ 								" with an unknown status!\n");
+ 							exit(1);
+ 						}
+ 						ok = true;
+ 						break;
+ 					}
+ 				}
+ 				if (!ok) {
+ 					fprintf(stderr, "Link tuple has no corresponding"
+ 						" Neighbor tuple\n");
+ 					exit(1);
+ 				}
+ 			}
+ 
+ 			int count = msg.hello().count;
+ 			link_code = (link_type & 0x03) | ((nb_type << 2) & 0x0f);
+ 			map<u_int8_t, int>::iterator pos = linkcodes_count.find(link_code);
+ 			if (pos == linkcodes_count.end()) {
+ 				linkcodes_count[link_code] = count;
+ 				assert(count >= 0 && count < OLSR_MAX_HELLOS);
+ 				msg.hello().hello_msg(count).count = 0;
+ 				msg.hello().hello_msg(count).link_code() = link_code;
+ 				msg.hello().hello_msg(count).reserved() = 0;
+ 				msg.hello().count++;
+ 			}
+ 			else
+ 				count = (*pos).second;
+ 			
+ 			int i = msg.hello().hello_msg(count).count;
+ 			assert(count >= 0 && count < OLSR_MAX_HELLOS);
+ 			assert(i >= 0 && i < OLSR_MAX_ADDRS);
+ 			
+ 			msg.hello().hello_msg(count).nb_iface_addr(i) =
+ 				link_tuple->nb_iface_addr();
+ 			msg.hello().hello_msg(count).count++;
+ 			msg.hello().hello_msg(count).link_msg_size() =
+ 				msg.hello().hello_msg(count).size();
+ 		}
+ 	}
+ 	
+ 	msg.msg_size() = msg.size();
+ 	
+ 	enque_msg(msg, JITTER);
+ }
+ 
+ ///
+ /// \brief Creates a new %OLSR TC message which is buffered for being sent later on.
+ ///
+ void
+ OLSR::send_tc() {
+ 	OLSR_msg msg;
+ 	msg.msg_type()		= OLSR_TC_MSG;
+ 	msg.vtime()		= OLSR::seconds_to_emf(OLSR_TOP_HOLD_TIME);
+ 	msg.orig_addr()		= ra_addr();
+ 	msg.ttl()		= 255;
+ 	msg.hop_count()		= 0;
+ 	msg.msg_seq_num()	= msg_seq();
+ 	
+ 	msg.tc().ansn()		= ansn_;
+ 	msg.tc().reserved()	= 0;
+ 	msg.tc().count		= 0;
+ 	
+ 	for (mprselset_t::iterator it = mprselset().begin(); it != mprselset().end(); it++) {
+ 		OLSR_mprsel_tuple* mprsel_tuple = *it;
+ 		int count = msg.tc().count;
+ 
+ 		assert(count >= 0 && count < OLSR_MAX_ADDRS);
+ 		msg.tc().nb_main_addr(count) = mprsel_tuple->main_addr();
+ 		msg.tc().count++;
+ 	}
+ 
+ 	msg.msg_size()		= msg.size();
+ 	
+ 	enque_msg(msg, JITTER);
+ }
+ 
+ ///
+ /// \brief Creates a new %OLSR MID message which is buffered for being sent later on.
+ /// \warning This message is never invoked because there is no support for multiple interfaces.
+ ///
+ void
+ OLSR::send_mid() {
+ 	OLSR_msg msg;
+ 	msg.msg_type()		= OLSR_MID_MSG;
+ 	msg.vtime()		= OLSR::seconds_to_emf(OLSR_MID_HOLD_TIME);
+ 	msg.orig_addr()		= ra_addr();
+ 	msg.ttl()		= 255;
+ 	msg.hop_count()		= 0;
+ 	msg.msg_seq_num()	= msg_seq();
+ 	
+ 	msg.mid().count		= 0;
+ 	//foreach iface in this_node do
+ 	//	msg.mid().iface_addr(i) = iface
+ 	//	msg.mid().count++
+ 	//done
+ 	
+ 	msg.msg_size()		= msg.size();
+ 	
+ 	enque_msg(msg, JITTER);
+ }
+ 
+ ///
+ /// \brief	Updates Link Set according to a new received HELLO message (following RFC 3626
+ ///		specification). Neighbor Set is also updated if needed.
+ ///
+ /// \param msg the OLSR message which contains the HELLO message.
+ /// \param receiver_iface the address of the interface where the message was received from.
+ /// \param sender_iface the address of the interface where the message was sent from.
+ ///
+ void
+ OLSR::link_sensing(OLSR_msg& msg, nsaddr_t receiver_iface, nsaddr_t sender_iface) {
+ 	OLSR_hello& hello	= msg.hello();
+ 	double now		= CURRENT_TIME;
+ 	bool updated		= false;
+ 	bool created		= false;
+ 	
+ 	OLSR_link_tuple* link_tuple = state_.find_link_tuple(sender_iface);
+ 	if (link_tuple == NULL) {
+ 		// We have to create a new tuple
+ 		link_tuple = new OLSR_link_tuple;
+ 		link_tuple->nb_iface_addr()	= sender_iface;
+ 		link_tuple->local_iface_addr()	= receiver_iface;
+ 		link_tuple->sym_time()		= now - 1;
+ 		link_tuple->lost_time()		= 0.0;
+ 		link_tuple->time()		= now + OLSR::emf_to_seconds(msg.vtime());
+ 		add_link_tuple(link_tuple, hello.willingness());
+ 		created = true;
+ 	}
+ 	else
+ 		updated = true;
+ 	
+  	link_tuple->asym_time() = now + OLSR::emf_to_seconds(msg.vtime());
+ 	assert(hello.count >= 0 && hello.count <= OLSR_MAX_HELLOS);
+ 	for (int i = 0; i < hello.count; i++) {
+ 		OLSR_hello_msg& hello_msg = hello.hello_msg(i);
+ 		int lt = hello_msg.link_code() & 0x03;
+ 		int nt = hello_msg.link_code() >> 2;
+ 		
+ 		// We must not process invalid advertised links
+ 		if ((lt == OLSR_SYM_LINK && nt == OLSR_NOT_NEIGH) ||
+ 			(nt != OLSR_SYM_NEIGH && nt != OLSR_MPR_NEIGH
+ 			&& nt != OLSR_NOT_NEIGH))
+ 			continue;
+ 		
+ 		assert(hello_msg.count >= 0 && hello_msg.count <= OLSR_MAX_ADDRS);
+ 		for (int j = 0; j < hello_msg.count; j++) {
+ 			if (hello_msg.nb_iface_addr(j) == receiver_iface) {
+ 				if (lt == OLSR_LOST_LINK) {
+ 					link_tuple->sym_time() = now - 1;
+ 					updated = true;
+ 				}
+ 				else if (lt == OLSR_SYM_LINK || lt == OLSR_ASYM_LINK) {
+ 					link_tuple->sym_time()	=
+ 						now + OLSR::emf_to_seconds(msg.vtime());
+ 					link_tuple->time()	=
+ 						link_tuple->sym_time() + OLSR_NEIGHB_HOLD_TIME;
+ 					link_tuple->lost_time()	= 0.0;
+ 					updated = true;
+ 				}
+ 				break;
+ 			}
+ 		}
+ 		
+ 	}
+ 	link_tuple->time() = MAX(link_tuple->time(), link_tuple->asym_time());
+ 	
+ 	if (updated)
+ 		updated_link_tuple(link_tuple);
+ 	
+ 	// Schedules link tuple deletion
+ 	if (created && link_tuple != NULL) {
+ 		OLSR_LinkTupleTimer* link_timer =
+ 			new OLSR_LinkTupleTimer(this, link_tuple);
+ 		link_timer->resched(DELAY(MIN(link_tuple->time(), link_tuple->sym_time())));
+ 	}
+ }
+ 
+ ///
+ /// \brief	Updates the Neighbor Set according to the information contained in a new received
+ ///		HELLO message (following RFC 3626).
+ ///
+ /// \param msg the %OLSR message which contains the HELLO message.
+ ///
+ void
+ OLSR::populate_nbset(OLSR_msg& msg) {
+ 	OLSR_hello& hello = msg.hello();
+ 	
+ 	OLSR_nb_tuple* nb_tuple = state_.find_nb_tuple(msg.orig_addr());
+ 	if (nb_tuple != NULL)
+ 		nb_tuple->willingness() = hello.willingness();
+ }
+ 
+ ///
+ /// \brief	Updates the 2-hop Neighbor Set according to the information contained in a new
+ ///		received HELLO message (following RFC 3626).
+ ///
+ /// \param msg the %OLSR message which contains the HELLO message.
+ ///
+ void
+ OLSR::populate_nb2hopset(OLSR_msg& msg) {
+ 	double now		= CURRENT_TIME;
+ 	OLSR_hello& hello	= msg.hello();
+ 	
+ 	for (linkset_t::iterator it_lt = linkset().begin(); it_lt != linkset().end(); it_lt++) {
+ 		OLSR_link_tuple* link_tuple = *it_lt;
+ 		if (get_main_addr(link_tuple->nb_iface_addr()) == msg.orig_addr()) {
+ 			if (link_tuple->sym_time() >= now) {
+ 				assert(hello.count >= 0 && hello.count <= OLSR_MAX_HELLOS);
+ 				for (int i = 0; i < hello.count; i++) {
+ 					OLSR_hello_msg& hello_msg = hello.hello_msg(i);
+ 					int nt = hello_msg.link_code() >> 2;
+ 					assert(hello_msg.count >= 0 &&
+ 						hello_msg.count <= OLSR_MAX_ADDRS);
+ 					
+ 					for (int j = 0; j < hello_msg.count; j++) {
+ 						nsaddr_t nb2hop_addr = hello_msg.nb_iface_addr(j);
+ 						if (nt == OLSR_SYM_NEIGH || nt == OLSR_MPR_NEIGH) {
+ 							// if the main address of the 2-hop
+ 							// neighbor address = main address of
+ 							// the receiving node: silently
+ 							// discard the 2-hop neighbor address
+ 							if (nb2hop_addr != ra_addr()) {
+ 								// Otherwise, a 2-hop tuple is created
+ 								OLSR_nb2hop_tuple* nb2hop_tuple =
+ 									state_.find_nb2hop_tuple(msg.orig_addr(), nb2hop_addr);
+ 								if (nb2hop_tuple == NULL) {
+ 									nb2hop_tuple =
+ 										new OLSR_nb2hop_tuple;
+ 									nb2hop_tuple->nb_main_addr() =
+ 										msg.orig_addr();
+ 									nb2hop_tuple->nb2hop_addr() =
+ 										nb2hop_addr;
+ 									add_nb2hop_tuple(nb2hop_tuple);
+ 									nb2hop_tuple->time() =
+ 										now + OLSR::emf_to_seconds(msg.vtime());
+ 									// Schedules nb2hop tuple
+ 									// deletion
+ 									OLSR_Nb2hopTupleTimer* nb2hop_timer =
+ 										new OLSR_Nb2hopTupleTimer(this, nb2hop_tuple);
+ 									nb2hop_timer->resched(DELAY(nb2hop_tuple->time()));
+ 								}
+ 								else {
+ 									nb2hop_tuple->time() =
+ 										now + OLSR::emf_to_seconds(msg.vtime());
+ 								}
+ 								
+ 							}
+ 						}
+ 						else if (nt == OLSR_NOT_NEIGH) {
+ 							// For each 2-hop node listed in the HELLO
+ 							// message with Neighbor Type equal to
+ 							// NOT_NEIGH all 2-hop tuples where:
+ 							// N_neighbor_main_addr == Originator
+ 							// Address AND N_2hop_addr  == main address
+ 							// of the 2-hop neighbor are deleted.
+ 							state_.erase_nb2hop_tuples(msg.orig_addr(),
+ 								nb2hop_addr);
+ 						}
+ 					}
+ 				}
+ 			}
+ 		}
+ 	}
+ }
+ 
+ ///
+ /// \brief	Updates the MPR Selector Set according to the information contained in a new
+ ///		received HELLO message (following RFC 3626).
+ ///
+ /// \param msg the %OLSR message which contains the HELLO message.
+ ///
+ void
+ OLSR::populate_mprselset(OLSR_msg& msg) {
+ 	double now		= CURRENT_TIME;
+ 	OLSR_hello& hello	= msg.hello();
+ 	
+ 	assert(hello.count >= 0 && hello.count <= OLSR_MAX_HELLOS);
+ 	for (int i = 0; i < hello.count; i++) {
+ 		OLSR_hello_msg& hello_msg = hello.hello_msg(i);
+ 		int nt = hello_msg.link_code() >> 2;
+ 		if (nt == OLSR_MPR_NEIGH) {
+ 			assert(hello_msg.count >= 0 && hello_msg.count <= OLSR_MAX_ADDRS);
+ 			for (int j = 0; j < hello_msg.count; j++) {
+ 				if (hello_msg.nb_iface_addr(j) == ra_addr()) {
+ 					// We must create a new entry into the mpr selector set
+ 					OLSR_mprsel_tuple* mprsel_tuple =
+ 						state_.find_mprsel_tuple(msg.orig_addr());
+ 					if (mprsel_tuple == NULL) {
+ 						mprsel_tuple = new OLSR_mprsel_tuple;
+ 						mprsel_tuple->main_addr() = msg.orig_addr();
+ 						mprsel_tuple->time() =
+ 							now + OLSR::emf_to_seconds(msg.vtime());
+ 						add_mprsel_tuple(mprsel_tuple);
+ 						// Schedules mpr selector tuple deletion
+ 						OLSR_MprSelTupleTimer* mprsel_timer =
+ 							new OLSR_MprSelTupleTimer(this, mprsel_tuple);
+ 						mprsel_timer->resched(DELAY(mprsel_tuple->time()));
+ 					}
+ 					else
+ 						mprsel_tuple->time() =
+ 							now + OLSR::emf_to_seconds(msg.vtime());
+ 				}
+ 			}
+ 		}
+ 	}
+ }
+ 
+ ///
+ /// \brief	Drops a given packet because it couldn't be delivered to the corresponding
+ ///		destination by the MAC layer. This may cause a neighbor loss, and appropiate
+ ///		actions are then taken.
+ ///
+ /// \param p the packet which couldn't be delivered by the MAC layer.
+ ///
+ void
+ OLSR::mac_failed(Packet* p) {
+ 	double now		= CURRENT_TIME;
+ 	struct hdr_ip* ih	= HDR_IP(p);
+ 	struct hdr_cmn* ch	= HDR_CMN(p);
+ 	
+ 	debug("%f: Node %d MAC Layer detects a breakage on link to %d\n",
+ 		now,
+ 		OLSR::node_id(ra_addr()),
+ 		OLSR::node_id(ch->next_hop()));
+ 	
+ 	if ((u_int32_t)ih->daddr() == IP_BROADCAST) {
+ 		drop(p, DROP_RTR_MAC_CALLBACK);
+ 		return;
+ 	}
+ 	
+ 	OLSR_link_tuple* link_tuple = state_.find_link_tuple(ch->next_hop());
+ 	if (link_tuple != NULL) {
+ 		link_tuple->lost_time()	= now + OLSR_NEIGHB_HOLD_TIME;
+ 		link_tuple->time()	= now + OLSR_NEIGHB_HOLD_TIME;
+ 		nb_loss(link_tuple);
+ 	}
+ 	drop(p, DROP_RTR_MAC_CALLBACK);
+ }
+ 
+ ///
+ /// \brief Schedule the timer used for sending HELLO messages.
+ ///
+ void
+ OLSR::set_hello_timer() {
+ 	hello_timer_.resched((double)(hello_ival() - JITTER));
+ }
+ 
+ ///
+ /// \brief Schedule the timer used for sending TC messages.
+ ///
+ void
+ OLSR::set_tc_timer() {
+ 	tc_timer_.resched((double)(tc_ival() - JITTER));
+ }
+ 
+ ///
+ /// \brief Schedule the timer used for sending MID messages.
+ ///
+ void
+ OLSR::set_mid_timer() {
+ 	mid_timer_.resched((double)(mid_ival() - JITTER));
+ }
+ 
+ ///
+ /// \brief Performs all actions needed when a neighbor loss occurs.
+ ///
+ /// Neighbor Set, 2-hop Neighbor Set, MPR Set and MPR Selector Set are updated.
+ ///
+ /// \param tuple link tuple with the information of the link to the neighbor which has been lost.
+ ///
+ void
+ OLSR::nb_loss(OLSR_link_tuple* tuple) {
+ 	debug("%f: Node %d detects neighbor %d loss\n",
+ 		CURRENT_TIME,
+ 		OLSR::node_id(ra_addr()),
+ 		OLSR::node_id(tuple->nb_iface_addr()));
+ 	
+ 	updated_link_tuple(tuple);
+ 	state_.erase_nb2hop_tuples(get_main_addr(tuple->nb_iface_addr()));
+ 	state_.erase_mprsel_tuples(get_main_addr(tuple->nb_iface_addr()));
+ 	
+ 	mpr_computation();
+  	rtable_computation();
+ }
+ 
+ ///
+ /// \brief Adds a duplicate tuple to the Duplicate Set.
+ ///
+ /// \param tuple the duplicate tuple to be added.
+ ///
+ void
+ OLSR::add_dup_tuple(OLSR_dup_tuple* tuple) {
+ 	/*debug("%f: Node %d adds dup tuple: addr = %d seq_num = %d\n",
+ 		CURRENT_TIME,
+ 		OLSR::node_id(ra_addr()),
+ 		OLSR::node_id(tuple->addr()),
+ 		tuple->seq_num());*/
+ 	
+ 	state_.insert_dup_tuple(tuple);
+ }
+ 
+ ///
+ /// \brief Removes a duplicate tuple from the Duplicate Set.
+ ///
+ /// \param tuple the duplicate tuple to be removed.
+ ///
+ void
+ OLSR::rm_dup_tuple(OLSR_dup_tuple* tuple) {
+ 	/*debug("%f: Node %d removes dup tuple: addr = %d seq_num = %d\n",
+ 		CURRENT_TIME,
+ 		OLSR::node_id(ra_addr()),
+ 		OLSR::node_id(tuple->addr()),
+ 		tuple->seq_num());*/
+ 	
+ 	state_.erase_dup_tuple(tuple);
+ }
+ 
+ ///
+ /// \brief Adds a link tuple to the Link Set (and an associated neighbor tuple to the Neighbor Set).
+ ///
+ /// \param tuple the link tuple to be added.
+ /// \param willingness willingness of the node which is going to be inserted in the Neighbor Set.
+ ///
+ void
+ OLSR::add_link_tuple(OLSR_link_tuple* tuple, u_int8_t  willingness) {
+ 	double now = CURRENT_TIME;
+ 
+ 	debug("%f: Node %d adds link tuple: nb_addr = %d\n",
+ 		now,
+ 		OLSR::node_id(ra_addr()),
+ 		OLSR::node_id(tuple->nb_iface_addr()));
+ 
+ 	state_.insert_link_tuple(tuple);
+ 	// Creates associated neighbor tuple
+ 	OLSR_nb_tuple* nb_tuple		= new OLSR_nb_tuple;
+ 	nb_tuple->nb_main_addr()	= get_main_addr(tuple->nb_iface_addr());
+ 	nb_tuple->willingness()		= willingness;
+ 	if (tuple->sym_time() >= now)
+ 		nb_tuple->status() = OLSR_STATUS_SYM;
+ 	else
+ 		nb_tuple->status() = OLSR_STATUS_NOT_SYM;
+ 	add_nb_tuple(nb_tuple);
+ }
+ 
+ ///
+ /// \brief Removes a link tuple from the Link Set.
+ ///
+ /// \param tuple the link tuple to be removed.
+ ///
+ void
+ OLSR::rm_link_tuple(OLSR_link_tuple* tuple) {
+ 	nsaddr_t nb_addr	= get_main_addr(tuple->nb_iface_addr());
+ 	double now		= CURRENT_TIME;
+ 	
+ 	debug("%f: Node %d removes link tuple: nb_addr = %d\n",
+ 		now,
+ 		OLSR::node_id(ra_addr()),
+ 		OLSR::node_id(tuple->nb_iface_addr()));
+ 	// Prints this here cause we are not actually calling rm_nb_tuple() (efficiency stuff)
+ 	debug("%f: Node %d removes neighbor tuple: nb_addr = %d\n",
+ 		now,
+ 		OLSR::node_id(ra_addr()),
+ 		OLSR::node_id(nb_addr));
+ 
+ 	state_.erase_link_tuple(tuple);
+ 	state_.erase_nb_tuple(nb_addr);
+ }
+ 
+ ///
+ /// \brief	This function is invoked when a link tuple is updated. Its aim is to
+ ///		also update the corresponding neighbor tuple if it is needed.
+ ///
+ /// \param tuple the link tuple which has been updated.
+ ///
+ void
+ OLSR::updated_link_tuple(OLSR_link_tuple* tuple) {
+ 	double now = CURRENT_TIME;
+ 	
+ 	// Each time a link tuple changes, the associated neighbor tuple must be recomputed
+ 	OLSR_nb_tuple* nb_tuple =
+ 		state_.find_nb_tuple(get_main_addr(tuple->nb_iface_addr()));
+ 	if (nb_tuple != NULL) {
+ 		if (use_mac() && tuple->lost_time() >= now)
+ 			nb_tuple->status() = OLSR_STATUS_NOT_SYM;
+ 		else if (tuple->sym_time() >= now)
+ 			nb_tuple->status() = OLSR_STATUS_SYM;
+ 		else
+ 			nb_tuple->status() = OLSR_STATUS_NOT_SYM;
+ 	}
+ 	
+ 	debug("%f: Node %d has updated link tuple: nb_addr = %d status = %s\n",
+ 		now,
+ 		OLSR::node_id(ra_addr()),
+ 		OLSR::node_id(tuple->nb_iface_addr()),
+ 		((nb_tuple->status() == OLSR_STATUS_SYM) ? "sym" : "not_sym"));
+ }
+ 
+ ///
+ /// \brief Adds a neighbor tuple to the Neighbor Set.
+ ///
+ /// \param tuple the neighbor tuple to be added.
+ ///
+ void
+ OLSR::add_nb_tuple(OLSR_nb_tuple* tuple) {
+ 	debug("%f: Node %d adds neighbor tuple: nb_addr = %d status = %s\n",
+ 		CURRENT_TIME,
+ 		OLSR::node_id(ra_addr()),
+ 		OLSR::node_id(tuple->nb_main_addr()),
+ 		((tuple->status() == OLSR_STATUS_SYM) ? "sym" : "not_sym"));
+ 	
+ 	state_.insert_nb_tuple(tuple);
+ }
+ 
+ ///
+ /// \brief Removes a neighbor tuple from the Neighbor Set.
+ ///
+ /// \param tuple the neighbor tuple to be removed.
+ ///
+ void
+ OLSR::rm_nb_tuple(OLSR_nb_tuple* tuple) {
+ 	debug("%f: Node %d removes neighbor tuple: nb_addr = %d status = %s\n",
+ 		CURRENT_TIME,
+ 		OLSR::node_id(ra_addr()),
+ 		OLSR::node_id(tuple->nb_main_addr()),
+ 		((tuple->status() == OLSR_STATUS_SYM) ? "sym" : "not_sym"));
+ 	
+ 	state_.erase_nb_tuple(tuple);
+ }
+ 
+ ///
+ /// \brief Adds a 2-hop neighbor tuple to the 2-hop Neighbor Set.
+ ///
+ /// \param tuple the 2-hop neighbor tuple to be added.
+ ///
+ void
+ OLSR::add_nb2hop_tuple(OLSR_nb2hop_tuple* tuple) {
+ 	debug("%f: Node %d adds 2-hop neighbor tuple: nb_addr = %d nb2hop_addr = %d\n",
+ 		CURRENT_TIME,
+ 		OLSR::node_id(ra_addr()),
+ 		OLSR::node_id(tuple->nb_main_addr()),
+ 		OLSR::node_id(tuple->nb2hop_addr()));
+ 
+ 	state_.insert_nb2hop_tuple(tuple);
+ }
+ 
+ ///
+ /// \brief Removes a 2-hop neighbor tuple from the 2-hop Neighbor Set.
+ ///
+ /// \param tuple the 2-hop neighbor tuple to be removed.
+ ///
+ void
+ OLSR::rm_nb2hop_tuple(OLSR_nb2hop_tuple* tuple) {
+ 	debug("%f: Node %d removes 2-hop neighbor tuple: nb_addr = %d nb2hop_addr = %d\n",
+ 		CURRENT_TIME,
+ 		OLSR::node_id(ra_addr()),
+ 		OLSR::node_id(tuple->nb_main_addr()),
+ 		OLSR::node_id(tuple->nb2hop_addr()));
+ 
+ 	state_.erase_nb2hop_tuple(tuple);
+ }
+ 
+ ///
+ /// \brief Adds an MPR selector tuple to the MPR Selector Set.
+ ///
+ /// Advertised Neighbor Sequence Number (ANSN) is also updated.
+ ///
+ /// \param tuple the MPR selector tuple to be added.
+ ///
+ void
+ OLSR::add_mprsel_tuple(OLSR_mprsel_tuple* tuple) {
+ 	debug("%f: Node %d adds MPR selector tuple: nb_addr = %d\n",
+ 		CURRENT_TIME,
+ 		OLSR::node_id(ra_addr()),
+ 		OLSR::node_id(tuple->main_addr()));
+ 
+ 	state_.insert_mprsel_tuple(tuple);
+ 	ansn_ = (ansn_ + 1)%(OLSR_MAX_SEQ_NUM + 1);
+ }
+ 
+ ///
+ /// \brief Removes an MPR selector tuple from the MPR Selector Set.
+ ///
+ /// Advertised Neighbor Sequence Number (ANSN) is also updated.
+ ///
+ /// \param tuple the MPR selector tuple to be removed.
+ ///
+ void
+ OLSR::rm_mprsel_tuple(OLSR_mprsel_tuple* tuple) {
+ 	debug("%f: Node %d removes MPR selector tuple: nb_addr = %d\n",
+ 		CURRENT_TIME,
+ 		OLSR::node_id(ra_addr()),
+ 		OLSR::node_id(tuple->main_addr()));
+ 
+ 	state_.erase_mprsel_tuple(tuple);
+ 	ansn_ = (ansn_ + 1)%(OLSR_MAX_SEQ_NUM + 1);
+ }
+ 
+ ///
+ /// \brief Adds a topology tuple to the Topology Set.
+ ///
+ /// \param tuple the topology tuple to be added.
+ ///
+ void
+ OLSR::add_topology_tuple(OLSR_topology_tuple* tuple) {
+ 	debug("%f: Node %d adds topology tuple: dest_addr = %d last_addr = %d seq = %d\n",
+ 		CURRENT_TIME,
+ 		OLSR::node_id(ra_addr()),
+ 		OLSR::node_id(tuple->dest_addr()),
+ 		OLSR::node_id(tuple->last_addr()),
+ 		tuple->seq());
+ 
+ 	state_.insert_topology_tuple(tuple);
+ }
+ 
+ ///
+ /// \brief Removes a topology tuple from the Topology Set.
+ ///
+ /// \param tuple the topology tuple to be removed.
+ ///
+ void
+ OLSR::rm_topology_tuple(OLSR_topology_tuple* tuple) {
+ 	debug("%f: Node %d removes topology tuple: dest_addr = %d last_addr = %d seq = %d\n",
+ 		CURRENT_TIME,
+ 		OLSR::node_id(ra_addr()),
+ 		OLSR::node_id(tuple->dest_addr()),
+ 		OLSR::node_id(tuple->last_addr()),
+ 		tuple->seq());
+ 
+ 	state_.erase_topology_tuple(tuple);
+ }
+ 
+ ///
+ /// \brief Adds an interface association tuple to the Interface Association Set.
+ ///
+ /// \param tuple the interface association tuple to be added.
+ ///
+ void
+ OLSR::add_ifaceassoc_tuple(OLSR_iface_assoc_tuple* tuple) {
+ 	debug("%f: Node %d adds iface association tuple: main_addr = %d iface_addr = %d\n",
+ 		CURRENT_TIME,
+ 		OLSR::node_id(ra_addr()),
+ 		OLSR::node_id(tuple->main_addr()),
+ 		OLSR::node_id(tuple->iface_addr()));
+ 
+ 	state_.insert_ifaceassoc_tuple(tuple);
+ }
+ 
+ ///
+ /// \brief Removes an interface association tuple from the Interface Association Set.
+ ///
+ /// \param tuple the interface association tuple to be removed.
+ ///
+ void
+ OLSR::rm_ifaceassoc_tuple(OLSR_iface_assoc_tuple* tuple) {
+ 	debug("%f: Node %d removes iface association tuple: main_addr = %d iface_addr = %d\n",
+ 		CURRENT_TIME,
+ 		OLSR::node_id(ra_addr()),
+ 		OLSR::node_id(tuple->main_addr()),
+ 		OLSR::node_id(tuple->iface_addr()));
+ 
+ 	state_.erase_ifaceassoc_tuple(tuple);
+ }
+ 
+ ///
+ /// \brief Gets the main address associated with a given interface address.
+ ///
+ /// \param iface_addr the interface address.
+ /// \return the corresponding main address.
+ ///
+ nsaddr_t
+ OLSR::get_main_addr(nsaddr_t iface_addr) {
+ 	OLSR_iface_assoc_tuple* tuple =
+ 		state_.find_ifaceassoc_tuple(iface_addr);
+ 	
+ 	if (tuple != NULL)
+ 		return tuple->main_addr();
+ 	return iface_addr;
+ }
+ 
+ ///
+ /// \brief Determines which sequence number is bigger (as it is defined in RFC 3626).
+ ///
+ /// \param s1 a sequence number.
+ /// \param s2 a sequence number.
+ /// \return true if s1 > s2, false in other case.
+ ///
+ bool
+ OLSR::seq_num_bigger_than(u_int16_t s1, u_int16_t s2) {
+ 	return (s1 > s2 && s1-s2 <= OLSR_MAX_SEQ_NUM/2)
+ 		|| (s2 > s1 && s2-s1 > OLSR_MAX_SEQ_NUM/2);
+ }
+ 
+ ///
+ /// \brief This auxiliary function (defined in RFC 3626) is used for calculating the MPR Set.
+ ///
+ /// \param tuple the neighbor tuple which has the main address of the node we are going to calculate its degree to.
+ /// \return the degree of the node.
+ ///
+ int
+ OLSR::degree(OLSR_nb_tuple* tuple) {
+ 	int degree = 0;
+ 	for (nb2hopset_t::iterator it = nb2hopset().begin(); it != nb2hopset().end(); it++) {
+ 		OLSR_nb2hop_tuple* nb2hop_tuple = *it;
+ 		if (nb2hop_tuple->nb_main_addr() == tuple->nb_main_addr()) {
+ 			OLSR_nb_tuple* nb_tuple =
+ 				state_.find_nb_tuple(nb2hop_tuple->nb_main_addr());
+ 			if (nb_tuple == NULL)
+ 				degree++;
+ 		}
+ 	}
+ 	return degree;
+ }
+ 
+ ///
+ /// \brief Frees the memory of the timers which have expired but haven't been released yet.
+ ///
+ void
+ OLSR::release_expired_timers() {
+ 	for (std::vector<TimerHandler*>::iterator it = expired_timers_.begin();
+ 		it != expired_timers_.end();
+ 		it++) {
+ 		delete *it;
+ 		it = expired_timers_.erase(it);
+ 		it--;
+ 	}
+ }
+ 
+ ///
+ /// \brief Converts a decimal number of seconds to the mantissa/exponent format.
+ ///
+ /// \param seconds decimal number of seconds we want to convert.
+ /// \return the number of seconds in mantissa/exponent format.
+ ///
+ u_int8_t
+ OLSR::seconds_to_emf(double seconds) {
+ 	// This implementation has been taken from unik-olsrd-0.4.5 (mantissa.c),
+ 	// licensed under the GNU Public License (GPL)
+ 	
+ 	int a, b = 0;
+  	while (seconds/OLSR_C >= pow((double)2, (double)b))
+ 		b++;
+ 	b--;
+ 	
+ 	if (b < 0) {
+ 		a = 1;
+ 		b = 0;
+ 	}
+ 	else if (b > 15) {
+ 		a = 15;
+ 		b = 15;
+ 	}
+ 	else {
+ 		a = (int)(16*((double)seconds/(OLSR_C*(double)pow(2, b))-1));
+ 		while (a >= 16) {
+ 			a -= 16;
+ 			b++;
+ 		}
+ 	}
+ 	
+ 	return (u_int8_t)(a*16+b);
+ }
+ 
+ ///
+ /// \brief Converts a number of seconds in the mantissa/exponent format to a decimal number.
+ ///
+ /// \param olsr_format number of seconds in mantissa/exponent format.
+ /// \return the decimal number of seconds.
+ ///
+ double
+ OLSR::emf_to_seconds(u_int8_t olsr_format) {
+ 	// This implementation has been taken from unik-olsrd-0.4.5 (mantissa.c),
+ 	// licensed under the GNU Public License (GPL)
+ 	int a = olsr_format >> 4;
+ 	int b = olsr_format - a*16;
+ 	return (double)(OLSR_C*(1+(double)a/16)*(double)pow(2,b));
+ }
+ 
+ ///
+ /// \brief Returns the identifier of a node given the address of the attached OLSR agent.
+ ///
+ /// \param addr the address of the OLSR routing agent.
+ /// \return the identifier of the node.
+ ///
+ int
+ OLSR::node_id(nsaddr_t addr) {
+ 	// Preventing a bad use for this function
+         if ((u_int32_t)addr == IP_BROADCAST)
+ 		return addr;
+ 	// Getting node id
+ 	Node* node = Node::get_node_by_address(addr);
+ 	assert(node != NULL);
+ 	return node->nodeid();
+ }
diff --new-file --recursive --context=3 --minimal -x '*.[ao]' -x '*.nam' -x '*.tr' -x '*.cache' -x core -x '*.core' ns-2.27-ORIG/olsr/OLSR.h ns-2.27/olsr/OLSR.h
*** ns-2.27-ORIG/olsr/OLSR.h	1970-01-01 01:00:00.000000000 +0100
--- ns-2.27/olsr/OLSR.h	2005-03-11 11:38:59.000000000 +0100
***************
*** 0 ****
--- 1,595 ----
+ /***************************************************************************
+  *   Copyright (C) 2004 by Francisco J. Ros                                *
+  *   fjrm@dif.um.es                                                        *
+  *                                                                         *
+  *   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.             *
+  ***************************************************************************/
+ 
+ /*!
+  * \mainpage
+  *
+  * \author Francisco J. Ros
+  * \date 11 March, 2005
+  *
+  * \section feat Features
+  *
+  * <p>This software implements base specification of <a href="http://www.ietf.org/rfc/rfc3626.txt">
+  *    %OLSR protocol</a> for <a href="http://www.isi.edu/nsnam/ns/">NS2 network simulator</a>.
+  *    It has been developed at the <a href="http://www.um.es/">University of Murcia</a>
+  *    (Spain) by <a href="http://ants.dif.um.es/~fjrm/">Francisco J. Ros</a>, and it is released
+  *    under the <a href="http://www.gnu.org/copyleft/gpl.html">GNU General Public License</a>.</p>
+  *
+  * <p>There are available patches for the latest releases of <strong>NS2</strong>, namely for
+  *    versions 2.27 and 2.28. Tests have been performed on a Debian GNU/Linux system, but the
+  *    code should work on all platforms supported by <strong>NS2</strong>.</p>
+  *
+  * <p>Here is a summary of software's main features:</p>
+  *
+  * <ul>
+  *  <li>Compliant with core-OLSR (but the use of multiple interfaces which is currently
+  *      not supported by <strong>NS2</strong>) as it is documented in RFC 3626.</li>
+  *
+  *  <li>Support for MAC layer feedback as described in RFC 3626.</li>
+  *
+  *  <li>Source code follows <strong>NS2</strong> coding style.</li>
+  *
+  *  <li>Highly configurable from TCL scripts, i.e., without the need of
+  *      recompiling the whole simulator. You can:</li>
+  *
+  *  <ul>
+  *    <li>Activate/deactivate debug mode.</li>
+  *
+  *    <li>Change the interval at which every message type is sent (on a
+  *        per-node basis).</li>
+  *
+  *    <li>Change a node's willingness for forwarding data packets on
+  *        behalf of other nodes (on a per-node basis).</li>
+  *
+  *    <li>Print whatever data structure managed by a node at a certain
+  *        time (on a per-node basis).</li>
+  *  </ul>
+  *
+  * </ul>
+  *
+  * \section inst Installing
+  *
+  * <p>In this section we are supposing that you have installed a version of <strong>NS</strong>
+  *    (2.27/2.28) which is properly running. Let's call <em>$NS_ROOT</em> the upper directory
+  *    where <strong>NS</strong> is installed. For instance, if you download and install
+  *    <em>ns-allinone-2.28.tar.gz</em> in your home directory, then <em>$NS_ROOT</em> is
+  *    <em>~/ns-allinone-2.28</em>. Besides let's call <em>$VERSION</em> to the version of
+  *    your installed <strong>NS</strong> software.</p>
+  *
+  * <p>There are two options for installing <strong>UM-OLSR</strong>, either applying a patch
+  *    or copying each source file to the appropiate place:</p>
+  *
+  * <ul>
+  *  <li>Applying patches</li>
+  *
+  *  <ol>
+  *   <li>Download <strong>UM-OLSR</strong> patch for <strong>NS</strong>
+  *       <a href="http://ants.dif.um.es/masimum/um-olsr/um-olsr_ns-2.27_v0.8.7.patch">2.27</a> or
+  *       <a href="http://ants.dif.um.es/masimum/um-olsr/um-olsr_ns-2.28_v0.8.7.patch">2.28</a>
+  *       version. Let's call <em>$PATCH</em> to the downloaded file.</li>
+  *
+  *   <li><tt># cp $PATCH $NS_ROOT && cd $NS_ROOT</tt></li>
+  *
+  *   <li><tt># patch -p0 \< $PATCH</tt></li>
+  *
+  *   <li><tt># cd ns-$VERSION</tt></li>
+  *
+  *   <li><tt># make</tt></li>
+  *  </ol>
+  *
+  *  <li>Copying files</li>
+  *
+  *  <ol>
+  *   <li>Download <strong>UM-OLSR</strong> code for <strong>NS</strong>
+  *       <a href="http://ants.dif.um.es/masimum/um-olsr/um-olsr_ns-2.27_v0.8.7.tar.gz">2.27</a> or
+  *       <a href="http://ants.dif.um.es/masimum/um-olsr/um-olsr_ns-2.28_v0.8.7.tar.gz">2.28</a>
+  *       version. Let's call <em>$FILE</em> to the downloaded file.</li>
+  *
+  *   <li><tt># tar zxvf $FILE</tt></li>
+  *
+  *   <li>Under the recently created directory are several files which must be copied
+  *       to the corresponding places in <em>$NS_ROOT</em>/ns-<em>$VERSION</em>.</li>
+  *
+  *   <li><tt># cd $NS_ROOT/ns-$VERSION</tt></li>
+  *
+  *   <li><tt># make</tt></li>
+  *  </ol>
+  *
+  * \section howto How to Use It
+  *
+  * <p><strong>UM-OLSR</strong> allows <strong>NS2</strong> users to use %OLSR protocol like
+  *    any other MANET routing protocol available in the official release.</p>
+  *
+  * <p><a href="http://ants.dif.um.es/masimum/um-olsr/olsr_example.tcl">This example</a>
+  * explores main features of <strong>UM-OLSR</strong> and shows how to perform simulations
+  * with this routing protocol. If you can't understand the content of the file, then you
+  * should start reading <a href="http://www.isi.edu/nsnam/ns/ns-documentation.html">NS
+  * Manual</a> or any of the available tutorials for beginners (see
+  * <a href="http://www.isi.edu/nsnam/ns/">NS web page</a>). The simulation consists of a
+  * simple TCL script which defines five mobile nodes (with no motion) and an UDP connection
+  * between two of them.</p>
+  *
+  * \section traces Understanding Trace Format
+  *
+  * <strong>UM-OLSR</strong> supports all trace formats defined in <strong>NS2</strong>,
+  * i.e, old, new and tagged trace formats. In all cases it is shown the same information
+  * when an OLSR packet is sent, received, dropped or forwarded:
+  *
+  * <ul>
+  *  <li>Number of messages this packet contains.</li>
+  *  <li>Packet sequence number.</li>
+  *  <li>For each message is also shown:</li>
+  *   <ul>
+  *    <li>Message type ("HELLO", "TC" or "UNKNOWN").</li>
+  *    <li>Originator address.</li>
+  *    <li>Hop count.</li>
+  *    <li>Message sequence number.</li>
+  *   </ul>
+  * </ul>
+  *
+  * If you need a more detailed description of trace format, see <em>CMUTrace::format_olsr()</em>
+  * function in <em>$NS_ROOT/ns-$VERSION/trace/cmu-trace.cc</em> or the result of the above mentioned
+  * <a href="http://ants.dif.um.es/masimum/um-olsr/olsr_example.tcl">example</a>.
+  */
+ 
+ ///
+ /// \file	OLSR.h
+ /// \brief	Header file for OLSR agent and related classes.
+ ///
+ /// Here are defined all timers used by OLSR, including those for managing internal
+ /// state and those for sending messages. Class OLSR is also defined, therefore this
+ /// file has signatures for the most important methods. Lots of constants are also
+ /// defined.
+ ///
+ 
+ #ifndef __OLSR_h__
+ #define __OLSR_h__
+ 
+ #include <olsr/OLSR_pkt.h>
+ #include <olsr/OLSR_state.h>
+ #include <olsr/OLSR_rtable.h>
+ #include <olsr/OLSR_repositories.h>
+ #include <trace.h>
+ #include <classifier-port.h>
+ #include <agent.h>
+ #include <packet.h>
+ #include <timer-handler.h>
+ #include <random.h>
+ #include <vector>
+ 
+ /********** Useful macros **********/
+ 
+ /// Returns maximum of two numbers.
+ #ifndef MAX
+ #define	MAX(a, b) (((a) > (b)) ? (a) : (b))
+ #endif
+ 
+ /// Returns minimum of two numbers.
+ #ifndef MIN
+ #define	MIN(a, b) (((a) < (b)) ? (a) : (b))
+ #endif
+ 
+ /// Defines NULL as zero, used for pointers.
+ #ifndef NULL
+ #define NULL 0
+ #endif
+ 
+ /// Gets current time from the scheduler.
+ #define CURRENT_TIME	Scheduler::instance().clock()
+ 
+ ///
+ /// \brief Gets the delay between a given time and the current time.
+ ///
+ /// If given time is previous to the current one, then this macro returns
+ /// a number close to 0. This is used for scheduling events at a certain moment.
+ ///
+ #define DELAY(time) (((time) < (CURRENT_TIME)) ? (0.000001) : \
+ 	(time - CURRENT_TIME + 0.000001))
+ 
+ /// Scaling factor used in RFC 3626.
+ #define OLSR_C		0.0625
+ 
+ 
+ /********** Intervals **********/
+ 
+ /// HELLO messages emission interval.
+ #define OLSR_HELLO_INTERVAL	2
+ 
+ /// TC messages emission interval.
+ #define OLSR_TC_INTERVAL	5
+ 
+ /// MID messages emission interval.
+ #define OLSR_MID_INTERVAL	OLSR_TC_INTERVAL
+ 
+ ///
+ /// \brief Period at which a node must cite every link and every neighbor.
+ ///
+ /// We only use this value in order to define OLSR_NEIGHB_HOLD_TIME.
+ ///
+ #define OLSR_REFRESH_INTERVAL	2
+ 
+ 
+ /********** Holding times **********/
+ 
+ /// Neighbor holding time.
+ #define OLSR_NEIGHB_HOLD_TIME	3*OLSR_REFRESH_INTERVAL
+ /// Top holding time.
+ #define OLSR_TOP_HOLD_TIME	3*OLSR_TC_INTERVAL
+ /// Dup holding time.
+ #define OLSR_DUP_HOLD_TIME	30
+ /// MID holding time.
+ #define OLSR_MID_HOLD_TIME	3*OLSR_MID_INTERVAL
+ 
+ 
+ /********** Link types **********/
+ 
+ /// Unspecified link type.
+ #define OLSR_UNSPEC_LINK	0
+ /// Asymmetric link type.
+ #define OLSR_ASYM_LINK		1
+ /// Symmetric link type.
+ #define OLSR_SYM_LINK		2
+ /// Lost link type.
+ #define OLSR_LOST_LINK		3
+ 
+ /********** Neighbor types **********/
+ 
+ /// Not neighbor type.
+ #define OLSR_NOT_NEIGH		0
+ /// Symmetric neighbor type.
+ #define OLSR_SYM_NEIGH		1
+ /// Asymmetric neighbor type.
+ #define OLSR_MPR_NEIGH		2
+ 
+ 
+ /********** Willingness **********/
+ 
+ /// Willingness for forwarding packets from other nodes: never.
+ #define OLSR_WILL_NEVER		0
+ /// Willingness for forwarding packets from other nodes: low.
+ #define OLSR_WILL_LOW		1
+ /// Willingness for forwarding packets from other nodes: medium.
+ #define OLSR_WILL_DEFAULT	3
+ /// Willingness for forwarding packets from other nodes: high.
+ #define OLSR_WILL_HIGH		6
+ /// Willingness for forwarding packets from other nodes: always.
+ #define OLSR_WILL_ALWAYS	7
+ 
+ 
+ /********** Miscellaneous constants **********/
+ 
+ /// Maximum allowed jitter.
+ #define OLSR_MAXJITTER		OLSR_HELLO_INTERVAL/4
+ /// Maximum allowed sequence number.
+ #define OLSR_MAX_SEQ_NUM	65535
+ /// Used to set status of an OLSR_nb_tuple as "not symmetric".
+ #define OLSR_STATUS_NOT_SYM	0
+ /// Used to set status of an OLSR_nb_tuple as "symmetric".
+ #define OLSR_STATUS_SYM		1
+ /// Random number between [0-OLSR_MAXJITTER] used to jitter OLSR packet transmission.
+ #define JITTER			(Random::uniform()*OLSR_MAXJITTER)
+ 
+ 
+ class OLSR;			// forward declaration
+ 
+ 
+ /********** Timers **********/
+ 
+ 
+ /// Timer for sending an enqued message.
+ class OLSR_MsgTimer : public TimerHandler {
+ public:
+ 	OLSR_MsgTimer(OLSR* agent) : TimerHandler() {
+ 		agent_	= agent;
+ 	}
+ protected:
+ 	OLSR*	agent_;			///< OLSR agent which created the timer.
+ 	virtual void expire(Event* e);
+ };
+ 
+ /// Timer for sending HELLO messages.
+ class OLSR_HelloTimer : public TimerHandler {
+ public:
+ 	OLSR_HelloTimer(OLSR* agent) : TimerHandler() { agent_ = agent; }
+ protected:
+ 	OLSR*	agent_;			///< OLSR agent which created the timer.
+ 	virtual void expire(Event* e);
+ };
+ 
+ 
+ /// Timer for sending TC messages.
+ class OLSR_TcTimer : public TimerHandler {
+ public:
+ 	OLSR_TcTimer(OLSR* agent) : TimerHandler() { agent_ = agent; }
+ protected:
+ 	OLSR*	agent_;			///< OLSR agent which created the timer.
+ 	virtual void expire(Event* e);
+ };
+ 
+ 
+ /// Timer for sending MID messages.
+ class OLSR_MidTimer : public TimerHandler {
+ public:
+ 	OLSR_MidTimer(OLSR* agent) : TimerHandler() { agent_ = agent; }
+ protected:
+ 	OLSR*	agent_;			///< OLSR agent which created the timer.
+ 	virtual void expire(Event* e);
+ };
+ 
+ 
+ /// Timer for removing duplicate tuples: OLSR_dup_tuple.
+ class OLSR_DupTupleTimer : public TimerHandler {
+ public:
+ 	OLSR_DupTupleTimer(OLSR* agent, OLSR_dup_tuple* tuple) : TimerHandler() {
+ 		agent_ = agent;
+ 		tuple_ = tuple;
+ 	}
+ protected:
+ 	OLSR*		agent_;	///< OLSR agent which created the timer.
+ 	OLSR_dup_tuple*	tuple_;	///< OLSR_dup_tuple which must be removed.
+ 	
+ 	virtual void expire(Event* e);
+ };
+ 
+ 
+ /// Timer for removing link tuples: OLSR_link_tuple.
+ class OLSR_LinkTupleTimer : public TimerHandler {
+ 	///
+ 	/// \brief A flag which tells if the timer has expired (at least) once or not.
+ 	///
+ 	/// When a link tuple has been just created, its sym_time is expired but this
+ 	/// does not mean a neighbor loss. Thus, we use this flag in order to be able
+ 	/// to distinguish this situation.
+ 	///
+ 	bool			first_time_;
+ public:
+ 	OLSR_LinkTupleTimer(OLSR* agent, OLSR_link_tuple* tuple) : TimerHandler() {
+ 		agent_		= agent;
+ 		tuple_		= tuple;
+ 		first_time_	= true;
+ 	}
+ protected:
+ 	OLSR*			agent_;	///< OLSR agent which created the timer.
+ 	OLSR_link_tuple*	tuple_;	///< OLSR_link_tuple which must be removed.
+ 	
+ 	virtual void expire(Event* e);
+ };
+ 
+ 
+ /// Timer for removing nb2hop tuples: OLSR_nb2hop_tuple.
+ class OLSR_Nb2hopTupleTimer : public TimerHandler {
+ public:
+ 	OLSR_Nb2hopTupleTimer(OLSR* agent, OLSR_nb2hop_tuple* tuple) : TimerHandler() {
+ 		agent_ = agent;
+ 		tuple_ = tuple;
+ 	}
+ protected:
+ 	OLSR*			agent_;	///< OLSR agent which created the timer.
+ 	OLSR_nb2hop_tuple*	tuple_;	///< OLSR_nb2hop_tuple which must be removed.
+ 	
+ 	virtual void expire(Event* e);
+ };
+ 
+ 
+ /// Timer for removing MPR selector tuples: OLSR_mprsel_tuple.
+ class OLSR_MprSelTupleTimer : public TimerHandler {
+ public:
+ 	OLSR_MprSelTupleTimer(OLSR* agent, OLSR_mprsel_tuple* tuple) : TimerHandler() {
+ 		agent_ = agent;
+ 		tuple_ = tuple;
+ 	}
+ protected:
+ 	OLSR*			agent_;	///< OLSR agent which created the timer.
+ 	OLSR_mprsel_tuple*	tuple_;	///< OLSR_mprsel_tuple which must be removed.
+ 	
+ 	virtual void expire(Event* e);
+ };
+ 
+ 
+ /// Timer for removing topology tuples: OLSR_topology_tuple.
+ class OLSR_TopologyTupleTimer : public TimerHandler {
+ public:
+ 	OLSR_TopologyTupleTimer(OLSR* agent, OLSR_topology_tuple* tuple) : TimerHandler() {
+ 		agent_ = agent;
+ 		tuple_ = tuple;
+ 	}
+ protected:
+ 	OLSR*			agent_;	///< OLSR agent which created the timer.
+ 	OLSR_topology_tuple*	tuple_;	///< OLSR_topology_tuple which must be removed.
+ 	
+ 	virtual void expire(Event* e);
+ };
+ 
+ 
+ /// Timer for removing interface association tuples: OLSR_iface_assoc_tuple.
+ class OLSR_IfaceAssocTupleTimer : public TimerHandler {
+ public:
+ 	OLSR_IfaceAssocTupleTimer(OLSR* agent, OLSR_iface_assoc_tuple* tuple) : TimerHandler() {
+ 		agent_ = agent;
+ 		tuple_ = tuple;
+ 	}
+ protected:
+ 	OLSR*			agent_;	///< OLSR agent which created the timer.
+ 	OLSR_iface_assoc_tuple*	tuple_;	///< OLSR_iface_assoc_tuple which must be removed.
+ 	
+ 	virtual void expire(Event* e);
+ };
+ 
+ 
+ /********** OLSR Agent **********/
+ 
+ 
+ ///
+ /// \brief Routing agent which implements %OLSR protocol following RFC 3626.
+ ///
+ /// Interacts with TCL interface through command() method. It implements all
+ /// functionalities related to sending and receiving packets and managing
+ /// internal state.
+ ///
+ class OLSR : public Agent {
+ 	// Makes some friends.
+ 	friend class OLSR_HelloTimer;
+ 	friend class OLSR_TcTimer;
+ 	friend class OLSR_MidTimer;
+ 	friend class OLSR_DupTupleTimer;
+ 	friend class OLSR_LinkTupleTimer;
+ 	friend class OLSR_Nb2hopTupleTimer;
+ 	friend class OLSR_MprSelTupleTimer;
+ 	friend class OLSR_TopologyTupleTimer;
+ 	friend class OLSR_IfaceAssocTupleTimer;
+ 	friend class OLSR_MsgTimer;
+ 	
+ 	/// Address of the routing agent.
+ 	nsaddr_t	ra_addr_;
+ 	
+ 	/// Packets sequence number counter.
+ 	u_int16_t	pkt_seq_;
+ 	/// Messages sequence number counter.
+ 	u_int16_t	msg_seq_;
+ 	/// Advertised Neighbor Set sequence number.
+ 	u_int16_t	ansn_;
+ 	
+ 	/// HELLO messages' emission interval.
+ 	int		hello_ival_;
+ 	/// TC messages' emission interval.
+ 	int		tc_ival_;
+ 	/// MID messages' emission interval.
+ 	int		mid_ival_;
+ 	/// Willingness for forwarding packets on behalf of other nodes.
+ 	int		willingness_;
+ 	/// Determines if layer 2 notifications are enabled or not.
+ 	int		use_mac_;
+ 	
+ 	/// Routing table.
+ 	OLSR_rtable		rtable_;
+ 	/// Internal state with all needed data structs.
+ 	OLSR_state		state_;
+ 	/// A list of pending messages which are buffered awaiting for being sent.
+ 	std::vector<OLSR_msg>	msgs_;
+ 
+ 	///
+ 	/// \brief A list of timers which have expired but their memory haven't been released yet.
+ 	///
+ 	/// This is a very ugly hack. Since we are dynamically creating
+ 	/// several timers we need to release their memory at a certain
+ 	/// time. Here we will store their references in order to later
+ 	/// on release them.
+ 	///
+ 	std::vector<TimerHandler*>	expired_timers_;
+ 	
+ 	void				release_expired_timers();	// See just above.
+ 	
+ protected:
+ 	PortClassifier*	dmux_;		///< For passing packets up to agents.
+ 	Trace*		logtarget_;	///< For logging.
+ 	
+ 	OLSR_HelloTimer	hello_timer_;	///< Timer for sending HELLO messages.
+ 	OLSR_TcTimer	tc_timer_;	///< Timer for sending TC messages.
+ 	OLSR_MidTimer	mid_timer_;	///< Timer for sending MID messages.
+ 	
+ 	/// Increments packet sequence number and returns the new value.
+ 	inline u_int16_t	pkt_seq() {
+ 		pkt_seq_ = (pkt_seq_ + 1)%(OLSR_MAX_SEQ_NUM + 1);
+ 		return pkt_seq_;
+ 	}
+ 	/// Increments message sequence number and returns the new value.
+ 	inline u_int16_t	msg_seq() {
+ 		msg_seq_ = (msg_seq_ + 1)%(OLSR_MAX_SEQ_NUM + 1);
+ 		return msg_seq_;
+ 	}
+ 	
+ 	inline nsaddr_t&	ra_addr()	{ return ra_addr_; }
+ 	
+ 	inline int&		hello_ival()	{ return hello_ival_; }
+ 	inline int&		tc_ival()	{ return tc_ival_; }
+ 	inline int&		mid_ival()	{ return mid_ival_; }
+ 	inline int&		willingness()	{ return willingness_; }
+ 	inline int&		use_mac()	{ return use_mac_; }
+ 	
+ 	inline linkset_t&	linkset()	{ return state_.linkset(); }
+ 	inline mprset_t&	mprset()	{ return state_.mprset(); }
+ 	inline mprselset_t&	mprselset()	{ return state_.mprselset(); }
+ 	inline nbset_t&		nbset()		{ return state_.nbset(); }
+ 	inline nb2hopset_t&	nb2hopset()	{ return state_.nb2hopset(); }
+ 	inline topologyset_t&	topologyset()	{ return state_.topologyset(); }
+ 	inline dupset_t&	dupset()	{ return state_.dupset(); }
+ 	inline ifaceassocset_t&	ifaceassocset()	{ return state_.ifaceassocset(); }
+ 	
+ 	void		recv_olsr(Packet*);
+ 	
+ 	void		mpr_computation();
+ 	void		rtable_computation();
+ 	
+ 	void		process_hello(OLSR_msg&, nsaddr_t, nsaddr_t);
+ 	void		process_tc(OLSR_msg&, nsaddr_t);
+ 	void		process_mid(OLSR_msg&, nsaddr_t);
+ 	
+ 	void		forward_default(Packet*, OLSR_msg&, OLSR_dup_tuple*, nsaddr_t);
+ 	void		forward_data(Packet*);
+ 	
+ 	void		enque_msg(OLSR_msg&, double);
+ 	void		send_hello();
+ 	void		send_tc();
+ 	void		send_mid();
+ 	void		send_pkt();
+ 	
+ 	void		link_sensing(OLSR_msg&, nsaddr_t, nsaddr_t);
+ 	void		populate_nbset(OLSR_msg&);
+ 	void		populate_nb2hopset(OLSR_msg&);
+ 	void		populate_mprselset(OLSR_msg&);
+ 
+ 	void		set_hello_timer();
+ 	void		set_tc_timer();
+ 	void		set_mid_timer();
+ 
+ 	void		nb_loss(OLSR_link_tuple*);
+ 	void		add_dup_tuple(OLSR_dup_tuple*);
+ 	void		rm_dup_tuple(OLSR_dup_tuple*);
+ 	void		add_link_tuple(OLSR_link_tuple*, u_int8_t);
+ 	void		rm_link_tuple(OLSR_link_tuple*);
+ 	void		updated_link_tuple(OLSR_link_tuple*);
+ 	void		add_nb_tuple(OLSR_nb_tuple*);
+ 	void		rm_nb_tuple(OLSR_nb_tuple*);
+ 	void		add_nb2hop_tuple(OLSR_nb2hop_tuple*);
+ 	void		rm_nb2hop_tuple(OLSR_nb2hop_tuple*);
+ 	void		add_mprsel_tuple(OLSR_mprsel_tuple*);
+ 	void		rm_mprsel_tuple(OLSR_mprsel_tuple*);
+ 	void		add_topology_tuple(OLSR_topology_tuple*);
+ 	void		rm_topology_tuple(OLSR_topology_tuple*);
+ 	void		add_ifaceassoc_tuple(OLSR_iface_assoc_tuple*);
+ 	void		rm_ifaceassoc_tuple(OLSR_iface_assoc_tuple*);
+ 	
+ 	nsaddr_t	get_main_addr(nsaddr_t);
+ 	int		degree(OLSR_nb_tuple*);
+ 
+ 	static bool	seq_num_bigger_than(u_int16_t, u_int16_t);
+ 
+ public:
+ 	OLSR(nsaddr_t);
+ 	int	command(int, const char*const*);
+ 	void	recv(Packet*, Handler*);
+ 	void	mac_failed(Packet*);
+ 	
+ 	static double		emf_to_seconds(u_int8_t);
+ 	static u_int8_t		seconds_to_emf(double);
+ 	static int		node_id(nsaddr_t);
+ };
+ 
+ #endif
diff --new-file --recursive --context=3 --minimal -x '*.[ao]' -x '*.nam' -x '*.tr' -x '*.cache' -x core -x '*.core' ns-2.27-ORIG/olsr/OLSR_pkt.h ns-2.27/olsr/OLSR_pkt.h
*** ns-2.27-ORIG/olsr/OLSR_pkt.h	1970-01-01 01:00:00.000000000 +0100
--- ns-2.27/olsr/OLSR_pkt.h	2005-03-11 11:38:59.000000000 +0100
***************
*** 0 ****
--- 1,228 ----
+ /***************************************************************************
+  *   Copyright (C) 2004 by Francisco J. Ros                                *
+  *   fjrm@dif.um.es                                                        *
+  *                                                                         *
+  *   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.             *
+  ***************************************************************************/
+ 
+ ///
+ /// \file	OLSR_pkt.h
+ /// \brief	This file contains all declarations of %OLSR packets and messages,
+ ///		including all related contants and macros.
+ ///
+ 
+ #ifndef __OLSR_pkt_h__
+ #define __OLSR_pkt_h__
+ 
+ #include <packet.h>
+ 
+ /********** Message types **********/
+ 
+ /// %OLSR HELLO message type.
+ #define OLSR_HELLO_MSG		1
+ /// %OLSR TC message type.
+ #define OLSR_TC_MSG		2
+ /// %OLSR MID message type.
+ #define OLSR_MID_MSG		3
+ 
+ /********** Packets stuff **********/
+ 
+ /// Accessor to the %OLSR packet.
+ #define PKT_OLSR(p)		OLSR_pkt::access(p)
+ 
+ ///
+ /// \brief Size of the addresses we are using.
+ ///
+ /// You should always use this macro when interested in calculate addresses'
+ /// sizes. By default it is supposed IPv6 addresses, but you can change to
+ /// IPv4 ones by recompiling with OLSR_IPv4 constant defined.
+ ///
+ #ifdef OLSR_IPv4
+ #define ADDR_SIZE	4
+ #else
+ #define ADDR_SIZE	16
+ #endif
+ 
+ /// Maximum number of messages per packet.
+ #define OLSR_MAX_MSGS		64
+ 
+ /// Maximum number of hellos per message (4 possible link types * 3 possible nb types).
+ #define OLSR_MAX_HELLOS		12
+ 
+ /// Maximum number of addresses advertised on a message.
+ #define OLSR_MAX_ADDRS		64
+ 
+ /// Size (in bytes) of packet header.
+ #define OLSR_PKT_HDR_SIZE	4
+ 
+ /// Size (in bytes) of message header.
+ #define OLSR_MSG_HDR_SIZE	12
+ 
+ /// Size (in bytes) of hello header.
+ #define OLSR_HELLO_HDR_SIZE	4
+ 
+ /// Size (in bytes) of hello_msg header.
+ #define OLSR_HELLO_MSG_HDR_SIZE	4
+ 
+ /// Size (in bytes) of tc header.
+ #define OLSR_TC_HDR_SIZE	4
+ 
+ /// Auxiliary struct which is part of the %OLSR HELLO message (struct OLSR_hello).
+ typedef struct OLSR_hello_msg {
+ 
+         /// Link code.
+ 	u_int8_t	link_code_;
+ 	/// Reserved.
+ 	u_int8_t	reserved_;
+ 	/// Size of this link message.
+ 	u_int16_t	link_msg_size_;
+ 	/// List of interface addresses of neighbor nodes.
+ 	nsaddr_t	nb_iface_addrs_[OLSR_MAX_ADDRS];
+ 	/// Number of interface addresses contained in nb_iface_addrs_.
+ 	int		count;
+ 	
+ 	inline u_int8_t&	link_code()		{ return link_code_; }
+ 	inline u_int8_t&	reserved()		{ return reserved_; }
+ 	inline u_int16_t&	link_msg_size()		{ return link_msg_size_; }
+ 	inline nsaddr_t&	nb_iface_addr(int i)	{ return nb_iface_addrs_[i]; }
+ 	
+ 	inline u_int32_t size() { return OLSR_HELLO_MSG_HDR_SIZE + count*ADDR_SIZE; }
+ 
+ } OLSR_hello_msg;
+ 
+ /// %OLSR HELLO message.
+ typedef struct OLSR_hello {
+ 
+ 	/// Reserved.
+ 	u_int16_t	reserved_;
+ 	/// HELLO emission interval in mantissa/exponent format.
+ 	u_int8_t	htime_;
+ 	/// Willingness of a node for forwarding packets on behalf of other nodes.
+ 	u_int8_t	willingness_;
+ 	/// List of OLSR_hello_msg.
+ 	OLSR_hello_msg	hello_body_[OLSR_MAX_HELLOS];
+ 	/// Number of OLSR_hello_msg contained in hello_body_.
+ 	int		count;
+ 	
+ 	inline u_int16_t&	reserved()		{ return reserved_; }
+ 	inline u_int8_t&	htime()			{ return htime_; }
+ 	inline u_int8_t&	willingness()		{ return willingness_; }
+ 	inline OLSR_hello_msg&	hello_msg(int i)	{ return hello_body_[i]; }
+ 	
+ 	inline u_int32_t size() {
+ 		u_int32_t sz = OLSR_HELLO_HDR_SIZE;
+ 		for (int i = 0; i < count; i++)
+ 			sz += hello_msg(i).size();
+ 		return sz;
+ 	}
+ 	
+ } OLSR_hello;
+ 
+ /// %OLSR TC message.
+ typedef struct OLSR_tc {
+ 
+         /// Advertised Neighbor Sequence Number.
+ 	u_int16_t	ansn_;
+ 	/// Reserved.
+ 	u_int16_t	reserved_;
+ 	/// List of neighbors' main addresses.
+ 	nsaddr_t	nb_main_addrs_[OLSR_MAX_ADDRS];
+ 	/// Number of neighbors' main addresses contained in nb_main_addrs_.
+ 	int		count;
+         
+ 	inline	u_int16_t&	ansn()			{ return ansn_; }
+ 	inline	u_int16_t&	reserved()		{ return reserved_; }
+ 	inline	nsaddr_t&	nb_main_addr(int i)	{ return nb_main_addrs_[i]; }
+ 	
+ 	inline	u_int32_t size() { return OLSR_TC_HDR_SIZE + count*ADDR_SIZE; }
+ 
+ } OLSR_tc;
+ 
+ /// %OLSR MID message.
+ typedef struct OLSR_mid {
+ 
+ 	/// List of interface addresses.
+ 	nsaddr_t	iface_addrs_[OLSR_MAX_ADDRS];
+ 	/// Number of interface addresses contained in iface_addrs_.
+ 	int		count;
+ 	
+ 	inline nsaddr_t&	iface_addr(int i)	{ return iface_addrs_[i]; }
+ 	
+ 	inline u_int32_t	size()			{ return count*ADDR_SIZE; }
+ 	
+ } OLSR_mid;
+ 
+ /// %OLSR message.
+ typedef struct OLSR_msg {
+ 
+ 	u_int8_t	msg_type_;	///< Message type.
+ 	u_int8_t	vtime_;		///< Validity time.
+ 	u_int16_t	msg_size_;	///< Message size (in bytes).
+ 	nsaddr_t	orig_addr_;	///< Main address of the node which generated this message.
+ 	u_int8_t	ttl_;		///< Time to live (in hops).
+ 	u_int8_t	hop_count_;	///< Number of hops which the message has taken.
+ 	u_int16_t	msg_seq_num_;	///< Message sequence number.
+ 	union {
+ 		OLSR_hello	hello_;
+ 		OLSR_tc		tc_;
+ 		OLSR_mid	mid_;
+ 	} msg_body_;			///< Message body.
+ 	
+ 	inline	u_int8_t&	msg_type()	{ return msg_type_; }
+ 	inline	u_int8_t&	vtime()		{ return vtime_; }
+ 	inline	u_int16_t&	msg_size()	{ return msg_size_; }
+ 	inline	nsaddr_t&	orig_addr()	{ return orig_addr_; }
+ 	inline	u_int8_t&	ttl()		{ return ttl_; }
+ 	inline	u_int8_t&	hop_count()	{ return hop_count_; }
+ 	inline	u_int16_t&	msg_seq_num()	{ return msg_seq_num_; }
+ 	inline	OLSR_hello&	hello()		{ return msg_body_.hello_; }
+ 	inline	OLSR_tc&	tc()		{ return msg_body_.tc_; }
+ 	inline	OLSR_mid&	mid()		{ return msg_body_.mid_; }
+ 	
+ 	inline u_int32_t size() {
+ 		u_int32_t sz = OLSR_MSG_HDR_SIZE;
+ 		if (msg_type() == OLSR_HELLO_MSG)
+ 			sz += hello().size();
+ 		else if (msg_type() == OLSR_TC_MSG)
+ 			sz += tc().size();
+ 		else if (msg_type() == OLSR_MID_MSG)
+ 			sz += mid().size();
+ 		return sz;
+ 	}
+ 
+ } OLSR_msg;
+ 
+ /// %OLSR packet.
+ typedef struct OLSR_pkt {
+ 
+ 	u_int16_t	pkt_len_;			///< Packet length (in bytes).
+ 	u_int16_t	pkt_seq_num_;			///< Packet sequence number.
+ 	OLSR_msg	pkt_body_[OLSR_MAX_MSGS];	///< Packet body.
+ 	int		count;				///< Number of OLSR_msg contained in pkt_body_.
+ 	
+ 	inline	u_int16_t&	pkt_len()	{ return pkt_len_; }
+ 	inline	u_int16_t&	pkt_seq_num()	{ return pkt_seq_num_; }
+ 	inline	OLSR_msg&	msg(int i)	{ return pkt_body_[i]; }
+ 	
+ 	static int offset_;
+ 	inline static int& offset() { return offset_; }
+ 	inline static struct OLSR_pkt* access(const Packet* p) {
+ 		return (struct OLSR_pkt*)p->access(offset_);
+ 	}
+ 
+ } OLSR_pkt;
+ 
+ #endif
diff --new-file --recursive --context=3 --minimal -x '*.[ao]' -x '*.nam' -x '*.tr' -x '*.cache' -x core -x '*.core' ns-2.27-ORIG/olsr/OLSR_printer.cc ns-2.27/olsr/OLSR_printer.cc
*** ns-2.27-ORIG/olsr/OLSR_printer.cc	1970-01-01 01:00:00.000000000 +0100
--- ns-2.27/olsr/OLSR_printer.cc	2005-03-11 11:38:59.000000000 +0100
***************
*** 0 ****
--- 1,348 ----
+ /***************************************************************************
+  *   Copyright (C) 2004 by Francisco J. Ros                                *
+  *   fjrm@dif.um.es                                                        *
+  *                                                                         *
+  *   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.             *
+  ***************************************************************************/
+ 
+ ///
+ /// \file	OLSR_printer.cc
+ /// \brief	Printing functions used for debugging and tracing are implemented in this file.
+ ///
+ 
+ #include <olsr/OLSR_printer.h>
+ 
+ /********** Messages and packets printing functions **********/
+ 
+ ///
+ /// \brief Prints a given common header into a given file.
+ /// \warning This function is actually not used.
+ /// \param out	File where the common header is going to be written.
+ /// \param ch	Common header to be written.
+ ///
+ void
+ OLSR_printer::print_cmn_hdr(FILE* out, struct hdr_cmn* ch) {
+ 	char *error, *direction;
+ 	
+ 	if (ch->error())
+ 		error = "yes";
+ 	else
+ 		error = "no";
+ 		
+ 	if (ch->direction() == hdr_cmn::DOWN)
+ 		direction = "DOWN";
+ 	else if (ch->direction() == hdr_cmn::UP)
+ 		direction = "UP";
+ 	else if (ch->direction() == hdr_cmn::NONE)
+ 		direction = "NONE";
+ 	else
+ 		direction = "UNKNOWN (likely a bug!)";
+ 	
+ 	// We could include this if we were interested in printing address type
+ 	/*if (ch->addr_type() == NS_AF_NONE)
+ 		addr_type = "NS_AF_NONE";
+ 	else if (ch->addr_type() == NS_AF_ILINK)
+ 		addr_type = "NS_AF_ILINK";
+ 	else if (ch->addr_type() == NS_AF_INET)
+ 		addr_type = "NS_AF_INET";
+ 	else
+ 		addr_type = "UNKNOWN (possibly a bug!)";*/
+ 	
+ 	fprintf(out,
+ 		"  COMMON HEADER\n\tptype = %s\n\tuid = %d\n\tsize = %d\n\terror = %s\n\tdirection = %s\n\n",
+ 		packet_info.name(ch->ptype()),
+ 		ch->uid(),
+ 		ch->size(),
+ 		error,
+ 		direction);
+ }
+ 
+ ///
+ /// \brief Prints a given IP header into a given file.
+ /// \warning This function is actually not used.
+ /// \param out	File where the IP header is going to be written.
+ /// \param ih	IP header to be written.
+ ///
+ void
+ OLSR_printer::print_ip_hdr(FILE* out, struct hdr_ip* ih) {
+ 	fprintf(out,
+ 		"  IP HEADER\n\tsrc_addr = %d\n\tsrc_port = %d\n\tdest_addr = %d\n\tdest_port = %d\n\tttl = %d\n\n",
+ 		ih->saddr(),
+ 		ih->sport(),
+ 		ih->daddr(),
+ 		ih->dport(),
+ 		ih->ttl());
+ }
+ 
+ ///
+ /// \brief Prints a given OLSR packet into a given file.
+ /// \warning This function is actually not used.
+ /// \param out	File where the %OLSR packet is going to be written.
+ /// \param pkt	%OLSR packet to be written.
+ ///
+ void
+ OLSR_printer::print_olsr_pkt(FILE* out, OLSR_pkt* pkt) {
+ 		
+ 	fprintf(out,
+ 		"  OLSR PACKET\n\tlength = %d\n\tseq_num = %d\n\t------------\n",
+ 		pkt->pkt_len(),
+ 		pkt->pkt_seq_num());
+ 	
+ 	for (int i = 0; i < pkt->count; i++) {
+ 		print_olsr_msg(out, pkt->msg(i));
+ 		fprintf(out, "\t------------\n");
+ 	}
+ 	fprintf(out, "\n");
+ }
+ 
+ ///
+ /// \brief Prints a given %OLSR message into a given file.
+ /// \warning This function is actually not used.
+ /// \param out	File where the %OLSR message is going to be written.
+ /// \param msg	%OLSR message to be written.
+ ///
+ void
+ OLSR_printer::print_olsr_msg(FILE* out, OLSR_msg& msg) {
+ 	char *msg_type;
+ 	
+ 	switch (msg.msg_type()) {
+ 		case OLSR_HELLO_MSG:
+ 			msg_type = "HELLO";
+ 			break;
+ 		case OLSR_TC_MSG:
+ 			msg_type = "TC";
+ 			break;
+ 		case OLSR_MID_MSG:
+ 			msg_type = "MID";
+ 			break;
+ 		default:
+ 			msg_type = "UNKNOWN (likely a bug!)";
+ 	}
+ 	
+ 	fprintf(out,
+ 		"\ttype = %s\n\tvtime = %.2f\n\tmsg_size = %d\n\torig_addr = %d\n\tttl = %d\n\thop_count = %d\n\tmsg_seq_num = %d\n",
+ 		msg_type,
+ 		OLSR::emf_to_seconds(msg.vtime()),
+ 		msg.msg_size(),
+ 		msg.orig_addr(),
+ 		msg.ttl(),
+ 		msg.hop_count(),
+ 		msg.msg_seq_num());
+ 	
+ 	if (msg.msg_type() == OLSR_HELLO_MSG)
+ 		print_olsr_hello(out, msg.hello());
+ 	else if (msg.msg_type() == OLSR_TC_MSG)
+ 		print_olsr_tc(out, msg.tc());
+ 	else if (msg.msg_type() == OLSR_MID_MSG)
+ 		print_olsr_mid(out, msg.mid());
+ }
+ 
+ ///
+ /// \brief Prints a given %OLSR HELLO message into a given file.
+ /// \warning This function is actually not used.
+ /// \param out		File where the %OLSR HELLO message is going to be written.
+ /// \param hello	%OLSR HELLO message to be written.
+ ///
+ void
+ OLSR_printer::print_olsr_hello(FILE* out, OLSR_hello& hello) {
+ 	
+ 	fprintf(out, "\thtime = %.2f\n\twillingness = %d\n",
+ 		OLSR::emf_to_seconds(hello.htime()),
+ 		hello.willingness());
+ 	
+ 	for (int i = 0; i < hello.count; i++) {
+ 		char *nt, *lt;
+ 		OLSR_hello_msg msg = hello.hello_msg(i);
+ 		
+ 		u_int8_t nb_type = msg.link_code() >> 2;
+ 		u_int8_t link_type = msg.link_code() & 0x03;
+ 		if (nb_type == OLSR_NOT_NEIGH)
+ 			nt = "NOT_NEIGH";
+ 		else if (nb_type == OLSR_SYM_NEIGH)
+ 			nt = "SYM_NEIGH";
+ 		else if (nb_type == OLSR_MPR_NEIGH)
+ 			nt = "MPR_NEIGH";
+ 		else
+ 			nt = "UNKNOWN (likely a bug!)";
+ 		
+ 		if (link_type == OLSR_UNSPEC_LINK)
+ 			lt = "UNSPEC_LINK";
+ 		else if (link_type == OLSR_ASYM_LINK)
+ 			lt = "ASYM_LINK";
+ 		else if (link_type == OLSR_SYM_LINK)
+ 			lt = "SYM_LINK";
+ 		else if (link_type == OLSR_LOST_LINK)
+ 			lt = "LOST_LINK";
+ 		else
+ 			lt = "UNKNOWN (likely a bug!)";
+ 		
+ 		fprintf(out, "\tlink_code = %s - %s\n\tlink_msg_size = %d\n",
+ 			nt,
+ 			lt,
+ 			msg.link_msg_size());
+ 	
+ 		for (int j = 0; j < msg.count; j++)
+ 			fprintf(out, "\tnb_iface_addr = %d\n", msg.nb_iface_addr(j));
+ 	}
+ }
+ 
+ ///
+ /// \brief Prints a given %OLSR TC message into a given file.
+ /// \warning This function is actually not used.
+ /// \param out	File where the %OLSR TC message is going to be written.
+ /// \param tc	%OLSR TC message to be written.
+ ///
+ void
+ OLSR_printer::print_olsr_tc(FILE* out, OLSR_tc& tc) {
+ 	fprintf(out, "\tansn = %d\n\treserved = %d\n",
+ 		tc.ansn(),
+ 		tc.reserved());
+ 	for (int i = 0; i < tc.count; i++)
+ 		fprintf(out, "\taddr = %d\n", tc.nb_main_addr(i));
+ }
+ 
+ ///
+ /// \brief Prints a given %OLSR MID message into a given file.
+ /// \warning This function is actually not used.
+ /// \param out	File where the %OLSR MID message is going to be written.
+ /// \param mid	%OLSR MID message to be written.
+ ///
+ void
+ OLSR_printer::print_olsr_mid(FILE* out, OLSR_mid& mid) {
+ 	for (int i = 0; i < mid.count; i++)
+ 		fprintf(out, "\tiface = %d\n", mid.iface_addr(i));
+ }
+ 
+ /********** Repositories printing functions **********/
+ 
+ ///
+ /// \brief Prints a given Link Set into a given trace file.
+ ///
+ /// \param out		Trace where the Link Set is going to be written.
+ /// \param linkset	Link Set to be written.
+ ///
+ void
+ OLSR_printer::print_linkset(Trace* out, linkset_t& linkset) {
+ 	sprintf(out->pt_->buffer(), "P\tlocal\tnb\tsym\t\tasym\t\tlost\t\ttime");
+ 	out->pt_->dump();
+ 	for (linkset_t::iterator it = linkset.begin(); it != linkset.end(); it++) {
+ 		OLSR_link_tuple* tuple = *it;
+ 		sprintf(out->pt_->buffer(), "P\t%d\t%d\t%f\t%f\t%f\t%f",
+ 			OLSR::node_id(tuple->local_iface_addr()),
+ 			OLSR::node_id(tuple->nb_iface_addr()),
+ 			tuple->sym_time(),
+ 			tuple->asym_time(),
+ 			tuple->lost_time(),
+ 			tuple->time());
+ 		out->pt_->dump();
+ 	}
+ }
+ 
+ ///
+ /// \brief Prints a given Neighbor Set into a given trace file.
+ ///
+ /// \param out		Trace where the Neighbor Set is going to be written.
+ /// \param nbset	Neighbor Set to be written.
+ ///
+ void
+ OLSR_printer::print_nbset(Trace* out, nbset_t& nbset) {
+ 	sprintf(out->pt_->buffer(), "P\tnb\tstatus\twillingness");
+ 	out->pt_->dump();
+ 	for (nbset_t::iterator it = nbset.begin(); it != nbset.end(); it++) {
+ 		OLSR_nb_tuple* tuple = *it;
+ 		sprintf(out->pt_->buffer(), "P\t%d\t%d\t%d",
+ 			OLSR::node_id(tuple->nb_main_addr()),
+ 			tuple->status(),
+ 			tuple->willingness());
+ 		out->pt_->dump();
+ 	}
+ }
+ 
+ ///
+ /// \brief Prints a given 2-hop Neighbor Set into a given trace file.
+ ///
+ /// \param out		Trace where the 2-hop Neighbor Set is going to be written.
+ /// \param nb2hopset	2-hop Neighbor Set to be written.
+ ///
+ void
+ OLSR_printer::print_nb2hopset(Trace* out, nb2hopset_t& nb2hopset) {
+ 	sprintf(out->pt_->buffer(), "P\tnb\tnb2hop\ttime");
+ 	out->pt_->dump();
+ 	for (nb2hopset_t::iterator it = nb2hopset.begin(); it != nb2hopset.end(); it++) {
+ 		OLSR_nb2hop_tuple* tuple = *it;
+ 		sprintf(out->pt_->buffer(), "P\t%d\t%d\t%f",
+ 			OLSR::node_id(tuple->nb_main_addr()),
+ 			OLSR::node_id(tuple->nb2hop_addr()),
+ 			tuple->time());
+ 		out->pt_->dump();
+ 	}
+ }
+ 
+ ///
+ /// \brief Prints a given MPR Set into a given trace file.
+ ///
+ /// \param out		Trace where the MPR Set is going to be written.
+ /// \param mprset	MPR Set to be written.
+ ///
+ void
+ OLSR_printer::print_mprset(Trace* out, mprset_t& mprset) {
+ 	sprintf(out->pt_->buffer(), "P\tnb");
+ 	out->pt_->dump();
+ 	for (mprset_t::iterator it = mprset.begin(); it != mprset.end(); it++) {
+ 		sprintf(out->pt_->buffer(), "P\t%d", OLSR::node_id(*it));
+ 		out->pt_->dump();
+ 	}
+ }
+ 
+ ///
+ /// \brief Prints a given MPR Selector Set into a given trace file.
+ ///
+ /// \param out		Trace where the MPR Selector Set is going to be written.
+ /// \param mprselset	MPR Selector Set to be written.
+ ///
+ void
+ OLSR_printer::print_mprselset(Trace* out, mprselset_t& mprselset) {
+ 	sprintf(out->pt_->buffer(), "P\tnb\ttime");
+ 	out->pt_->dump();
+ 	for (mprselset_t::iterator it = mprselset.begin(); it != mprselset.end(); it++) {
+ 		OLSR_mprsel_tuple* mprsel_tuple = *it;
+ 		sprintf(out->pt_->buffer(), "P\t%d\t%f",
+ 			OLSR::node_id(mprsel_tuple->main_addr()),
+ 			mprsel_tuple->time());
+ 		out->pt_->dump();
+ 	}
+ }
+ 
+ ///
+ /// \brief Prints a given Topology Set into a given trace file.
+ ///
+ /// \param out		Trace where the Topology Set is going to be written.
+ /// \param topologyset	Topology Set to be written.
+ ///
+ void
+ OLSR_printer::print_topologyset(Trace* out, topologyset_t& topologyset) {
+ 	sprintf(out->pt_->buffer(), "P\tdest\tlast\tseq\ttime");
+ 	out->pt_->dump();
+ 	for (topologyset_t::iterator it = topologyset.begin(); it != topologyset.end(); it++) {
+ 		OLSR_topology_tuple* topology_tuple = *it;
+ 		sprintf(out->pt_->buffer(), "P\t%d\t%d\t%d\t%f",
+ 			OLSR::node_id(topology_tuple->dest_addr()),
+ 			OLSR::node_id(topology_tuple->last_addr()),
+ 			topology_tuple->seq(),
+ 			topology_tuple->time());
+ 		out->pt_->dump();
+ 	}
+ }
diff --new-file --recursive --context=3 --minimal -x '*.[ao]' -x '*.nam' -x '*.tr' -x '*.cache' -x core -x '*.core' ns-2.27-ORIG/olsr/OLSR_printer.h ns-2.27/olsr/OLSR_printer.h
*** ns-2.27-ORIG/olsr/OLSR_printer.h	1970-01-01 01:00:00.000000000 +0100
--- ns-2.27/olsr/OLSR_printer.h	2005-03-11 11:38:59.000000000 +0100
***************
*** 0 ****
--- 1,59 ----
+ /***************************************************************************
+  *   Copyright (C) 2004 by Francisco J. Ros                                *
+  *   fjrm@dif.um.es                                                        *
+  *                                                                         *
+  *   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.             *
+  ***************************************************************************/
+ 
+ ///
+ /// \file	OLSR_printer.h
+ /// \brief	Header file which includes all printing functions related to OLSR.
+ ///
+ 
+ #ifndef __OLSR_printer_h__
+ #define __OLSR_printer_h__
+ 
+ #include <olsr/OLSR.h>
+ #include <olsr/OLSR_pkt.h>
+ #include <olsr/OLSR_repositories.h>
+ #include <packet.h>
+ #include <ip.h>
+ #include <trace.h>
+ 
+ /// Encapsulates all printing functions for OLSR data structures and messages.
+ class OLSR_printer {
+ 	friend class OLSR;
+ 
+ protected:
+ 	static void	print_linkset(Trace*, linkset_t&);
+ 	static void	print_nbset(Trace*, nbset_t&);
+ 	static void	print_nb2hopset(Trace*, nb2hopset_t&);
+ 	static void	print_mprset(Trace*, mprset_t&);
+ 	static void	print_mprselset(Trace*, mprselset_t&);
+ 	static void	print_topologyset(Trace*, topologyset_t&);
+ 	
+ 	static void	print_olsr_pkt(FILE*, OLSR_pkt*);
+ 	static void	print_olsr_msg(FILE*, OLSR_msg&);
+ 	static void	print_olsr_hello(FILE*, OLSR_hello&);
+ 	static void	print_olsr_tc(FILE*, OLSR_tc&);
+ 	static void	print_olsr_mid(FILE*, OLSR_mid&);
+ 
+ public:
+ 	static void	print_cmn_hdr(FILE*, struct hdr_cmn*);
+ 	static void	print_ip_hdr(FILE*, struct hdr_ip*);
+ };
+ 
+ #endif
diff --new-file --recursive --context=3 --minimal -x '*.[ao]' -x '*.nam' -x '*.tr' -x '*.cache' -x core -x '*.core' ns-2.27-ORIG/olsr/OLSR_repositories.h ns-2.27/olsr/OLSR_repositories.h
*** ns-2.27-ORIG/olsr/OLSR_repositories.h	1970-01-01 01:00:00.000000000 +0100
--- ns-2.27/olsr/OLSR_repositories.h	2005-03-11 11:38:59.000000000 +0100
***************
*** 0 ****
--- 1,172 ----
+ /***************************************************************************
+  *   Copyright (C) 2004 by Francisco J. Ros                                *
+  *   fjrm@dif.um.es                                                        *
+  *                                                                         *
+  *   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.             *
+  ***************************************************************************/
+ 
+ ///
+ /// \file	OLSR_repositories.h
+ /// \brief	Here are defined all data structures needed by an OLSR node.
+ ///
+ 
+ #ifndef __OLSR_repositories_h__
+ #define __OLSR_repositories_h__
+ 
+ #include <set>
+ #include <vector>
+ #include <config.h>
+ 
+ /// An %OLSR's routing table entry.
+ typedef struct OLSR_rt_entry {
+ 	nsaddr_t	dest_addr_;	///< Address of the destination node.
+ 	nsaddr_t	next_addr_;	///< Address of the next hop.
+ 	nsaddr_t	iface_addr_;	///< Address of the local interface.
+ 	u_int32_t	dist_;		///< Distance in hops to the destination.
+ 	
+ 	inline nsaddr_t&	dest_addr()	{ return dest_addr_; }
+ 	inline nsaddr_t&	next_addr()	{ return next_addr_; }
+ 	inline nsaddr_t&	iface_addr()	{ return iface_addr_; }
+ 	inline u_int32_t&	dist()		{ return dist_; }
+ } OLSR_rt_entry;
+ 
+ /// An Interface Association Tuple.
+ typedef struct OLSR_iface_assoc_tuple {
+ 	/// Interface address of a node.
+ 	nsaddr_t	iface_addr_;
+ 	/// Main address of the node.
+ 	nsaddr_t	main_addr_;
+ 	/// Time at which this tuple expires and must be removed.
+ 	double		time_;
+ 	
+ 	inline nsaddr_t&	iface_addr()	{ return iface_addr_; }
+ 	inline nsaddr_t&	main_addr()	{ return main_addr_; }
+ 	inline double&		time()		{ return time_; }
+ } OLSR_iface_assoc_tuple;
+ 
+ /// A Link Tuple.
+ typedef struct OLSR_link_tuple {
+ 	/// Interface address of the local node.
+ 	nsaddr_t	local_iface_addr_;
+ 	/// Interface address of the neighbor node.
+ 	nsaddr_t	nb_iface_addr_;
+ 	/// The link is considered bidirectional until this time.
+ 	double		sym_time_;
+ 	/// The link is considered unidirectional until this time.
+ 	double		asym_time_;
+ 	/// The link is considered lost until this time (used for link layer notification).
+ 	double		lost_time_;
+ 	/// Time at which this tuple expires and must be removed.
+ 	double		time_;
+ 	
+ 	inline nsaddr_t&	local_iface_addr()	{ return local_iface_addr_; }
+ 	inline nsaddr_t&	nb_iface_addr()		{ return nb_iface_addr_; }
+ 	inline double&		sym_time()		{ return sym_time_; }
+ 	inline double&		asym_time()		{ return asym_time_; }
+ 	inline double&		lost_time()		{ return lost_time_; }
+ 	inline double&		time()			{ return time_; }
+ } OLSR_link_tuple;
+ 
+ /// A Neighbor Tuple.
+ typedef struct OLSR_nb_tuple {
+ 	/// Main address of a neighbor node.
+ 	nsaddr_t nb_main_addr_;
+ 	/// Neighbor Type and Link Type at the four less significative digits.
+ 	u_int8_t status_;
+ 	/// A value between 0 and 7 specifying the node's willingness to carry traffic on behalf of other nodes.
+ 	u_int8_t willingness_;
+ 	
+ 	inline nsaddr_t&	nb_main_addr()	{ return nb_main_addr_; }
+ 	inline u_int8_t&	status()	{ return status_; }
+ 	inline u_int8_t&	willingness()	{ return willingness_; }
+ } OLSR_nb_tuple;
+ 
+ /// A 2-hop Tuple.
+ typedef struct OLSR_nb2hop_tuple {
+ 	/// Main address of a neighbor.
+ 	nsaddr_t	nb_main_addr_;
+ 	/// Main address of a 2-hop neighbor with a symmetric link to nb_main_addr.
+ 	nsaddr_t	nb2hop_addr_;
+ 	/// Time at which this tuple expires and must be removed.
+ 	double		time_;
+ 	
+ 	inline nsaddr_t&	nb_main_addr()	{ return nb_main_addr_; }
+ 	inline nsaddr_t&	nb2hop_addr()	{ return nb2hop_addr_; }
+ 	inline double&		time()		{ return time_; }
+ } OLSR_nb2hop_tuple;
+ 
+ /// An MPR-Selector Tuple.
+ typedef struct OLSR_mprsel_tuple {
+ 	/// Main address of a node which have selected this node as a MPR.
+ 	nsaddr_t	main_addr_;
+ 	/// Time at which this tuple expires and must be removed.
+ 	double		time_;
+ 	
+ 	inline nsaddr_t&	main_addr()	{ return main_addr_; }
+ 	inline double&		time()		{ return time_; }
+ } OLSR_mprsel_tuple;
+ 
+ /// The type "list of interface addresses"
+ typedef std::vector<nsaddr_t> addr_list_t;
+ 
+ /// A Duplicate Tuple
+ typedef struct OLSR_dup_tuple {
+ 	/// Originator address of the message.
+ 	nsaddr_t	addr_;
+ 	/// Message sequence number.
+ 	u_int16_t	seq_num_;
+ 	/// Indicates whether the message has been retransmitted or not.
+ 	bool		retransmitted_;
+ 	/// List of interfaces which the message has been received on.
+ 	addr_list_t	iface_list_;
+ 	/// Time at which this tuple expires and must be removed.
+ 	double		time_;
+ 	
+ 	inline nsaddr_t&	addr()		{ return addr_; }
+ 	inline u_int16_t&	seq_num()	{ return seq_num_; }
+ 	inline bool&		retransmitted()	{ return retransmitted_; }
+ 	inline addr_list_t&	iface_list()	{ return iface_list_; }
+ 	inline double&		time()		{ return time_; }
+ } OLSR_dup_tuple;
+ 
+ /// A Topology Tuple
+ typedef struct OLSR_topology_tuple {
+ 	/// Main address of the destination.
+ 	nsaddr_t	dest_addr_;
+ 	/// Main address of a node which is a neighbor of the destination.
+ 	nsaddr_t	last_addr_;
+ 	/// Sequence number.
+ 	u_int16_t	seq_;
+ 	/// Time at which this tuple expires and must be removed.
+ 	double		time_;
+ 	
+ 	inline nsaddr_t&	dest_addr()	{ return dest_addr_; }
+ 	inline nsaddr_t&	last_addr()	{ return last_addr_; }
+ 	inline u_int16_t&	seq()		{ return seq_; }
+ 	inline double&		time()		{ return time_; }
+ } OLSR_topology_tuple;
+ 
+ 
+ typedef std::set<nsaddr_t>			mprset_t;	///< MPR Set type.
+ typedef std::vector<OLSR_mprsel_tuple*>		mprselset_t;	///< MPR Selector Set type.
+ typedef std::vector<OLSR_link_tuple*>		linkset_t;	///< Link Set type.
+ typedef std::vector<OLSR_nb_tuple*>		nbset_t;	///< Neighbor Set type.
+ typedef std::vector<OLSR_nb2hop_tuple*>		nb2hopset_t;	///< 2-hop Neighbor Set type.
+ typedef std::vector<OLSR_topology_tuple*>	topologyset_t;	///< Topology Set type.
+ typedef std::vector<OLSR_dup_tuple*>		dupset_t;	///< Duplicate Set type.
+ typedef std::vector<OLSR_iface_assoc_tuple*>	ifaceassocset_t;///< Interface Association Set type.
+ 
+ #endif
diff --new-file --recursive --context=3 --minimal -x '*.[ao]' -x '*.nam' -x '*.tr' -x '*.cache' -x core -x '*.core' ns-2.27-ORIG/olsr/OLSR_rtable.cc ns-2.27/olsr/OLSR_rtable.cc
*** ns-2.27-ORIG/olsr/OLSR_rtable.cc	1970-01-01 01:00:00.000000000 +0100
--- ns-2.27/olsr/OLSR_rtable.cc	2005-03-11 11:38:59.000000000 +0100
***************
*** 0 ****
--- 1,171 ----
+ /***************************************************************************
+  *   Copyright (C) 2004 by Francisco J. Ros                                *
+  *   fjrm@dif.um.es                                                        *
+  *                                                                         *
+  *   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.             *
+  ***************************************************************************/
+ 
+ ///
+ /// \file	OLSR_rtable.cc
+ /// \brief	Implementation of our routing table.
+ ///
+ 
+ #include <olsr/OLSR.h>
+ #include <olsr/OLSR_rtable.h>
+ #include <olsr/OLSR_repositories.h>
+ 
+ ///
+ /// \brief Creates a new empty routing table.
+ ///
+ OLSR_rtable::OLSR_rtable() {
+ }
+ 
+ ///
+ /// \brief Destroys the routing table and all its entries.
+ ///
+ OLSR_rtable::~OLSR_rtable() {
+ 	// Iterates over the routing table deleting each OLSR_rt_entry*.
+ 	for (rtable_t::iterator it = rt_.begin(); it != rt_.end(); it++)
+ 		delete (*it).second;
+ }
+ 
+ ///
+ /// \brief Clears the routing table and frees the memory assigned to each one of its entries.
+ ///
+ void
+ OLSR_rtable::clear() {
+ 	// Iterates over the routing table deleting each OLSR_rt_entry*.
+ 	for (rtable_t::iterator it = rt_.begin(); it != rt_.end(); it++)
+ 		delete (*it).second;
+ 
+ 	// Cleans routing table.
+ 	rt_.clear();
+ }
+ 
+ ///
+ /// \brief Deletes the entry whose destination address is given.
+ /// \param dest	address of the destination node.
+ ///
+ void
+ OLSR_rtable::rm_entry(nsaddr_t dest) {
+ 	// Remove the pair whose key is dest
+ 	rt_.erase(dest);
+ }
+ 
+ ///
+ /// \brief Looks up an entry for the specified destination address.
+ /// \param dest	destination address.
+ /// \return	the routing table entry for that destination address, or NULL
+ ///		if such an entry does not exist
+ ///
+ OLSR_rt_entry*
+ OLSR_rtable::lookup(nsaddr_t dest) {
+ 	// Get the iterator at "dest" position
+ 	rtable_t::iterator it = rt_.find(dest);
+ 	// If there is no route to "dest", return NULL
+ 	if (it == rt_.end())
+ 		return NULL;
+ 	
+ 	// Returns the rt entry (second element of the pair)
+ 	return (*it).second;
+ }
+ 
+ ///
+ /// \brief	Finds the appropiate entry which must be used in order to forward
+ ///		a data packet to a next hop (given a destination).
+ ///
+ /// Imagine a routing table like this: [A,B] [B,C] [C,C]; being each pair of the
+ /// form [dest addr,next-hop addr]. In this case, if this function is invoked with
+ /// [A,B] then pair [C,C] is returned because C is the next hop that must be used
+ /// to forward a data packet destined to A. That is, C is a neighbor of this node,
+ /// but B isn't. This function finds the appropiate neighbor for forwarding a packet.
+ ///
+ /// \param entry	the routing table entry which indicates the destination node
+ ///			we are interested in.
+ /// \return		the appropiate routing table entry which indicates the next
+ ///			hop which must be used for forwarding a data packet, or NULL
+ ///			if there is no such entry.
+ ///
+ OLSR_rt_entry*
+ OLSR_rtable::find_send_entry(OLSR_rt_entry* entry) {
+ 	OLSR_rt_entry* e = entry;
+ 	while (e != NULL && e->dest_addr() != e->next_addr())
+ 		e = lookup(e->next_addr());
+ 	return e;
+ }
+ 
+ ///
+ /// \brief Adds a new entry into the routing table.
+ ///
+ /// If an entry for the given destination existed, it is deleted and freed.
+ ///
+ /// \param dest		address of the destination node.
+ /// \param next		address of the next hop node.
+ /// \param iface	address of the local interface.
+ /// \param dist		distance to the destination node.
+ /// \return		the routing table entry which has been added.
+ ///
+ OLSR_rt_entry*
+ OLSR_rtable::add_entry(nsaddr_t dest, nsaddr_t next, nsaddr_t iface, u_int32_t dist) {
+ 	// Creates a new rt entry with specified values
+ 	OLSR_rt_entry* entry = new OLSR_rt_entry();
+ 	entry->dest_addr()	= dest;
+ 	entry->next_addr()	= next;
+ 	entry->iface_addr()	= iface;
+ 	entry->dist()		= dist;
+ 	
+ 	// Inserts the new entry
+ 	rtable_t::iterator it = rt_.find(dest);
+ 	if (it != rt_.end())
+ 		delete (*it).second;
+ 	rt_[dest] = entry;
+ 	
+ 	// Returns the new rt entry
+ 	return entry;
+ }
+ 
+ ///
+ /// \brief Returns the number of entries in the routing table.
+ /// \return the number of entries in the routing table.
+ ///
+ u_int32_t
+ OLSR_rtable::size() {
+ 	return rt_.size();
+ }
+ 
+ ///
+ /// \brief Prints out the content of the routing table to a given trace file.
+ ///
+ /// Content is represented as a table in which each line is preceeded by a 'P'.
+ /// First line contains the name of every column (dest, next, iface, dist)
+ /// and the following ones are the values of each entry.
+ ///
+ /// \param out the Trace where the routing table must be written into.
+ ///
+ void
+ OLSR_rtable::print(Trace* out) {	
+ 	sprintf(out->pt_->buffer(), "P\tdest\tnext\tiface\tdist");
+ 	out->pt_->dump();
+ 	for (rtable_t::iterator it = rt_.begin(); it != rt_.end(); it++) {
+ 		OLSR_rt_entry* entry = (*it).second;
+ 		sprintf(out->pt_->buffer(), "P\t%d\t%d\t%d\t%d",
+ 			OLSR::node_id(entry->dest_addr()),
+ 			OLSR::node_id(entry->next_addr()),
+ 			OLSR::node_id(entry->iface_addr()),
+ 			entry->dist());
+ 		out->pt_->dump();
+ 	}
+ }
diff --new-file --recursive --context=3 --minimal -x '*.[ao]' -x '*.nam' -x '*.tr' -x '*.cache' -x core -x '*.core' ns-2.27-ORIG/olsr/OLSR_rtable.h ns-2.27/olsr/OLSR_rtable.h
*** ns-2.27-ORIG/olsr/OLSR_rtable.h	1970-01-01 01:00:00.000000000 +0100
--- ns-2.27/olsr/OLSR_rtable.h	2005-03-11 11:38:59.000000000 +0100
***************
*** 0 ****
--- 1,61 ----
+ /***************************************************************************
+  *   Copyright (C) 2004 by Francisco J. Ros                                *
+  *   fjrm@dif.um.es                                                        *
+  *                                                                         *
+  *   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.             *
+  ***************************************************************************/
+ 
+ ///
+ /// \file	OLSR_rtable.h
+ /// \brief	Header file for routing table's related stuff.
+ ///
+ 
+ #ifndef __OLSR_rtable_h__
+ #define __OLSR_rtable_h__
+ 
+ #include <olsr/OLSR_repositories.h>
+ #include <trace.h>
+ #include <map>
+ 
+ ///
+ /// \brief Defines rtable_t as a map of OLSR_rt_entry, whose key is the destination address.
+ ///
+ /// The routing table is thus defined as pairs: [dest address, entry]. Each element
+ /// of the pair can be accesed via "first" and "second" members.
+ ///
+ typedef std::map<nsaddr_t, OLSR_rt_entry*> rtable_t;
+ 
+ ///
+ /// \brief This class is a representation of the OLSR's Routing Table.
+ ///
+ class OLSR_rtable {
+ 	rtable_t	rt_;	///< Data structure for the routing table.
+ 
+ public:
+ 	
+ 	OLSR_rtable();
+ 	~OLSR_rtable();
+ 	
+ 	void		clear();
+ 	void		rm_entry(nsaddr_t dest);
+ 	OLSR_rt_entry*	add_entry(nsaddr_t dest, nsaddr_t next, nsaddr_t iface, u_int32_t dist);
+ 	OLSR_rt_entry*	lookup(nsaddr_t dest);
+ 	OLSR_rt_entry*	find_send_entry(OLSR_rt_entry*);
+ 	u_int32_t	size();
+ 	void		print(Trace*);
+ };
+ 
+ #endif
diff --new-file --recursive --context=3 --minimal -x '*.[ao]' -x '*.nam' -x '*.tr' -x '*.cache' -x core -x '*.core' ns-2.27-ORIG/olsr/OLSR_state.cc ns-2.27/olsr/OLSR_state.cc
*** ns-2.27-ORIG/olsr/OLSR_state.cc	1970-01-01 01:00:00.000000000 +0100
--- ns-2.27/olsr/OLSR_state.cc	2005-03-11 11:38:59.000000000 +0100
***************
*** 0 ****
--- 1,338 ----
+ /***************************************************************************
+  *   Copyright (C) 2004 by Francisco J. Ros                                *
+  *   fjrm@dif.um.es                                                        *
+  *                                                                         *
+  *   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.             *
+  ***************************************************************************/
+ 
+ ///
+ /// \file	OLSR_state.cc
+ /// \brief	Implementation of all functions needed for manipulating the internal
+ ///		state of an OLSR node.
+ ///
+ 
+ #include <olsr/OLSR_state.h>
+ #include <olsr/OLSR.h>
+ 
+ /********** MPR Selector Set Manipulation **********/
+ 
+ OLSR_mprsel_tuple*
+ OLSR_state::find_mprsel_tuple(nsaddr_t main_addr) {
+ 	for (mprselset_t::iterator it = mprselset_.begin(); it != mprselset_.end(); it++) {
+ 		OLSR_mprsel_tuple* tuple = *it;
+ 		if (tuple->main_addr() == main_addr)
+ 			return tuple;
+ 	}
+ 	return NULL;
+ }
+ 
+ void
+ OLSR_state::erase_mprsel_tuple(OLSR_mprsel_tuple* tuple) {
+ 	for (mprselset_t::iterator it = mprselset_.begin(); it != mprselset_.end(); it++) {
+ 		if (*it == tuple) {
+ 			mprselset_.erase(it);
+ 			break;
+ 		}
+ 	}
+ }
+ 
+ void
+ OLSR_state::erase_mprsel_tuples(nsaddr_t main_addr) {
+ 	for (mprselset_t::iterator it = mprselset_.begin(); it != mprselset_.end(); it++) {
+ 		OLSR_mprsel_tuple* tuple = *it;
+ 		if (tuple->main_addr() == main_addr) {
+ 			it = mprselset_.erase(it);
+ 			it--;
+ 		}
+ 	}
+ }
+ 
+ void
+ OLSR_state::insert_mprsel_tuple(OLSR_mprsel_tuple* tuple) {
+ 	mprselset_.push_back(tuple);
+ }
+ 
+ /********** Neighbor Set Manipulation **********/
+ 
+ OLSR_nb_tuple*
+ OLSR_state::find_nb_tuple(nsaddr_t main_addr) {
+ 	for (nbset_t::iterator it = nbset_.begin(); it != nbset_.end(); it++) {
+ 		OLSR_nb_tuple* tuple = *it;
+ 		if (tuple->nb_main_addr() == main_addr)
+ 			return tuple;
+ 	}
+ 	return NULL;
+ }
+ 
+ OLSR_nb_tuple*
+ OLSR_state::find_sym_nb_tuple(nsaddr_t main_addr) {
+ 	for (nbset_t::iterator it = nbset_.begin(); it != nbset_.end(); it++) {
+ 		OLSR_nb_tuple* tuple = *it;
+ 		if (tuple->nb_main_addr() == main_addr && tuple->status() == OLSR_STATUS_SYM)
+ 			return tuple;
+ 	}
+ 	return NULL;
+ }
+ 
+ OLSR_nb_tuple*
+ OLSR_state::find_nb_tuple(nsaddr_t main_addr, u_int8_t willingness) {
+ 	for (nbset_t::iterator it = nbset_.begin(); it != nbset_.end(); it++) {
+ 		OLSR_nb_tuple* tuple = *it;
+ 		if (tuple->nb_main_addr() == main_addr && tuple->willingness() == willingness)
+ 			return tuple;
+ 	}
+ 	return NULL;
+ }
+ 
+ void
+ OLSR_state::erase_nb_tuple(OLSR_nb_tuple* tuple) {
+ 	for (nbset_t::iterator it = nbset_.begin(); it != nbset_.end(); it++) {
+ 		if (*it == tuple) {
+ 			nbset_.erase(it);
+ 			break;
+ 		}
+ 	}
+ }
+ 
+ void
+ OLSR_state::erase_nb_tuple(nsaddr_t main_addr) {
+ 	for (nbset_t::iterator it = nbset_.begin(); it != nbset_.end(); it++) {
+ 		OLSR_nb_tuple* tuple = *it;
+ 		if (tuple->nb_main_addr() == main_addr) {
+ 			it = nbset_.erase(it);
+ 			break;
+ 		}
+ 	}
+ }
+ 
+ void
+ OLSR_state::insert_nb_tuple(OLSR_nb_tuple* tuple) {
+ 	nbset_.push_back(tuple);
+ }
+ 
+ /********** Neighbor 2 Hop Set Manipulation **********/
+ 
+ OLSR_nb2hop_tuple*
+ OLSR_state::find_nb2hop_tuple(nsaddr_t nb_main_addr, nsaddr_t nb2hop_addr) {
+ 	for (nb2hopset_t::iterator it = nb2hopset_.begin(); it != nb2hopset_.end(); it++) {
+ 		OLSR_nb2hop_tuple* tuple = *it;
+ 		if (tuple->nb_main_addr() == nb_main_addr && tuple->nb2hop_addr() == nb2hop_addr)
+ 			return tuple;
+ 	}
+ 	return NULL;
+ }
+ 
+ void
+ OLSR_state::erase_nb2hop_tuple(OLSR_nb2hop_tuple* tuple) {
+ 	for (nb2hopset_t::iterator it = nb2hopset_.begin(); it != nb2hopset_.end(); it++) {
+ 		if (*it == tuple) {
+ 			nb2hopset_.erase(it);
+ 			break;
+ 		}
+ 	}
+ }
+ 
+ void
+ OLSR_state::erase_nb2hop_tuples(nsaddr_t nb_main_addr, nsaddr_t nb2hop_addr) {
+ 	for (nb2hopset_t::iterator it = nb2hopset_.begin(); it != nb2hopset_.end(); it++) {
+ 		OLSR_nb2hop_tuple* tuple = *it;
+ 		if (tuple->nb_main_addr() == nb_main_addr && tuple->nb2hop_addr() == nb2hop_addr) {
+ 			it = nb2hopset_.erase(it);
+ 			it--;
+ 		}
+ 	}
+ }
+ 
+ void
+ OLSR_state::erase_nb2hop_tuples(nsaddr_t nb_main_addr) {
+ 	for (nb2hopset_t::iterator it = nb2hopset_.begin(); it != nb2hopset_.end(); it++) {
+ 		OLSR_nb2hop_tuple* tuple = *it;
+ 		if (tuple->nb_main_addr() == nb_main_addr) {
+ 			it = nb2hopset_.erase(it);
+ 			it--;
+ 		}
+ 	}
+ }
+ 
+ void
+ OLSR_state::insert_nb2hop_tuple(OLSR_nb2hop_tuple* tuple){
+ 	nb2hopset_.push_back(tuple);
+ }
+ 
+ /********** MPR Set Manipulation **********/
+ 
+ bool
+ OLSR_state::find_mpr_addr(nsaddr_t addr) {
+ 	mprset_t::iterator it = mprset_.find(addr);
+ 	return (it != mprset_.end());
+ }
+ 
+ void
+ OLSR_state::insert_mpr_addr(nsaddr_t addr) {
+ 	mprset_.insert(addr);
+ }
+ 
+ void
+ OLSR_state::clear_mprset() {
+ 	mprset_.clear();
+ }
+ 
+ /********** Duplicate Set Manipulation **********/
+ 
+ OLSR_dup_tuple*
+ OLSR_state::find_dup_tuple(nsaddr_t addr, u_int16_t seq_num) {
+ 	for (dupset_t::iterator it = dupset_.begin(); it != dupset_.end(); it++) {
+ 		OLSR_dup_tuple* tuple = *it;
+ 		if (tuple->addr() == addr && tuple->seq_num() == seq_num)
+ 			return tuple;
+ 	}
+ 	return NULL;
+ }
+ 
+ void
+ OLSR_state::erase_dup_tuple(OLSR_dup_tuple* tuple) {
+ 	for (dupset_t::iterator it = dupset_.begin(); it != dupset_.end(); it++) {
+ 		if (*it == tuple) {
+ 			dupset_.erase(it);
+ 			break;
+ 		}
+ 	}
+ }
+ 
+ void
+ OLSR_state::insert_dup_tuple(OLSR_dup_tuple* tuple) {
+ 	dupset_.push_back(tuple);
+ }
+ 
+ /********** Link Set Manipulation **********/
+ 
+ OLSR_link_tuple*
+ OLSR_state::find_link_tuple(nsaddr_t iface_addr) {
+ 	for (linkset_t::iterator it = linkset_.begin(); it != linkset_.end(); it++) {
+ 		OLSR_link_tuple* tuple = *it;
+ 		if (tuple->nb_iface_addr() == iface_addr)
+ 			return tuple;
+ 	}
+ 	return NULL;
+ }
+ 
+ OLSR_link_tuple*
+ OLSR_state::find_sym_link_tuple(nsaddr_t iface_addr, double now) {
+ 	for (linkset_t::iterator it = linkset_.begin(); it != linkset_.end(); it++) {
+ 		OLSR_link_tuple* tuple = *it;
+ 		if (tuple->nb_iface_addr() == iface_addr) {
+ 			if (tuple->sym_time() > now)
+ 				return tuple;
+ 			else
+ 				break;
+ 		}
+ 	}
+ 	return NULL;
+ }
+ 
+ void
+ OLSR_state::erase_link_tuple(OLSR_link_tuple* tuple) {
+ 	for (linkset_t::iterator it = linkset_.begin(); it != linkset_.end(); it++) {
+ 		if (*it == tuple) {
+ 			linkset_.erase(it);
+ 			break;
+ 		}
+ 	}
+ }
+ 
+ void
+ OLSR_state::insert_link_tuple(OLSR_link_tuple* tuple) {
+ 	linkset_.push_back(tuple);
+ }
+ 
+ /********** Topology Set Manipulation **********/
+ 
+ OLSR_topology_tuple*
+ OLSR_state::find_topology_tuple(nsaddr_t dest_addr, nsaddr_t last_addr) {
+ 	for (topologyset_t::iterator it = topologyset_.begin(); it != topologyset_.end(); it++) {
+ 		OLSR_topology_tuple* tuple = *it;
+ 		if (tuple->dest_addr() == dest_addr && tuple->last_addr() == last_addr)
+ 			return tuple;
+ 	}
+ 	return NULL;
+ }
+ 
+ OLSR_topology_tuple*
+ OLSR_state::find_newer_topology_tuple(nsaddr_t last_addr, u_int16_t ansn) {
+ 	for (topologyset_t::iterator it = topologyset_.begin(); it != topologyset_.end(); it++) {
+ 		OLSR_topology_tuple* tuple = *it;
+ 		if (tuple->last_addr() == last_addr && tuple->seq() > ansn)
+ 			return tuple;
+ 	}
+ 	return NULL;
+ }
+ 
+ void
+ OLSR_state::erase_topology_tuple(OLSR_topology_tuple* tuple) {
+ 	for (topologyset_t::iterator it = topologyset_.begin(); it != topologyset_.end(); it++) {
+ 		if (*it == tuple) {
+ 			topologyset_.erase(it);
+ 			break;
+ 		}
+ 	}
+ }
+ 
+ void
+ OLSR_state::erase_older_topology_tuples(nsaddr_t last_addr, u_int16_t ansn) {
+ 	for (topologyset_t::iterator it = topologyset_.begin(); it != topologyset_.end(); it++) {
+ 		OLSR_topology_tuple* tuple = *it;
+ 		if (tuple->last_addr() == last_addr && tuple->seq() < ansn) {
+ 			it = topologyset_.erase(it);
+ 			it--;
+ 		}
+ 	}
+ }
+ 
+ void
+ OLSR_state::insert_topology_tuple(OLSR_topology_tuple* tuple) {
+ 	topologyset_.push_back(tuple);
+ }
+ 
+ /********** Interface Association Set Manipulation **********/
+ 
+ OLSR_iface_assoc_tuple*
+ OLSR_state::find_ifaceassoc_tuple(nsaddr_t iface_addr) {
+ 	for (ifaceassocset_t::iterator it = ifaceassocset_.begin();
+ 		it != ifaceassocset_.end();
+ 		it++) {
+ 		OLSR_iface_assoc_tuple* tuple = *it;
+ 		if (tuple->iface_addr() == iface_addr)
+ 			return tuple;
+ 	}
+ 	return NULL;
+ }
+ 
+ void
+ OLSR_state::erase_ifaceassoc_tuple(OLSR_iface_assoc_tuple* tuple) {
+ 	for (ifaceassocset_t::iterator it = ifaceassocset_.begin();
+ 		it != ifaceassocset_.end();
+ 		it++) {
+ 		if (*it == tuple) {
+ 			ifaceassocset_.erase(it);
+ 			break;
+ 		}
+ 	}
+ }
+ 
+ void
+ OLSR_state::insert_ifaceassoc_tuple(OLSR_iface_assoc_tuple* tuple) {
+ 	ifaceassocset_.push_back(tuple);
+ }
diff --new-file --recursive --context=3 --minimal -x '*.[ao]' -x '*.nam' -x '*.tr' -x '*.cache' -x core -x '*.core' ns-2.27-ORIG/olsr/OLSR_state.h ns-2.27/olsr/OLSR_state.h
*** ns-2.27-ORIG/olsr/OLSR_state.h	1970-01-01 01:00:00.000000000 +0100
--- ns-2.27/olsr/OLSR_state.h	2005-03-11 11:38:59.000000000 +0100
***************
*** 0 ****
--- 1,97 ----
+ /***************************************************************************
+  *   Copyright (C) 2004 by Francisco J. Ros                                *
+  *   fjrm@dif.um.es                                                        *
+  *                                                                         *
+  *   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.             *
+  ***************************************************************************/
+ 
+ ///
+ /// \file	OLSR_state.h
+ /// \brief	This header file declares and defines internal state of an OLSR node.
+ ///
+ 
+ #ifndef __OLSR_state_h__
+ #define __OLSR_state_h__
+ 
+ #include <olsr/OLSR_repositories.h>
+ 
+ /// This class encapsulates all data structures needed for maintaining internal state of an OLSR node.
+ class OLSR_state {
+ 	friend class OLSR;
+ 	
+ 	linkset_t	linkset_;	///< Link Set (RFC 3626, section 4.2.1).
+ 	nbset_t		nbset_;		///< Neighbor Set (RFC 3626, section 4.3.1).
+ 	nb2hopset_t	nb2hopset_;	///< 2-hop Neighbor Set (RFC 3626, section 4.3.2).
+ 	topologyset_t	topologyset_;	///< Topology Set (RFC 3626, section 4.4).
+ 	mprset_t	mprset_;	///< MPR Set (RFC 3626, section 4.3.3).
+ 	mprselset_t	mprselset_;	///< MPR Selector Set (RFC 3626, section 4.3.4).
+ 	dupset_t	dupset_;	///< Duplicate Set (RFC 3626, section 3.4).
+ 	ifaceassocset_t	ifaceassocset_;	///< Interface Association Set (RFC 3626, section 4.1).
+ 	
+ protected:
+ 	inline	linkset_t&		linkset()	{ return linkset_; }
+ 	inline	mprset_t&		mprset()	{ return mprset_; }
+ 	inline	mprselset_t&		mprselset()	{ return mprselset_; }
+ 	inline	nbset_t&		nbset()		{ return nbset_; }
+ 	inline	nb2hopset_t&		nb2hopset()	{ return nb2hopset_; }
+ 	inline	topologyset_t&		topologyset()	{ return topologyset_; }
+ 	inline	dupset_t&		dupset()	{ return dupset_; }
+ 	inline	ifaceassocset_t&	ifaceassocset()	{ return ifaceassocset_; }
+ 	
+ 	OLSR_mprsel_tuple*	find_mprsel_tuple(nsaddr_t);
+ 	void			erase_mprsel_tuple(OLSR_mprsel_tuple*);
+ 	void			erase_mprsel_tuples(nsaddr_t);
+ 	void			insert_mprsel_tuple(OLSR_mprsel_tuple*);
+ 	
+ 	OLSR_nb_tuple*		find_nb_tuple(nsaddr_t);
+ 	OLSR_nb_tuple*		find_sym_nb_tuple(nsaddr_t);
+ 	OLSR_nb_tuple*		find_nb_tuple(nsaddr_t, u_int8_t);
+ 	void			erase_nb_tuple(OLSR_nb_tuple*);
+ 	void			erase_nb_tuple(nsaddr_t);
+ 	void			insert_nb_tuple(OLSR_nb_tuple*);
+ 	
+ 	OLSR_nb2hop_tuple*	find_nb2hop_tuple(nsaddr_t, nsaddr_t);
+ 	void			erase_nb2hop_tuple(OLSR_nb2hop_tuple*);
+ 	void			erase_nb2hop_tuples(nsaddr_t);
+ 	void			erase_nb2hop_tuples(nsaddr_t, nsaddr_t);
+ 	void			insert_nb2hop_tuple(OLSR_nb2hop_tuple*);
+ 
+ 	bool			find_mpr_addr(nsaddr_t);
+ 	void			insert_mpr_addr(nsaddr_t);
+ 	void			clear_mprset();
+ 	
+ 	OLSR_dup_tuple*		find_dup_tuple(nsaddr_t, u_int16_t);
+ 	void			erase_dup_tuple(OLSR_dup_tuple*);
+ 	void			insert_dup_tuple(OLSR_dup_tuple*);
+ 	
+ 	OLSR_link_tuple*	find_link_tuple(nsaddr_t);
+ 	OLSR_link_tuple*	find_sym_link_tuple(nsaddr_t, double);
+ 	void			erase_link_tuple(OLSR_link_tuple*);
+ 	void			insert_link_tuple(OLSR_link_tuple*);
+ 
+ 	OLSR_topology_tuple*	find_topology_tuple(nsaddr_t, nsaddr_t);
+ 	OLSR_topology_tuple*	find_newer_topology_tuple(nsaddr_t, u_int16_t);
+ 	void			erase_topology_tuple(OLSR_topology_tuple*);
+ 	void			erase_older_topology_tuples(nsaddr_t, u_int16_t);
+ 	void			insert_topology_tuple(OLSR_topology_tuple*);
+ 	
+ 	OLSR_iface_assoc_tuple* find_ifaceassoc_tuple(nsaddr_t);
+ 	void			erase_ifaceassoc_tuple(OLSR_iface_assoc_tuple*);
+ 	void			insert_ifaceassoc_tuple(OLSR_iface_assoc_tuple*);
+ 	
+ };
+ 
+ #endif
diff --new-file --recursive --context=3 --minimal -x '*.[ao]' -x '*.nam' -x '*.tr' -x '*.cache' -x core -x '*.core' ns-2.27-ORIG/queue/priqueue.cc ns-2.27/queue/priqueue.cc
*** ns-2.27-ORIG/queue/priqueue.cc	2005-03-11 11:38:20.000000000 +0100
--- ns-2.27/queue/priqueue.cc	2005-03-11 11:39:30.000000000 +0100
***************
*** 90,95 ****
--- 90,96 ----
  		case PT_MESSAGE:
                  case PT_TORA:
                  case PT_AODV:
+ 		case PT_OLSR:
                          recvHighPriority(p, h);
                          break;
  
diff --new-file --recursive --context=3 --minimal -x '*.[ao]' -x '*.nam' -x '*.tr' -x '*.cache' -x core -x '*.core' ns-2.27-ORIG/tcl/lib/ns-default.tcl ns-2.27/tcl/lib/ns-default.tcl
*** ns-2.27-ORIG/tcl/lib/ns-default.tcl	2005-03-11 11:38:22.000000000 +0100
--- ns-2.27/tcl/lib/ns-default.tcl	2005-03-11 11:39:49.000000000 +0100
***************
*** 1268,1270 ****
--- 1268,1278 ----
  # Quick Start definitions end here
  
  Delayer set debug_ false
+ 
+ # Defaults defined for OLSR
+ Agent/OLSR set debug_       false
+ Agent/OLSR set use_mac_     false
+ Agent/OLSR set willingness_ 3
+ Agent/OLSR set hello_ival_  2
+ Agent/OLSR set tc_ival_     5
+ Agent/OLSR set mid_ival_    5
diff --new-file --recursive --context=3 --minimal -x '*.[ao]' -x '*.nam' -x '*.tr' -x '*.cache' -x core -x '*.core' ns-2.27-ORIG/tcl/lib/ns-lib.tcl ns-2.27/tcl/lib/ns-lib.tcl
*** ns-2.27-ORIG/tcl/lib/ns-lib.tcl	2005-03-11 11:38:22.000000000 +0100
--- ns-2.27/tcl/lib/ns-lib.tcl	2005-03-11 11:39:49.000000000 +0100
***************
*** 600,605 ****
--- 600,608 ----
  	    AODV {
  		    set ragent [$self create-aodv-agent $node]
  	    }
+ 	    OLSR {
+ 		    set ragent [$self create-olsr-agent $node]
+ 	    }
  	    TORA {
  		    Simulator set IMEPFlag_ ON
  		    set ragent [$self create-tora-agent $node]
***************
*** 789,794 ****
--- 792,805 ----
          return $ragent
  }
  
+ Simulator instproc create-olsr-agent { node } {
+ 	#  Create OLSR routing agent
+ 	set ragent [new Agent/OLSR [$node node-addr]]
+ 	$self at 0.0 "$ragent start"
+ 	$node set ragent_ $ragent
+ 	return $ragent
+ }
+ 
  Simulator instproc use-newtrace {} {
  	Simulator set WirelessNewTrace_ 1
  } 
diff --new-file --recursive --context=3 --minimal -x '*.[ao]' -x '*.nam' -x '*.tr' -x '*.cache' -x core -x '*.core' ns-2.27-ORIG/tcl/lib/ns-packet.tcl ns-2.27/tcl/lib/ns-packet.tcl
*** ns-2.27-ORIG/tcl/lib/ns-packet.tcl	2005-03-11 11:38:22.000000000 +0100
--- ns-2.27/tcl/lib/ns-packet.tcl	2005-03-11 11:39:49.000000000 +0100
***************
*** 111,116 ****
--- 111,117 ----
  }
  
  foreach prot {
+ 	OLSR
  	AODV
  	ARP
    	aSRM 
diff --new-file --recursive --context=3 --minimal -x '*.[ao]' -x '*.nam' -x '*.tr' -x '*.cache' -x core -x '*.core' ns-2.27-ORIG/trace/cmu-trace.cc ns-2.27/trace/cmu-trace.cc
*** ns-2.27-ORIG/trace/cmu-trace.cc	2005-03-11 11:38:26.000000000 +0100
--- ns-2.27/trace/cmu-trace.cc	2005-03-11 11:39:58.000000000 +0100
***************
*** 51,59 ****
--- 51,61 ----
  #include <tora/tora_packet.h> //TORA
  #include <imep/imep_spec.h>         // IMEP
  #include <aodv/aodv_packet.h> //AODV
+ #include <olsr/OLSR_pkt.h> // OLSR
  #include <cmu-trace.h>
  #include <mobilenode.h>
  #include <simulator.h>
+ #include <string.h>
  
  #include "diffusion/diff_header.h" // DIFFUSION -- Chalermek
  
***************
*** 821,828 ****
  				rp->rp_dst_seqno,
  				rp->rp_lifetime,
  				rp->rp_type == AODVTYPE_RREP ? "REPLY" :
! 				(rp->rp_type == AODVTYPE_RERR ? "ERROR" :
! 				 "HELLO"));
  	        } else {
  			
  			sprintf(pt_->buffer() + offset,
--- 823,830 ----
  				rp->rp_dst_seqno,
  				rp->rp_lifetime,
  				rp->rp_type == AODVTYPE_RREP ? "REPLY" :
! 			    (rp->rp_type == AODVTYPE_RERR ? "ERROR" :
! 			     "HELLO"));
  	        } else {
  			
  			sprintf(pt_->buffer() + offset,
***************
*** 833,840 ****
  				rp->rp_dst_seqno,
  				rp->rp_lifetime,
  				rp->rp_type == AODVTYPE_RREP ? "REPLY" :
! 				(rp->rp_type == AODVTYPE_RERR ? "ERROR" :
! 				 "HELLO"));
  		}
                  break;
  		
--- 835,842 ----
  				rp->rp_dst_seqno,
  				rp->rp_lifetime,
  				rp->rp_type == AODVTYPE_RREP ? "REPLY" :
! 			    (rp->rp_type == AODVTYPE_RERR ? "ERROR" :
! 			     "HELLO"));
  		}
                  break;
  		
***************
*** 851,856 ****
--- 853,933 ----
  }
  
  void
+ CMUTrace::format_olsr(Packet *p, int offset)
+ {
+ 	OLSR_pkt* op = PKT_OLSR(p);
+ 
+ 	if (pt_->tagged()) {
+ 		sprintf(pt_->buffer() + offset,
+ 			"-olsr:n %d -olsr:s %d ",
+ 			op->count,
+ 			op->pkt_seq_num());
+ 		
+ 		int len = strlen(pt_->buffer());
+ 		for (int i = 0; i < op->count; i++) {
+ 			const char *s;
+ 			if (op->msg(i).msg_type() == OLSR_HELLO_MSG)
+ 				s = "-olsr:t HELLO -olsr:o %d -olsr:h %d -olsr:ms %d ";
+ 			else if (op->msg(i).msg_type() == OLSR_TC_MSG)
+ 				s = "-olsr:t TC -olsr:o %d -olsr:h %d -olsr:ms %d ";
+ 			else
+ 				s = "-olsr:t UNKNOWN -olsr:o %d -olsr:h %d -olsr:ms %d ";
+ 			sprintf(pt_->buffer() + len, s,
+ 				op->msg(i).orig_addr(),
+ 				op->msg(i).hop_count(),
+ 				op->msg(i).msg_seq_num());
+ 			len = strlen(pt_->buffer());
+ 		}
+ 	}
+ 	else if (newtrace_) {
+ 		sprintf(pt_->buffer() + offset,
+ 			"-P olsr -Pn %d -Ps %d ",
+ 			op->count,
+ 			op->pkt_seq_num());
+ 		
+ 		int len = strlen(pt_->buffer());
+ 		for (int i = 0; i < op->count; i++) {
+ 			const char *s;
+ 			if (op->msg(i).msg_type() == OLSR_HELLO_MSG)
+ 				s = "[-Pt HELLO -Po %d -Ph %d -Pms %d] ";
+ 			else if (op->msg(i).msg_type() == OLSR_TC_MSG)
+ 				s = "[-Pt TC -Po %d -Ph %d -Pms %d] ";
+ 			else
+ 				s = "[-Pt UNKNOWN -Po %d -Ph %d -Pms %d] ";
+ 			sprintf(pt_->buffer() + len, s,
+ 				op->msg(i).orig_addr(),
+ 				op->msg(i).hop_count(),
+ 				op->msg(i).msg_seq_num());
+ 			len = strlen(pt_->buffer());
+ 		}
+ 	}
+ 	else {
+ 		sprintf(pt_->buffer() + offset,
+ 			"[%d %d ",
+ 			op->count,
+ 			op->pkt_seq_num());
+ 		
+ 		int len = strlen(pt_->buffer());
+ 		for (int i = 0; i < op->count; i++) {
+ 			const char *s;
+ 			if (op->msg(i).msg_type() == OLSR_HELLO_MSG)
+ 				s = "[HELLO %d %d %d]";
+ 			else if (op->msg(i).msg_type() == OLSR_TC_MSG)
+ 				s = "[TC %d %d %d]";
+ 			else
+ 				s = "[UNKNOWN %d %d %d]";
+ 			sprintf(pt_->buffer() + len, s,
+ 				op->msg(i).orig_addr(),
+ 				op->msg(i).hop_count(),
+ 				op->msg(i).msg_seq_num());
+ 			len = strlen(pt_->buffer());
+ 		}
+ 		
+ 		sprintf(pt_->buffer() + len, "]");
+ 	}
+ }
+ 
+ void
  CMUTrace::nam_format(Packet *p, int offset)
  {
  	Node* srcnode = 0 ;
***************
*** 1058,1063 ****
--- 1135,1143 ----
  		case PT_GAF:
  		case PT_PING:
  			break;
+ 		case PT_OLSR:
+ 			format_olsr(p, offset);
+ 			break;
  		default:
  			fprintf(stderr, "%s - invalid packet type (%s).\n",
  				__PRETTY_FUNCTION__, packet_info.name(ch->ptype()));
diff --new-file --recursive --context=3 --minimal -x '*.[ao]' -x '*.nam' -x '*.tr' -x '*.cache' -x core -x '*.core' ns-2.27-ORIG/trace/cmu-trace.h ns-2.27/trace/cmu-trace.h
*** ns-2.27-ORIG/trace/cmu-trace.h	2005-03-11 11:38:26.000000000 +0100
--- ns-2.27/trace/cmu-trace.h	2005-03-11 11:39:58.000000000 +0100
***************
*** 125,130 ****
--- 125,131 ----
  	void	format_tora(Packet *p, int offset);
          void    format_imep(Packet *p, int offset);
          void    format_aodv(Packet *p, int offset);
+ 	void	format_olsr(Packet *p, int offset);
  };
  
  #endif /* __cmu_trace__ */
