Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

tc.hxx

Go to the documentation of this file.
00001 // Copyright (C) 2003, 2004, 2005 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, Boston, MA  02110-1301, USA.
00018 
00019 #ifndef QOLYESTER_DAEMON_MSG_TC_HXX
00020 # define QOLYESTER_DAEMON_MSG_TC_HXX 1
00021 
00022 # include "set/topology.hh"
00023 
00024 # include "tc.hh"
00025 
00026 namespace olsr {
00027 
00028   extern toposet_t      topo_set;
00029   extern std::ostream   dump_tc;
00030 
00031   namespace msg {
00032 
00033     TCMessage::TCMessage() : _data() {}
00034 
00035     TCMessage::TCMessage(const utl::Data& d) : _data(d) {}
00036 
00037     bool
00038     TCMessage::dump(utl::Data& d, const address_t& interface) const {
00039       bool      ret = false;
00040 
00041       if (_data.empty()) { // we want to generate a new message
00042 
00043         if (d.size() < Message::min_length + min_length)
00044           return true; // try again immediately
00045 
00046         if (!cproxy.is_advset_empty())
00047           cproxy.stamp_hold();
00048 
00049         if (do_dump_tc)
00050           dump_tc << "TC preparation (" << interface << ") (ANSN: "
00051                   << cproxy.advset_seqnum() << ") "
00052                   << Message::seqnum << " {\n";
00053 
00054         Message::raw*   mraw = reinterpret_cast<Message::raw*>(d.raw());
00055         raw*            traw = reinterpret_cast<raw*>(mraw->data);
00056 
00057         d += sizeof *mraw + sizeof *traw;
00058 
00059         // Dump message header
00060         mraw->type     = TC_MESSAGE;                    // Message Type
00061         mraw->vtime    = utl::Vtime(cst::top_hold_time);// VTime
00062         // mraw->size  = 0;                             // set later
00063         main_addr.dump(mraw->addr);
00064         mraw->ttl      = 255;                           // Time To Live
00065         mraw->hopcount = 0;                             // Hop Count
00066         mraw->seqnum   = htons(Message::seqnum);        // Sequence number
00067 
00068         traw->ansn     = htons(cproxy.advset_seqnum());
00069         traw->reserved = 0;
00070 
00071         typedef std::list<cproxy_t::tc_neighborset_t::iterator> nset_t;
00072 
00073         nset_t          mn_set;
00074         nset_t          others_set;
00075         bool            some_sym = false;
00076         unsigned        bytes_so_far = 0;
00077 
00078         for (cproxy_t::tc_neighborset_t::iterator n =
00079                cproxy.tc_neighborset().begin(interface);
00080              n != cproxy.tc_neighborset().end(interface); ++n) {
00081 
00082           if (cproxy.tc_neighborset().stamp(n) ==
00083               timeval_t::now())
00084             break;
00085 
00086           if (!n->is_mprsel()) {
00087             if (tc_redundancy == mprselset) {
00088               others_set.push_back(n);
00089               continue;
00090             } else if (!n->is_mpr())
00091               if (tc_redundancy == mprselset_mprset) {
00092                 others_set.push_back(n);
00093                 continue;
00094               }
00095           } else
00096             some_sym = true;
00097 
00098 
00099           if (d.size() - bytes_so_far < ADDRESS_SIZE) {
00100             if (cproxy.tc_neighborset().expired(n, cst::tc_interval,
00101                                                 timeval_t::in(cst::tc_interval)))
00102               ret = true;
00103             break;
00104           }
00105 
00106           mn_set.push_back(n);
00107           bytes_so_far += ADDRESS_SIZE;
00108         }
00109 
00110         if (some_sym) {
00111           for (nset_t::iterator i = mn_set.begin();
00112                i != mn_set.end(); d += ADDRESS_SIZE, ++i) {
00113 
00114             if (do_dump_tc)
00115               dump_tc << "  " << (*i)->main_addr() << "\n";
00116 
00117             (*i)->main_addr().dump(d.raw());
00118             cproxy.tc_neighborset().set_stamp(*i);
00119           }
00120         }
00121 
00122         for (nset_t::iterator i = others_set.begin();
00123              i != others_set.end(); ++i)
00124           cproxy.tc_neighborset().set_stamp(*i);
00125 
00126         mraw->size = htons(d.raw() - reinterpret_cast<u_int8_t*>(mraw));
00127 
00128         if (do_dump_tc)
00129           dump_tc << "}" << std::endl;
00130 
00131       } else {
00132 
00133         if (d.size() < _data.size())
00134           return true;
00135 
00136         _data.dump(d);
00137         d += _data.size();
00138       }
00139 
00140       return ret;
00141     }
00142 
00143     void
00144     TCMessage::parse(const utl::ConstData& d, const Message::header& mh) {
00145       const raw*        h = reinterpret_cast<const raw*>(d.raw());
00146 
00147       if (do_dump_tc)
00148         dump_tc << "TC from " << mh.originator
00149                 << " (" << mh.sender << " -> " << mh.receiver << ") (ANSN: "
00150                 << ntohs(h->ansn) << ") M(" << mh.mseqnum << ") P("
00151                 << mh.pseqnum << ") Hc(" << mh.hopcount << ") {\n";
00152 
00153       cproxy_t::linkset_t::iterator     l =
00154         cproxy.linkset().find(set::Link::make_key(mh.receiver, mh.sender));
00155 
00156       if (l == cproxy.linkset().end() || !l->is_sym()) {
00157 
00158         if (do_dump_tc)
00159           dump_tc << "  (ignored since not from symmetric neighbor)\n}"
00160                      << std::endl;
00161         return;
00162       }
00163 
00164       // From now on, the message is OK.
00165 
00166       utl::ConstData    payload = d + sizeof (raw);
00167 
00168       // Extract the topology tuples.
00169       std::pair<toposet_t::toposet_t::iterator, toposet_t::toposet_t::iterator>
00170         x = topo_set.toposet().equal_range(set::TopologyEntry::
00171                                            make_key(mh.originator));
00172 
00173       // Check if there is a topology tuple with higher seqnum.
00174       for (toposet_t::toposet_t::iterator i = x.first; i != x.second; ++i)
00175         if (i->seqnum() > utl::Seqnum<u_int16_t>(ntohs(h->ansn))) {
00176           if (do_dump_tc)
00177             dump_tc << "  (ignored since out of order)\n}" << std::endl;
00178           return;
00179         }
00180 
00181       // Erase all "old" tuples (with lower seqnum).
00182       for (toposet_t::toposet_t::iterator i = x.first;
00183            i != x.second; /* at end */)
00184         if (i->seqnum() < utl::Seqnum<u_int16_t>(ntohs(h->ansn))) {
00185           toposet_t::toposet_t::iterator        tmp = i++;
00186           topo_set.erase(tmp);
00187         } else
00188           ++i;
00189 
00190       // Get all the "current" tuples.
00191       x = topo_set.toposet().equal_range(set::TopologyEntry::
00192                                          make_key(mh.originator));
00193 
00194       // Extract the payload of the message.
00195       const u_int8_t    (*addrs)[ADDRESS_SIZE] =
00196         reinterpret_cast<const u_int8_t (*)[ADDRESS_SIZE]>(payload.raw());
00197       unsigned          len = payload.size() / ADDRESS_SIZE;
00198 
00199       for (unsigned i = 0; i < len; ++i) {
00200         address_t               addr(addrs[i], ADDRESS_SIZE);
00201 
00202         if (do_dump_tc)
00203           dump_tc << "  "  << addr << "\n";
00204 
00205         if (addr == main_addr)
00206           continue;
00207 
00208         // The following distinction is necessary, since toposet_t is
00209         // a multiset, so duplicate entries may appear if no explicit
00210         // check for existing tuples is done.
00211 
00212         // Update validity of the tuple if it exists.
00213         bool                    found = false;
00214         for (toposet_t::toposet_t::iterator k = x.first;
00215              k != x.second; ++k)
00216           if (k->dest_addr() == addr) {
00217             sch::TimedEvent*    e = k->updater();
00218             scheduler.erase(e);
00219             e->set_next(timeval_t::in(mh.validity));
00220             k->set_time(timeval_t::in(mh.validity));
00221             scheduler.insert(e);
00222             found = true;
00223           }
00224 
00225         // Or insert a new tuple in the set.
00226         if (!found) {
00227           topo_set.insert(set::TopologyEntry(addr,
00228                                              mh.originator,
00229                                              ntohs(h->ansn),
00230                                              mh.validity));
00231         }
00232       }
00233 
00234       if (do_dump_tc)
00235         dump_tc << "}" << std::endl;
00236     }
00237 
00238   } // namespace msg
00239 
00240 } // namespace olsr
00241 
00242 #endif // ! QOLYESTER_DAEMON_MSG_TC_HXX

Generated on Thu Jul 28 21:21:48 2005 for Qolyester daemon by  doxygen 1.4.1