events.hxx

Go to the documentation of this file.
00001 // Copyright (C) 2003-2006 Laboratoire de Recherche en Informatique
00002 
00003 // This file is part of Qolyester.
00004 
00005 // Qolyester is free software; you can redistribute it and/or
00006 // modify it under the terms of the GNU General Public License
00007 // as published by the Free Software Foundation; either version 2
00008 // of the License, or (at your option) any later version.
00009 
00010 // Qolyester is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU General Public License for more details.
00014 
00015 // You should have received a copy of the GNU General Public License
00016 // along with this program; if not, write to the Free Software
00017 // Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018 // Boston, MA  02110-1301, USA.
00019 
00020 #ifndef QOLYESTER_DAEMON_SCH_EVENTS_HXX
00021 # define QOLYESTER_DAEMON_SCH_EVENTS_HXX 1
00022 
00023 # include "alg/routingtable.hh"
00024 # include "alg/mprselection.hh"
00025 # include "set/duplicate.hh"
00026 # include "set/hna.hh"
00027 # include "set/interfaces.hh"
00028 # include "set/mid.hh"
00029 # include "set/routes.hh"
00030 # include "set/topology.hh"
00031 # include "set/neighbors.hh"
00032 # include "sys/routing.hh"
00033 
00034 # include "events.hh"
00035 
00036 namespace olsr {
00037 
00038   extern utl::Mark      mprset_recomp;
00039   extern utl::Mark      advset_changed;
00040 
00041   extern sch::TimedEvent*       tc_sender;
00042   extern dupset_t       dup_set;
00043   extern hnaset_t       hna_set;
00044   extern midset_t       mid_set;
00045   extern lrouteset_t    lroute_set;
00046   extern rrouteset_t    rroute_set;
00047   extern toposet_t      topo_set;
00048   extern ifaceset_t     iface_set;
00049   extern thnset_t       thn_set;
00050 
00051   extern std::ostream   dump_state;
00052 
00053   namespace sch {
00054 
00055     namespace internal {
00056 
00057 # define SENDER_TRAITS(Msg, Id) \
00058       const timeval_t& sender_traits<msg::Msg ## Message>::interval = \
00059         cst::Id ## _interval; \
00060       const timeval_t sender_traits<msg::Msg ## Message>::in_jitter(1000); \
00061       const timeval_t& sender_traits<msg::Msg ## Message>::maxjitter = \
00062         cst::maxjitter; \
00063       const std::string sender_traits<msg::Msg ## Message>::name = #Msg ;
00064 
00065       SENDER_TRAITS(HELLO, hello);
00066       SENDER_TRAITS(TC, tc);
00067       SENDER_TRAITS(MID, mid);
00068       SENDER_TRAITS(HNA, hna);
00069 
00070 #undef SENDER_TRAITS
00071 
00072     } // namespace internal
00073 
00074 # ifdef DEBUG
00075     template <class M>
00076     MessageSender<M>::MessageSender()
00077       : Super(timeval_t::in_jitter(internal::sender_traits<M>::in_jitter),
00078               internal::sender_traits<M>::interval,
00079               internal::sender_traits<M>::maxjitter,
00080               std::string("MessageSender(") +
00081               internal::sender_traits<M>::name + ')')
00082     {}
00083 # else // !DEBUG
00084     template <class M>
00085     MessageSender<M>::MessageSender()
00086       : Super(timeval_t::in_jitter(internal::sender_traits<M>::in_jitter),
00087               internal::sender_traits<M>::interval,
00088               internal::sender_traits<M>::maxjitter)
00089     {}
00090 # endif
00091 
00092     template <class M>
00093     void
00094     MessageSender<M>::handle() {
00095       Super::handle();
00096       pending_messages.push_back(new M());
00097     }
00098 
00099 # ifdef DEBUG
00100     MessageSender<msg::TCMessage>::MessageSender()
00101       : Super(timeval_t::in_jitter(internal::sender_traits<msg::TCMessage>::in_jitter),
00102               internal::sender_traits<msg::TCMessage>::interval,
00103               internal::sender_traits<msg::TCMessage>::maxjitter,
00104               "MessageSender(TC)")
00105     {}
00106 # else // !DEBUG
00107     MessageSender<msg::TCMessage>::MessageSender()
00108       : Super(timeval_t::in_jitter(internal::sender_traits<msg::TCMessage>::in_jitter),
00109               internal::sender_traits<msg::TCMessage>::interval,
00110               internal::sender_traits<msg::TCMessage>::maxjitter)
00111     {}
00112 # endif
00113 
00114     void
00115     MessageSender<msg::TCMessage>::handle() {
00116       Super::handle();
00117       if (!cproxy.is_advset_empty() || !cproxy.is_hold_expired())
00118         pending_messages.push_back(new msg::TCMessage());
00119     }
00120 
00121 # ifdef DEBUG
00122     MessageForwarder::MessageForwarder(const timeval_t& n,
00123                                        const msg::UnknownMessage& m)
00124       : Super(n, "MessageForwarder"),
00125         message_(new msg::UnknownMessage(m))
00126     {}
00127 # else // !DEBUG
00128     MessageForwarder::MessageForwarder(const timeval_t& n,
00129                                        const msg::UnknownMessage& m)
00130       : Super(n),
00131         message_(new msg::UnknownMessage(m))
00132     {}
00133 # endif
00134 
00135     MessageForwarder::~MessageForwarder() {
00136       if (message_ != 0)
00137         delete message_;
00138     }
00139 
00140     void
00141     MessageForwarder::handle() {
00142       if (message_ != 0) {
00143         pending_messages.push_back(message_);
00144         message_ = 0;
00145       }
00146       scheduler.destroy(this);
00147     }
00148 
00149 # ifdef DEBUG
00150     StatePrinter::StatePrinter()
00151       : Super(timeval_t::now(), cst::dump_interval, "StatePrinter")
00152     {}
00153 # else // !DEBUG
00154     StatePrinter::StatePrinter()
00155       : Super(timeval_t::now(), cst::dump_interval)
00156     {}
00157 # endif
00158 
00159     // The state printer handler
00160     void
00161     StatePrinter::handle() {
00162       Super::handle();
00163 
00164       dump_state << "STATE {\n"
00165                  << indent;
00166       if (cproxy.nset_.empty())
00167         dump_state << "Neighbors {}\n";
00168       else {
00169         dump_state << "Neighbors {\n"
00170                    << indent;
00171         for (cproxy_t::nset_t::const_iterator i = cproxy.nset_.begin();
00172              i != cproxy.nset_.end(); ++i)
00173           dump_state << (i->is_sym()    ? "S " : "A ")
00174                      << (i->is_mpr()    ? "M " : "_ ")
00175                      << (i->is_mprsel() ? "s " : "_ ")
00176                      << i->main_addr() << " (" << i->lset_.size()
00177                      << " link(s)) "
00178                      << "s:" << of(i->mprsel_time().diff()) << ' '
00179                      << "w: " << i->willingness() << '\n';
00180         dump_state << deindent
00181                    << "}\n";
00182       }
00183       if (cproxy.lset_.empty())
00184         dump_state << "Links {}\n";
00185       else {
00186         dump_state << "Links {\n"
00187                    << indent;
00188         for (cproxy_t::lset_t::const_iterator i = cproxy.lset_.begin();
00189              i != cproxy.lset_.end(); ++i) {
00190 # ifndef QOLYESTER_ENABLE_LINKHYS
00191           dump_state << (i->is_sym() ? "S " :
00192                          i->asymtime() > timeval_t::now() ?
00193                          "A " : "L ")
00194 # else // QOLYESTER_ENABLE_LINKHYS
00195           dump_state << (!i->losttime().is_past() ? "L " :
00196                          i->is_sym() ? "S " :
00197                          i->asymtime() > timeval_t::now() ?
00198                          "A " : "L ")
00199 # endif
00200                      << i->local_addr() << " <- " << i->remote_addr() << " ("
00201                      << i->main_addr() << ")\n        "
00202                      << "t:" << of(i->time_.diff()) << ' '
00203                      << "A:" << of(i->asymtime_.diff()) << ' '
00204                      << "S:" << of(i->symtime_.diff()) << ' '
00205 # ifdef QOLYESTER_ENABLE_LINKHYS
00206                      << "L:" << of(i->losttime_.diff()) << (i->pending_ ?
00207                                                             " P " : "   ")
00208                      << "n:" << of(i->nexttime_.diff()) << ' '
00209                      << "Q:" << of(i->quality_)
00210 # endif // !QOLYESTER_ENABLE_LINKHYS
00211                      << '\n';
00212         }
00213         dump_state << deindent
00214                    << "}\n";
00215       }
00216       if (thn_set.tset_.empty())
00217         dump_state << "2-Hop neighbors {}\n";
00218       else {
00219         dump_state << "2-Hop neighbors {\n"
00220                    << indent;
00221         for (thnset_t::tset_t::const_iterator i = thn_set.tset_.begin();
00222              i != thn_set.tset_.end(); ++i)
00223           dump_state << i->main_addr() << " -> " << i->twohop_addr()
00224                      << ' ' << "t:" << of(i->time_.diff()) << '\n';
00225         dump_state << deindent
00226                    << "}\n";
00227       }
00228       if (topo_set.tset_.empty())
00229         dump_state << "Topology {}\n";
00230       else {
00231         dump_state << "Topology {\n"
00232                    << indent;
00233         for (toposet_t::tset_t::const_iterator i = topo_set.tset_.begin();
00234              i != topo_set.tset_.end(); ++i)
00235           dump_state << i->last_addr() << " -> " << i->dest_addr()
00236                      << ' ' << "t:" << of(i->time_.diff()) << '\n';
00237         dump_state << deindent
00238                    << '}' << std::endl;
00239       }
00240 # ifdef QOLYESTER_ENABLE_MID
00241       if (mid_set.mset_.empty())
00242         dump_state << "MID set {}\n";
00243       else {
00244         dump_state << "MID set {\n"
00245                    << indent;
00246         for (midset_t::mset_t::const_iterator i = mid_set.mset_.begin();
00247              i != mid_set.mset_.end(); ++i)
00248           dump_state << i->iface_addr() << " (" << i->main_addr()
00249                      << ") " << "t:" << of(i->time_.diff()) << '\n';
00250         dump_state << deindent
00251                    << "}\n";
00252       }
00253 # endif // !QOLYESTER_ENABLE_MID
00254 # ifdef QOLYESTER_ENABLE_HNA
00255       if (hna_set.hset_.empty())
00256         dump_state << "HNA set {}\n";
00257       else {
00258         dump_state << "HNA set {\n"
00259                    << indent;
00260         for (hnaset_t::hset_t::const_iterator i = hna_set.hset_.begin();
00261              i != hna_set.hset_.end(); ++i)
00262           dump_state << i->gw_addr() << " -> "
00263                << i->net_addr() << '/' << i->prefix() << ' '
00264                << "t:" << of(i->time_.diff()) << '\n';
00265         dump_state << deindent
00266                    << "}\n";
00267       }
00268 # endif // !QOLYESTER_ENABLE_HNA
00269       if (dup_set.dset_.empty())
00270         dump_state << up << "Duplicate set {}\n" << down;
00271       else {
00272         dump_state << up << "Duplicate set {\n"
00273                    << indent;
00274         for (dupset_t::dset_t::const_iterator i = dup_set.dset_.begin();
00275              i != dup_set.dset_.end(); ++i) {
00276           dump_state << i->addr_ << ' ' << i->seqnum_
00277                      << (i->retransmitted_ ? " R" : " _") << ' '
00278                      << i->time_.diff() << " { ";
00279           for (set::DuplicateEntry::ifaces_t::const_iterator j =
00280                  i->ifaces_.begin();
00281                j != i->ifaces_.end(); ++j)
00282             dump_state << *j << ' ';
00283           dump_state << "}\n";
00284         }
00285         dump_state << deindent
00286                    << "}\n" << down;
00287       }
00288       if (lroute_set.set_.empty() && rroute_set.set_.empty())
00289         dump_state << "Route set {}\n";
00290       else {
00291         dump_state << "Route set {\n"
00292                    << indent;
00293         for (lrouteset_t::set_t::const_iterator i = lroute_set.set_.begin();
00294              i != lroute_set.set_.end(); ++i)
00295           dump_state << i->dest_addr() << '/' << i->prefix() << " : "
00296                      << i->interface_info().name() << '\n';
00297         for (rrouteset_t::set_t::const_iterator i = rroute_set.set_.begin();
00298              i != rroute_set.set_.end(); ++i)
00299           dump_state << i->dest_addr() << '/' << i->prefix() << " : "
00300                      << i->next_addr() << '\n';
00301         dump_state << deindent
00302                    << '}' << std::endl;
00303       }
00304 # ifdef DEBUG
00305       debug << indent;
00306       sys::RoutingActions().print_kernel_routes();
00307       debug << deindent;
00308 # endif
00309       dump_state << up << path_net << '\n' << down;
00310       dump_state << deindent
00311                  << '}' << std::endl;
00312     }
00313 
00314 # ifdef DEBUG
00315     PacketSender::PacketSender(iface_t* i, const pkt::Packet& p)
00316       : Super(i->send_p(), "PacketSender"),
00317         iface_(i),
00318         packets_() {
00319       packets_.push(p);
00320       i->insert_event(this);
00321     }
00322 # else // !DEBUG
00323     PacketSender::PacketSender(iface_t* i, const pkt::Packet& p)
00324       : Super(i->send_p()),
00325         iface_(i),
00326         packets_() {
00327       packets_.push(p);
00328       i->insert_event(this);
00329     }
00330 # endif
00331 
00332     void
00333     PacketSender::handle() {
00334       assert(!packets_.empty());
00335       p().pfd.revents = 0;
00336       try {
00337         iface_->send(packets_.front());
00338       } catch (errnoexcept_t& e) {
00339         warning << "PacketSender: " << e.what() << std::endl;
00340       }
00341       packets_.pop();
00342       if (packets_.empty()) {
00343         debug << up(2) << "PacketSender::handle(): no packets left, destroying"
00344               << std::endl << down(2);
00345         iface_->erase_event(this);
00346         scheduler.destroy(this);
00347       } else {
00348         scheduler.insert(this);
00349         debug << up(2) << "PacketSender::handle(): " << packets_.size()
00350               << " packets left" << std::endl << down(2);
00351       }
00352     }
00353 
00354     void
00355     PacketSender::push_packet(const pkt::Packet& p) {
00356       while (packets_.size() >= iface_->queue_size()) {
00357         notice << "PacketSender::push_packet(): queue overflow ("
00358                << packets_.size() << "), popping front" << std::endl;
00359         packets_.pop();
00360       }
00361       packets_.push(p);
00362       debug << up(2) << "PacketSender::push_packet(): "
00363             << packets_.size() << " packets left" << std::endl << down(2);
00364     }
00365 
00366 # ifdef DEBUG
00367     PacketReceiver::PacketReceiver(iface_t* i)
00368       : Super(i->recv_p(), "PacketReceiver"),
00369         iface_(i) {
00370       i->insert_event(this);
00371     }
00372 # else // !DEBUG
00373     PacketReceiver::PacketReceiver(iface_t* i)
00374       : Super(i->recv_p()),
00375         iface_(i) {
00376       i->insert_event(this);
00377     }
00378 # endif
00379 
00380     void
00381     PacketReceiver::handle() {
00382       p().pfd.revents = 0;
00383       scheduler.insert(this);
00384       try {
00385         pkt::Packet     p = iface_->receive();
00386         pkt::Packet::parse(p.data(), p.sender(), iface_->addr());
00387       } catch (std::runtime_error& e) {
00388         warning << "PacketReceiver: " << e.what() << std::endl;
00389       }
00390     }
00391 
00392     bool
00393     QolyesterLoopHandler::operator()() const {
00394 
00395       // Here, we process the pending messages.
00396       if (!pending_messages.empty())
00397         iface_set.send_messages();
00398 
00399       if (mprset_recomp.mark()) {
00400         mprset_recomp.reset();
00401         alg::mprselection();
00402       }
00403 
00404       // Shift the sending of the next TC message if needed.
00405       if (advset_changed.mark()) {
00406         advset_changed.reset();
00407         assert(tc_sender != 0);
00408         scheduler.erase(tc_sender);
00409         tc_sender->set_next(timeval_t::in(timeval_t::jitter(cst::maxjitter)));
00410         scheduler.insert(tc_sender);
00411       }
00412 
00413       // Recalculate routes if needed.
00414       if (routes_recomp.mark()) {
00415         routes_recomp.reset();
00416         try {
00417           alg::compute_routes();
00418         } catch (errnoexcept_t& e) {
00419           warning << e.what() << std::endl;
00420         }
00421       }
00422 
00423       // Cleanly terminate if needed.
00424       if (terminate_now.mark())
00425         remove_routes();
00426 
00427       return Super::operator()();
00428     }
00429 
00430     void remove_routes()
00431     {
00432       debug << "Removing all routes" << std::endl;
00433       alg::flush_routes(lrouteset_t(), rrouteset_t());
00434     }
00435 
00436   } // namespace sch
00437 
00438 } // namespace olsr
00439 
00440 #endif // !QOLYESTER_DAEMON_SCH_EVENTS_HXX

Generated on Mon Sep 10 17:02:11 2007 for Qolyester daemon by  doxygen 1.5.1