📄 olsr.cc
字号:
/*************************************************************************** * Copyright (C) 2004 by Francisco J. Ros * * fjrm@dif.um.es * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/////// \file OLSR.cc/// \brief Implementation of OLSR agent and related classes.////// This is the main file of this software because %OLSR's behaviour is/// implemented here.///#include <olsr/OLSR.h>#include <olsr/OLSR_pkt.h>#include <olsr/OLSR_printer.h>#include <math.h>#include <limits.h>#include <address.h>#include <ip.h>#include <cmu-trace.h>#include <map>/// Length (in bytes) of UDP header.#define UDP_HDR_LEN 8////// \brief Function called by MAC layer when cannot deliver a packet.////// \param p Packet which couldn't be delivered./// \param arg OLSR agent passed for a callback.///static voidolsr_mac_failed_callback(Packet *p, void *arg) { ((OLSR*)arg)->mac_failed(p);}/********** TCL Hooks **********/int OLSR_pkt::offset_;static class OLSRHeaderClass : public PacketHeaderClass {public: OLSRHeaderClass() : PacketHeaderClass("PacketHeader/OLSR", sizeof(OLSR_pkt)) { bind_offset(&OLSR_pkt::offset_); }} class_rtProtoOLSR_hdr;static class OLSRClass : public TclClass {public: OLSRClass() : TclClass("Agent/OLSR") {} TclObject* create(int argc, const char*const* argv) { // argv has the following structure: // <tcl-object> <tcl-object> Agent/OLSR create-shadow <id> // e.g: _o17 _o17 Agent/OLSR create-shadow 0 // argv[4] is the address of the node assert(argc == 5); return new OLSR((nsaddr_t)Address::instance().str2addr(argv[4])); }} class_rtProtoOLSR;////// \brief Interface with TCL interpreter.////// From your TCL scripts or shell you can invoke commands on this OLSR/// routing agent thanks to this function. Currently you can call "start",/// "print_rtable", "print_linkset", "print_nbset", "print_nb2hopset",/// "print_mprset", "print_mprselset" and "print_topologyset" commands.////// \param argc Number of arguments./// \param argv Arguments./// \return TCL_OK or TCL_ERROR.///intOLSR::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.///voidOLSR_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.///voidOLSR_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.///voidOLSR_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.///voidOLSR_DupTupleTimer::expire(Event* e) { if (tuple_->time() < CURRENT_TIME) { agent_->rm_dup_tuple(tuple_); delete tuple_; delete 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.///voidOLSR_LinkTupleTimer::expire(Event* e) { double now = CURRENT_TIME; if (tuple_->time() < now) { agent_->rm_link_tuple(tuple_); delete tuple_; delete 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.///voidOLSR_Nb2hopTupleTimer::expire(Event* e) { if (tuple_->time() < CURRENT_TIME) { agent_->rm_nb2hop_tuple(tuple_); delete tuple_; delete 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.///voidOLSR_MprSelTupleTimer::expire(Event* e) { if (tuple_->time() < CURRENT_TIME) { agent_->rm_mprsel_tuple(tuple_); delete tuple_; delete 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.///voidOLSR_TopologyTupleTimer::expire(Event* e) { if (tuple_->time() < CURRENT_TIME) { agent_->rm_topology_tuple(tuple_); delete tuple_; delete 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.///voidOLSR_IfaceAssocTupleTimer::expire(Event* e) { if (tuple_->time() < CURRENT_TIME) { agent_->rm_ifaceassoc_tuple(tuple_); delete tuple_; delete 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.///voidOLSR_MsgTimer::expire(Event* e) { agent_->send_pkt(); delete this;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -