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

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