diff --new-file --recursive --context=3 --minimal -x '*.[ao]' -x '*.nam' -x '*.tr' -x '*.tar' -x '*.cache' -x core -x '*.core' -x '*.orig' -x '*.rej' -x '*.*~' -x ns_tcl.cc ns-2.33-orig/Makefile ns-2.33/Makefile *** ns-2.33-orig/Makefile 2009-03-04 23:00:32.000000000 +0000 --- ns-2.33/Makefile 2009-03-02 22:36:31.000000000 +0000 *************** *** 271,276 **** --- 271,277 ---- 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 '*.tar' -x '*.cache' -x core -x '*.core' -x '*.orig' -x '*.rej' -x '*.*~' -x ns_tcl.cc ns-2.33-orig/common/packet.cc ns-2.33/common/packet.cc *** ns-2.33-orig/common/packet.cc 2009-03-04 23:00:31.000000000 +0000 --- ns-2.33/common/packet.cc 2009-03-02 22:36:31.000000000 +0000 *************** *** 66,71 **** --- 66,72 ---- 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 '*.tar' -x '*.cache' -x core -x '*.core' -x '*.orig' -x '*.rej' -x '*.*~' -x ns_tcl.cc ns-2.33-orig/common/packet.h ns-2.33/common/packet.h *** ns-2.33-orig/common/packet.h 2009-03-04 23:00:31.000000000 +0000 --- ns-2.33/common/packet.h 2009-03-02 22:43:40.000000000 +0000 *************** *** 179,186 **** // Bell Labs Traffic Trace Type (PackMime OL) static const packet_t PT_BLTRACE = 60; // insert new packet types here ! static packet_t PT_NTYPE = 61; // This MUST be the LAST one enum packetClass { --- 179,189 ---- // Bell Labs Traffic Trace Type (PackMime OL) static const packet_t PT_BLTRACE = 60; + // um-olsr + static const packet_t PT_OLSR = 61; + // insert new packet types here ! static packet_t PT_NTYPE = 62; // This MUST be the LAST one enum packetClass { *************** *** 373,378 **** --- 376,383 ---- // XCP name_[PT_XCP]="xcp"; + + name_[PT_OLSR]= "OLSR"; // Bell Labs (PackMime OL) name_[PT_BLTRACE]="BellLabsTrace"; diff --new-file --recursive --context=3 --minimal -x '*.[ao]' -x '*.nam' -x '*.tr' -x '*.tar' -x '*.cache' -x core -x '*.core' -x '*.orig' -x '*.rej' -x '*.*~' -x ns_tcl.cc ns-2.33-orig/gen/ptypes.cc ns-2.33/gen/ptypes.cc *** ns-2.33-orig/gen/ptypes.cc 2009-03-04 23:00:32.000000000 +0000 --- ns-2.33/gen/ptypes.cc 2009-03-02 22:51:59.000000000 +0000 *************** *** 124,129 **** --- 124,131 ---- set pvals(59) HDLC\n\ set ptype(belllabstrace) 60\n\ set pvals(60) BellLabsTrace\n\ + set ptype(olsr) 61\n\ + set pvals(61) OLSR\n\ proc ptype2val {str} {\n\ global ptype\n\ set str [string tolower $str]\n\ diff --new-file --recursive --context=3 --minimal -x '*.[ao]' -x '*.nam' -x '*.tr' -x '*.tar' -x '*.cache' -x core -x '*.core' -x '*.orig' -x '*.rej' -x '*.*~' -x ns_tcl.cc ns-2.33-orig/indep-utils/cmu-scen-gen/setdest/setdest.cc ns-2.33/indep-utils/cmu-scen-gen/setdest/setdest.cc *** ns-2.33-orig/indep-utils/cmu-scen-gen/setdest/setdest.cc 2009-03-04 23:00:32.000000000 +0000 --- ns-2.33/indep-utils/cmu-scen-gen/setdest/setdest.cc 2009-03-03 03:54:40.000000000 +0000 *************** *** 62,69 **** //#define SHOW_SYMMETRIC_PAIRS ! #define GOD_FORMAT "$ns_ at %.12f \"$god_ set-dist %d %d %d\"\n" ! #define GOD_FORMAT2 "$god_ set-dist %d %d %d\n" #define NODE_FORMAT "$ns_ at %.12f \"$node_(%d) setdest %.12f %.12f %.12f\"\n" #define NODE_FORMAT2 "$node_(%d) setdest %.12f %.12f %.12f\n" #define NODE_FORMAT3 "$node_(%d) set %c_ %.12f\n" --- 62,69 ---- //#define SHOW_SYMMETRIC_PAIRS ! #define GOD_FORMAT "$ns_ at %.12f \"God set-dist %d %d %d\"\n" ! #define GOD_FORMAT2 "God set-dist %d %d %d\n" #define NODE_FORMAT "$ns_ at %.12f \"$node_(%d) setdest %.12f %.12f %.12f\"\n" #define NODE_FORMAT2 "$node_(%d) setdest %.12f %.12f %.12f\n" #define NODE_FORMAT3 "$node_(%d) set %c_ %.12f\n" diff --new-file --recursive --context=3 --minimal -x '*.[ao]' -x '*.nam' -x '*.tr' -x '*.tar' -x '*.cache' -x core -x '*.core' -x '*.orig' -x '*.rej' -x '*.*~' -x ns_tcl.cc ns-2.33-orig/olsr/OLSR.cc ns-2.33/olsr/OLSR.cc *** ns-2.33-orig/olsr/OLSR.cc 1970-01-01 00:00:00.000000000 +0000 --- ns-2.33/olsr/OLSR.cc 2009-03-02 22:36:31.000000000 +0000 *************** *** 0 **** --- 1,2068 ---- + /*************************************************************************** + * 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 + #include + #include + #include + #include + #include + #include + #include + #include + + /// 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: + // Agent/OLSR create-shadow + // 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 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::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 > reachability; + set 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::iterator it = rs.begin(); it != rs.end(); it++) { + int r = *it; + if (r > 0) { + for (std::vector::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 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::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. + /// + /// Maximum number of messages which can be contained in an %OLSR packet is + /// dictated by OLSR_MAX_MSGS constant. + /// + 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::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 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::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::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 '*.tar' -x '*.cache' -x core -x '*.core' -x '*.orig' -x '*.rej' -x '*.*~' -x ns_tcl.cc ns-2.33-orig/olsr/OLSR.h ns-2.33/olsr/OLSR.h *** ns-2.33-orig/olsr/OLSR.h 1970-01-01 00:00:00.000000000 +0000 --- ns-2.33/olsr/OLSR.h 2009-03-02 22:36:31.000000000 +0000 *************** *** 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 + * + *

This software implements base specification of + * %OLSR protocol for NS2 network simulator. + * It has been developed at the University of Murcia + * (Spain) by Francisco J. Ros, and it is released + * under the GNU General Public License.

+ * + *

There are available patches for the latest releases of NS2, 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 NS2.

+ * + *

Here is a summary of software's main features:

+ * + *
    + *
  • Compliant with core-OLSR (but the use of multiple interfaces which is currently + * not supported by NS2) as it is documented in RFC 3626.
  • + * + *
  • Support for MAC layer feedback as described in RFC 3626.
  • + * + *
  • Source code follows NS2 coding style.
  • + * + *
  • Highly configurable from TCL scripts, i.e., without the need of + * recompiling the whole simulator. You can:
  • + * + *
      + *
    • Activate/deactivate debug mode.
    • + * + *
    • Change the interval at which every message type is sent (on a + * per-node basis).
    • + * + *
    • Change a node's willingness for forwarding data packets on + * behalf of other nodes (on a per-node basis).
    • + * + *
    • Print whatever data structure managed by a node at a certain + * time (on a per-node basis).
    • + *
    + * + *
+ * + * \section inst Installing + * + *

In this section we are supposing that you have installed a version of NS + * (2.27/2.28) which is properly running. Let's call $NS_ROOT the upper directory + * where NS is installed. For instance, if you download and install + * ns-allinone-2.28.tar.gz in your home directory, then $NS_ROOT is + * ~/ns-allinone-2.28. Besides let's call $VERSION to the version of + * your installed NS software.

+ * + *

There are two options for installing UM-OLSR, either applying a patch + * or copying each source file to the appropiate place:

+ * + *
    + *
  • Applying patches
  • + * + *
      + *
    1. Download UM-OLSR patch for NS + * 2.27 or + * 2.28 + * version. Let's call $PATCH to the downloaded file.
    2. + * + *
    3. # cp $PATCH $NS_ROOT && cd $NS_ROOT
    4. + * + *
    5. # patch -p0 \< $PATCH
    6. + * + *
    7. # cd ns-$VERSION
    8. + * + *
    9. # make
    10. + *
    + * + *
  • Copying files
  • + * + *
      + *
    1. Download UM-OLSR code for NS + * 2.27 or + * 2.28 + * version. Let's call $FILE to the downloaded file.
    2. + * + *
    3. # tar zxvf $FILE
    4. + * + *
    5. Under the recently created directory are several files which must be copied + * to the corresponding places in $NS_ROOT/ns-$VERSION.
    6. + * + *
    7. # cd $NS_ROOT/ns-$VERSION
    8. + * + *
    9. # make
    10. + *
    + * + * \section howto How to Use It + * + *

    UM-OLSR allows NS2 users to use %OLSR protocol like + * any other MANET routing protocol available in the official release.

    + * + *

    This example + * explores main features of UM-OLSR 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 NS + * Manual or any of the available tutorials for beginners (see + * NS web page). The simulation consists of a + * simple TCL script which defines five mobile nodes (with no motion) and an UDP connection + * between two of them.

    + * + * \section traces Understanding Trace Format + * + * UM-OLSR supports all trace formats defined in NS2, + * 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: + * + *
      + *
    • Number of messages this packet contains.
    • + *
    • Packet sequence number.
    • + *
    • For each message is also shown:
    • + *
        + *
      • Message type ("HELLO", "TC" or "UNKNOWN").
      • + *
      • Originator address.
      • + *
      • Hop count.
      • + *
      • Message sequence number.
      • + *
      + *
    + * + * If you need a more detailed description of trace format, see CMUTrace::format_olsr() + * function in $NS_ROOT/ns-$VERSION/trace/cmu-trace.cc or the result of the above mentioned + * example. + */ + + /// + /// \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 + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + + /********** 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 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 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 '*.tar' -x '*.cache' -x core -x '*.core' -x '*.orig' -x '*.rej' -x '*.*~' -x ns_tcl.cc ns-2.33-orig/olsr/OLSR_pkt.h ns-2.33/olsr/OLSR_pkt.h *** ns-2.33-orig/olsr/OLSR_pkt.h 1970-01-01 00:00:00.000000000 +0000 --- ns-2.33/olsr/OLSR_pkt.h 2009-03-02 22:36:31.000000000 +0000 *************** *** 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 + + /********** 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 '*.tar' -x '*.cache' -x core -x '*.core' -x '*.orig' -x '*.rej' -x '*.*~' -x ns_tcl.cc ns-2.33-orig/olsr/OLSR_printer.cc ns-2.33/olsr/OLSR_printer.cc *** ns-2.33-orig/olsr/OLSR_printer.cc 1970-01-01 00:00:00.000000000 +0000 --- ns-2.33/olsr/OLSR_printer.cc 2009-03-02 22:36:31.000000000 +0000 *************** *** 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 + + /********** 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 '*.tar' -x '*.cache' -x core -x '*.core' -x '*.orig' -x '*.rej' -x '*.*~' -x ns_tcl.cc ns-2.33-orig/olsr/OLSR_printer.h ns-2.33/olsr/OLSR_printer.h *** ns-2.33-orig/olsr/OLSR_printer.h 1970-01-01 00:00:00.000000000 +0000 --- ns-2.33/olsr/OLSR_printer.h 2009-03-02 22:36:31.000000000 +0000 *************** *** 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 + #include + #include + #include + #include + #include + + /// 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 '*.tar' -x '*.cache' -x core -x '*.core' -x '*.orig' -x '*.rej' -x '*.*~' -x ns_tcl.cc ns-2.33-orig/olsr/OLSR_repositories.h ns-2.33/olsr/OLSR_repositories.h *** ns-2.33-orig/olsr/OLSR_repositories.h 1970-01-01 00:00:00.000000000 +0000 --- ns-2.33/olsr/OLSR_repositories.h 2009-03-02 22:36:31.000000000 +0000 *************** *** 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 + #include + #include + + /// 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 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 mprset_t; ///< MPR Set type. + typedef std::vector mprselset_t; ///< MPR Selector Set type. + typedef std::vector linkset_t; ///< Link Set type. + typedef std::vector nbset_t; ///< Neighbor Set type. + typedef std::vector nb2hopset_t; ///< 2-hop Neighbor Set type. + typedef std::vector topologyset_t; ///< Topology Set type. + typedef std::vector dupset_t; ///< Duplicate Set type. + typedef std::vector ifaceassocset_t;///< Interface Association Set type. + + #endif diff --new-file --recursive --context=3 --minimal -x '*.[ao]' -x '*.nam' -x '*.tr' -x '*.tar' -x '*.cache' -x core -x '*.core' -x '*.orig' -x '*.rej' -x '*.*~' -x ns_tcl.cc ns-2.33-orig/olsr/OLSR_rtable.cc ns-2.33/olsr/OLSR_rtable.cc *** ns-2.33-orig/olsr/OLSR_rtable.cc 1970-01-01 00:00:00.000000000 +0000 --- ns-2.33/olsr/OLSR_rtable.cc 2009-03-02 22:36:31.000000000 +0000 *************** *** 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 + #include + #include + + /// + /// \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 '*.tar' -x '*.cache' -x core -x '*.core' -x '*.orig' -x '*.rej' -x '*.*~' -x ns_tcl.cc ns-2.33-orig/olsr/OLSR_rtable.h ns-2.33/olsr/OLSR_rtable.h *** ns-2.33-orig/olsr/OLSR_rtable.h 1970-01-01 00:00:00.000000000 +0000 --- ns-2.33/olsr/OLSR_rtable.h 2009-03-02 22:36:31.000000000 +0000 *************** *** 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 + #include + #include + + /// + /// \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 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 '*.tar' -x '*.cache' -x core -x '*.core' -x '*.orig' -x '*.rej' -x '*.*~' -x ns_tcl.cc ns-2.33-orig/olsr/OLSR_state.cc ns-2.33/olsr/OLSR_state.cc *** ns-2.33-orig/olsr/OLSR_state.cc 1970-01-01 00:00:00.000000000 +0000 --- ns-2.33/olsr/OLSR_state.cc 2009-03-02 22:36:31.000000000 +0000 *************** *** 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 + #include + + /********** 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 '*.tar' -x '*.cache' -x core -x '*.core' -x '*.orig' -x '*.rej' -x '*.*~' -x ns_tcl.cc ns-2.33-orig/olsr/OLSR_state.h ns-2.33/olsr/OLSR_state.h *** ns-2.33-orig/olsr/OLSR_state.h 1970-01-01 00:00:00.000000000 +0000 --- ns-2.33/olsr/OLSR_state.h 2009-03-02 22:36:31.000000000 +0000 *************** *** 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 + + /// 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 '*.tar' -x '*.cache' -x core -x '*.core' -x '*.orig' -x '*.rej' -x '*.*~' -x ns_tcl.cc ns-2.33-orig/queue/priqueue.cc ns-2.33/queue/priqueue.cc *** ns-2.33-orig/queue/priqueue.cc 2009-03-04 23:00:32.000000000 +0000 --- ns-2.33/queue/priqueue.cc 2009-03-02 22:36:31.000000000 +0000 *************** *** 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 '*.tar' -x '*.cache' -x core -x '*.core' -x '*.orig' -x '*.rej' -x '*.*~' -x ns_tcl.cc ns-2.33-orig/tcl/lib/ns-default.tcl ns-2.33/tcl/lib/ns-default.tcl *** ns-2.33-orig/tcl/lib/ns-default.tcl 2009-03-04 23:00:34.000000000 +0000 --- ns-2.33/tcl/lib/ns-default.tcl 2009-03-02 22:46:01.000000000 +0000 *************** *** 1450,1455 **** --- 1450,1463 ---- 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 + Agent/TCP/Linux set rtxcur_init_ 3 Agent/TCP/Linux set maxrto_ 120 Agent/TCP/Linux set minrto_ 0.2 diff --new-file --recursive --context=3 --minimal -x '*.[ao]' -x '*.nam' -x '*.tr' -x '*.tar' -x '*.cache' -x core -x '*.core' -x '*.orig' -x '*.rej' -x '*.*~' -x ns_tcl.cc ns-2.33-orig/tcl/lib/ns-lib.tcl ns-2.33/tcl/lib/ns-lib.tcl *** ns-2.33-orig/tcl/lib/ns-lib.tcl 2009-03-04 23:00:34.000000000 +0000 --- ns-2.33/tcl/lib/ns-lib.tcl 2009-03-02 22:47:16.000000000 +0000 *************** *** 630,635 **** --- 630,638 ---- 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] *************** *** 850,855 **** --- 853,866 ---- 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 '*.tar' -x '*.cache' -x core -x '*.core' -x '*.orig' -x '*.rej' -x '*.*~' -x ns_tcl.cc ns-2.33-orig/tcl/lib/ns-packet.tcl ns-2.33/tcl/lib/ns-packet.tcl *** ns-2.33-orig/tcl/lib/ns-packet.tcl 2009-03-04 23:00:34.000000000 +0000 --- ns-2.33/tcl/lib/ns-packet.tcl 2009-03-02 22:49:11.000000000 +0000 *************** *** 162,167 **** --- 162,168 ---- Mac # network wireless stack # Mobility, Ad-Hoc Networks, Sensor Nets: AODV # routing protocol for ad-hoc networks + OLSR # routing protocol for ad-hoc networks Diffusion # diffusion/diffusion.cc IMEP # Internet MANET Encapsulation Protocol, for ad-hoc networks MIP # Mobile IP, mobile/mip-reg.cc diff --new-file --recursive --context=3 --minimal -x '*.[ao]' -x '*.nam' -x '*.tr' -x '*.tar' -x '*.cache' -x core -x '*.core' -x '*.orig' -x '*.rej' -x '*.*~' -x ns_tcl.cc ns-2.33-orig/tcl/mobility/olsr_example.tcl ns-2.33/tcl/mobility/olsr_example.tcl *** ns-2.33-orig/tcl/mobility/olsr_example.tcl 1970-01-01 00:00:00.000000000 +0000 --- ns-2.33/tcl/mobility/olsr_example.tcl 2009-03-03 03:35:52.000000000 +0000 *************** *** 0 **** --- 1,193 ---- + # ====================================================================== + # Define options + # ====================================================================== + set opt(chan) Channel/WirelessChannel ;# channel type + set opt(prop) Propagation/TwoRayGround ;# radio-propagation model + set opt(netif) Phy/WirelessPhy ;# network interface type + set opt(mac) Mac/802_11 ;# MAC type + set opt(ifq) Queue/DropTail/PriQueue ;# interface queue type + set opt(ll) LL ;# link layer type + set opt(ant) Antenna/OmniAntenna ;# antenna model + set opt(ifqlen) 50 ;# max packet in ifq + set opt(nn) 5 ;# number of mobilenodes + set opt(adhocRouting) OLSR ;# routing protocol + + set opt(cp) "" ;# connection pattern file + set opt(sc) "" ;# node movement file. + + set opt(x) 400 ;# x coordinate of topology + set opt(y) 600 ;# y coordinate of topology + set opt(seed) 0.0 ;# seed for random number gen. + set opt(stop) 45 ;# time to stop simulation + + set opt(cbr-start) 30.0 + # ============================================================================ + + # + # check for random seed + # + if {$opt(seed) > 0} { + puts "Seeding Random number generator with $opt(seed)\n" + ns-random $opt(seed) + } + + # + # create simulator instance + # + set ns_ [new Simulator] + + # + # control OLSR behaviour from this script - + # commented lines are not needed because + # those are default values + # + Agent/OLSR set use_mac_ true + #Agent/OLSR set debug_ false + #Agent/OLSR set willingness 3 + #Agent/OLSR set hello_ival_ 2 + #Agent/OLSR set tc_ival_ 5 + + # + # open traces + # + set tracefd [open olsr_example.tr w] + set namtrace [open olsr_example.nam w] + $ns_ use-newtrace + $ns_ trace-all $tracefd + $ns_ namtrace-all-wireless $namtrace $opt(x) $opt(y) + + # + # create topography object + # + set topo [new Topography] + + # + # define topology + # + $topo load_flatgrid $opt(x) $opt(y) + + # + # create God + # + create-god $opt(nn) + + # + # configure mobile nodes + # + $ns_ node-config -adhocRouting $opt(adhocRouting) \ + -llType $opt(ll) \ + -macType $opt(mac) \ + -ifqType $opt(ifq) \ + -ifqLen $opt(ifqlen) \ + -antType $opt(ant) \ + -propType $opt(prop) \ + -phyType $opt(netif) \ + -channelType $opt(chan) \ + -topoInstance $topo \ + -wiredRouting OFF \ + -agentTrace ON \ + -routerTrace ON \ + -macTrace OFF + + for {set i 0} {$i < $opt(nn)} {incr i} { + set node_($i) [$ns_ node] + } + + # + # positions + # + $node_(0) set X_ 350.0 + $node_(0) set Y_ 200.0 + $node_(0) set Z_ 0.0 + + $node_(1) set X_ 200.0 + $node_(1) set Y_ 350.0 + $node_(1) set Z_ 0.0 + + $node_(2) set X_ 200.0 + $node_(2) set Y_ 550.0 + $node_(2) set Z_ 0.0 + + $node_(3) set X_ 50.0 + $node_(3) set Y_ 200.0 + $node_(3) set Z_ 0.0 + + $node_(4) set X_ 200.0 + $node_(4) set Y_ 50.0 + $node_(4) set Z_ 0.0 + + # + # setup UDP connection + # + set udp [new Agent/UDP] + set null [new Agent/Null] + $ns_ attach-agent $node_(0) $udp + $ns_ attach-agent $node_(2) $null + $ns_ connect $udp $null + set cbr [new Application/Traffic/CBR] + $cbr set packetSize_ 512 + $cbr set rate_ 20Kb + $cbr attach-agent $udp + $ns_ at $opt(cbr-start) "$cbr start" + + # + # print (in the trace file) routing table and other + # internal data structures on a per-node basis + # + $ns_ at 10.0 "[$node_(0) agent 255] print_rtable" + $ns_ at 15.0 "[$node_(0) agent 255] print_linkset" + $ns_ at 20.0 "[$node_(0) agent 255] print_nbset" + $ns_ at 25.0 "[$node_(0) agent 255] print_nb2hopset" + $ns_ at 30.0 "[$node_(0) agent 255] print_mprset" + $ns_ at 35.0 "[$node_(0) agent 255] print_mprselset" + $ns_ at 40.0 "[$node_(0) agent 255] print_topologyset" + + # + # source connection-pattern and node-movement scripts + # + if { $opt(cp) == "" } { + puts "*** NOTE: no connection pattern specified." + set opt(cp) "none" + } else { + puts "Loading connection pattern..." + source $opt(cp) + } + if { $opt(sc) == "" } { + puts "*** NOTE: no scenario file specified." + set opt(sc) "none" + } else { + puts "Loading scenario file..." + source $opt(sc) + puts "Load complete..." + } + + # + # define initial node position in nam + # + for {set i 0} {$i < $opt(nn)} {incr i} { + $ns_ initial_node_pos $node_($i) 20 + } + + # + # tell all nodes when the simulation ends + # + for {set i 0} {$i < $opt(nn) } {incr i} { + $ns_ at $opt(stop).0 "$node_($i) reset"; + } + + $ns_ at $opt(stop).0002 "puts \"NS EXITING...\" ; $ns_ halt" + $ns_ at $opt(stop).0001 "stop" + + proc stop {} { + global ns_ tracefd namtrace + $ns_ flush-trace + close $tracefd + close $namtrace + } + + # + # begin simulation + # + puts "Starting Simulation..." + + $ns_ run diff --new-file --recursive --context=3 --minimal -x '*.[ao]' -x '*.nam' -x '*.tr' -x '*.tar' -x '*.cache' -x core -x '*.core' -x '*.orig' -x '*.rej' -x '*.*~' -x ns_tcl.cc ns-2.33-orig/trace/cmu-trace.cc ns-2.33/trace/cmu-trace.cc *** ns-2.33-orig/trace/cmu-trace.cc 2009-03-04 23:00:37.000000000 +0000 --- ns-2.33/trace/cmu-trace.cc 2009-03-02 22:36:31.000000000 +0000 *************** *** 51,56 **** --- 51,57 ---- #include //TORA #include // IMEP #include //AODV + #include // OLSR #include #include #include *************** *** 944,949 **** --- 945,1025 ---- } 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 ; *************** *** 1239,1244 **** --- 1315,1323 ---- case PT_GAF: case PT_PING: break; + case PT_OLSR: + format_olsr(p, offset); + break; default: if(pktTrc_ && pktTrc_->format_unknow(p, offset, pt_, newtrace_)) diff --new-file --recursive --context=3 --minimal -x '*.[ao]' -x '*.nam' -x '*.tr' -x '*.tar' -x '*.cache' -x core -x '*.core' -x '*.orig' -x '*.rej' -x '*.*~' -x ns_tcl.cc ns-2.33-orig/trace/cmu-trace.h ns-2.33/trace/cmu-trace.h *** ns-2.33-orig/trace/cmu-trace.h 2009-03-04 23:00:37.000000000 +0000 --- ns-2.33/trace/cmu-trace.h 2009-03-02 22:50:12.000000000 +0000 *************** *** 159,164 **** --- 159,165 ---- 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); // This holds all the tracers added at run-time static PacketTracer *pktTrc_;