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

mprselection.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_ALG_MPRSELECTION_HXX
00020 # define QOLYESTER_DAEMON_ALG_MPRSELECTION_HXX 1
00021 
00022 # include "set/neighbors.hh"
00023 
00024 # include "mprselection.hh"
00025 
00026 namespace olsr {
00027 
00028   extern thnset_t       thn_set;
00029   extern utl::Mark      advset_changed;
00030 
00031   namespace alg {
00032 
00033     // The MPR selection routine.  This is the extended version,
00034     // taking into account the MPR_COVERAGE parameter, as described in
00035     // section 16.2.
00036     void mprselection()
00037     {
00038       debug << "SELECTING MPRs" << std::endl;
00039 
00040       // Declaration of several convenience types.
00041 
00042       // An address set
00043       typedef std::set<address_t>               aset_t;
00044 
00045       // A simple 2-hop neighbor set
00046       typedef std::map<address_t, aset_t>       thnsimpleset_t;
00047 
00048       // A neighbor set (in fact this is a pointer set, to spare
00049       // memory usage)
00050       typedef std::set<const set::Neighbor*, utl::pless<set::Neighbor> >
00051                                                 nset_t;
00052       // The iterator on the neighbor set, which can be used as though
00053       // the elements were references to neighbors themselves and not
00054       // pointers.
00055       typedef utl::DerefIterator<nset_t::const_iterator>
00056                                                 nset_const_iterator;
00057 
00058       // A degree map, mapping 1-hop neighbor addresses into their
00059       // degree (see the RFC 3626 section 8.3.1 for more info).
00060       typedef std::map<address_t, unsigned>     degreemap_t;
00061 
00062       // A coverer map, mapping 2-hop neighbor addresses into the set
00063       // of 1-hop neighbors that reach them.
00064       typedef std::map<address_t, aset_t>       coverermap_t;
00065 
00066       aset_t                            mprs;
00067       aset_t                            total_n2;
00068       nset_t                            rcandidates;
00069       thnsimpleset_t                    thns;
00070 
00071       // Compute the global 2-hop neighborhood.
00072 
00073       // We want to exclude 1-hop neighbors that would certainly not
00074       // be chosen as MPR regardless of the interface (asym nodes and
00075       // nodes with willingness equal to WILL_NEVER) and 2-hop
00076       // neighbors that are also symmetric 1-hop neighbors.
00077       for (thnset_t::thnset_t::iterator t = thn_set.thnset().begin();
00078            t != thn_set.thnset().end(); ++t) {
00079         cproxy_t::sym_neighborset_t::iterator   n =
00080           cproxy.sym_neighborset().find(set::Neighbor::make_key(t->main_addr()));
00081         if (n == cproxy.sym_neighborset().end() ||
00082             n->willingness() == WILL_NEVER)
00083           continue; // Ignore asym and non-willing nodes
00084         if (cproxy.sym_neighborset().find(set::Neighbor::make_key(t->twohop_addr())) !=
00085             cproxy.sym_neighborset().end())
00086           continue; // Ignore symmetric nodes
00087         thns[t->main_addr()].insert(t->twohop_addr());
00088         total_n2.insert(t->twohop_addr());
00089       }
00090 
00091 # ifdef QOLYESTER_ENABLE_MID
00092 
00093       // Cycle over all the interfaces to compute the per-interface MPR-set.
00094       for (ifaceset_t::const_iterator i = iface_set.begin();
00095            i != iface_set.end();
00096            ++i) {
00097 
00098 # else // ! QOLYESTER_ENABLE_MID
00099 
00100       {
00101         iface_t*        i = &this_interface;
00102 
00103 # endif
00104 
00105         thnsimpleset_t                  lthns;
00106         nset_t                          candidates;
00107 
00108         // Compute the 2-hop set and candidates.
00109         for (thnsimpleset_t::const_iterator oh = thns.begin();
00110              oh != thns.end(); ++oh) {
00111           cproxy_t::sym_neighborset_t::iterator n =
00112             cproxy.sym_neighborset().find(set::Neighbor::make_key(oh->first));
00113           assert(n != cproxy.sym_neighborset().end());
00114           std::pair<set::Neighbor::linkset_t::iterator,
00115                     set::Neighbor::linkset_t::iterator> er =
00116             n->find_lifaces(i->addr());
00117           bool  sym_found = false;
00118           for (set::Neighbor::linkset_t::iterator l = er.first;
00119                l != er.second; ++l)
00120             if (l->is_sym()) {
00121               sym_found = true;
00122               break;
00123             }
00124           if (!sym_found)
00125             continue; // Ignore nodes unreachable through this iface
00126           lthns[oh->first] = oh->second;
00127           candidates.insert(&*n);
00128         }
00129 
00130 # ifdef QOLYESTER_ENABLE_MID
00131         aset_t          lmprs;          // iface-local MPR-set
00132 # else // ! QOLYESTER_ENABLE_MID
00133         aset_t&         lmprs = mprs;
00134 # endif
00135         degreemap_t     degree_map;     // degree map
00136         coverermap_t    coverer_map;    // covered map
00137         aset_t          n2;             // temp N2 set
00138 
00139         // Populate the N2 set for this interface
00140         for (thnsimpleset_t::const_iterator oh = lthns.begin();
00141              oh != lthns.end(); ++oh) {
00142           // Update the degree
00143           degree_map[oh->first] = oh->second.size();
00144 
00145           for (aset_t::const_iterator th = oh->second.begin();
00146                th != oh->second.end(); ++th) {
00147             coverer_map[*th].insert(oh->first);
00148             n2.insert(*th);             // Insert in N2 set
00149           }
00150         }
00151 
00152         // Preliminary MPR selection
00153 
00154         // Get the WILL_ALWAYS neighbors into the iface-local MPR-set first
00155         // and don't add then to the global removal-candidates set.
00156         for (nset_const_iterator n =
00157                nset_const_iterator::build(candidates.begin());
00158              n != nset_const_iterator::build(candidates.end()); ++n)
00159           if (n->willingness() == WILL_ALWAYS)
00160             lmprs.insert(n->main_addr());
00161 
00162         // Get the neighbors that are necessary relays to some 2-hop neighbors
00163         for (coverermap_t::const_iterator c = coverer_map.begin();
00164              c != coverer_map.end(); ++c)
00165           if (c->second.size() <= mprcoverage) {
00166             lmprs.insert(c->second.begin(), c->second.end());
00167             n2.erase(c->first);
00168           }
00169 
00170         // End of preliminary selection
00171         // Reach counter initialization
00172         // For each node in N2, the number of already-selected MPRs
00173         // reaching it is recorded.  The purpose is to let us know
00174         // when a node in N2 is already covered.
00175         typedef std::map<address_t, unsigned>   reachcount_t;
00176         reachcount_t                            reachcount;
00177 
00178         for (aset_t::const_iterator m = lmprs.begin();
00179              m != lmprs.end(); ++m) {
00180           candidates.erase(&set::Neighbor::make_key(*m));
00181           thnsimpleset_t::const_iterator        oh = lthns.find(*m);
00182           assert(oh != lthns.end());
00183           for (aset_t::const_iterator th = oh->second.begin();
00184                th != oh->second.end(); ++th)
00185             if (++reachcount[*th] >= mprcoverage)
00186               n2.erase(*th);
00187         }
00188 
00189         // Populating the 'remaining' 2-hop neighbor set
00190         // which will be used in the following loop.
00191         thnsimpleset_t                          rthns;
00192 
00193         for (thnsimpleset_t::const_iterator oh = lthns.begin();
00194              oh != lthns.end(); ++oh)
00195           for (aset_t::const_iterator th = oh->second.begin();
00196                th != oh->second.end(); ++th)
00197             if (n2.find(*th) != n2.end())
00198               rthns[oh->first].insert(*th);
00199 
00200         // Cycle while N2 is not empty
00201         while (!n2.empty()) {
00202 
00203           typedef std::map<address_t, unsigned> reachmap_t;
00204           reachmap_t                            reachmap;
00205 
00206           // Build the reachability map
00207           for (nset_const_iterator n =
00208                  nset_const_iterator::build(candidates.begin());
00209                n != nset_const_iterator::build(candidates.end()); ++n)
00210             reachmap[n->main_addr()] = rthns[n->main_addr()].size();
00211 
00212           // Get the neighbor with max willingness, reachability, degree.
00213 
00214           bool                  first = true;
00215           const set::Neighbor*  maxn = 0;
00216           unsigned              r = 0;
00217           unsigned              d = 0;
00218 
00219           for (nset_const_iterator n =
00220                  nset_const_iterator::build(candidates.begin());
00221                n != nset_const_iterator::build(candidates.end()); ++n) {
00222             unsigned n_r = reachmap[n->main_addr()];
00223             if (first ||
00224                 n->willingness() > maxn->willingness() ||
00225                 (n->willingness() == maxn->willingness() &&
00226                  (n_r > r ||
00227                   n_r == r && degree_map[n->main_addr()] > d))) {
00228               first = false;
00229               maxn  = &*n;
00230               r     = n_r;
00231               d     = degree_map[n->main_addr()];
00232             }
00233           }
00234 
00235           assert(!first);
00236 
00237           // Update reach counters and remove any node in N2 that
00238           // has enough coverage thanks to the selection of this MPR.
00239           aset_t&       a_thns = lthns[maxn->main_addr()];
00240           for (aset_t::const_iterator th = a_thns.begin();
00241                th != a_thns.end(); ++th) {
00242             if (++reachcount[*th] >= mprcoverage)
00243               n2.erase(*th);
00244           }
00245 
00246           // Insert the MPR into the iface-local MPR-set
00247           lmprs.insert(maxn->main_addr());
00248           // and in the removal-candidates set
00249           // and remove it from the set of candidates
00250           rcandidates.insert(maxn);
00251           candidates.erase(maxn);
00252         }
00253 
00254 # ifdef QOLYESTER_ENABLE_MID
00255         // Merge the iface-local MPR-set into the global MPR-set
00256         mprs.insert(lmprs.begin(), lmprs.end());
00257 # endif
00258 
00259       }
00260 
00261       // Optimize the MPR-set
00262 
00263       // Compute the coverage count for each node in N2.
00264       std::map<address_t, unsigned>     covcount_map;
00265       for (aset_t::const_iterator m = mprs.begin(); m != mprs.end(); ++m) {
00266         const aset_t&   m_thns = thns[*m];
00267         for (aset_t::const_iterator th = m_thns.begin(); th != m_thns.end(); ++th)
00268           ++covcount_map[*th];
00269       }
00270 
00271       // Compute a willingness map.  The point is to sort
00272       // removal-candidates by order of increasing willingness.
00273       typedef std::multimap<unsigned, address_t>        wmap_t;
00274       wmap_t                                            wmap;
00275       for (nset_const_iterator rc =
00276              nset_const_iterator::build(rcandidates.begin());
00277            rc != nset_const_iterator::build(rcandidates.end()); ++rc)
00278         wmap.insert(wmap_t::value_type(rc->willingness(), rc->main_addr()));
00279 
00280       // Iterate on the willingness map and check it the candidate can
00281       // be actually removed, i.e. check if removal doesn't decrease
00282       // some N2 node's coverage count below the MPR_COVERAGE
00283       // threshold.
00284       for (wmap_t::const_iterator rc = wmap.begin(); rc != wmap.end(); ++rc) {
00285         aset_t& rc_thns = thns[rc->second];
00286         bool    remove = true;
00287         for (aset_t::const_iterator th = rc_thns.begin(); th != rc_thns.end(); ++th)
00288           if (covcount_map[*th] <= mprcoverage) {
00289             remove = false;
00290             break;
00291           }
00292         if (remove)
00293           mprs.erase(rc->second);
00294       }
00295 
00296       bool      changed = false;
00297 
00298       // Apply the MPR changes.
00299       for (cproxy_t::sym_neighborset_t::iterator n =
00300              cproxy.sym_neighborset().begin();
00301            n != cproxy.sym_neighborset().end(); ++n) {
00302         if (n->is_mpr()) {
00303           if (mprs.find(n->main_addr()) == mprs.end()) {
00304             cproxy.unset_mpr(n);
00305             changed = true;
00306           }
00307         } else
00308           if (mprs.find(n->main_addr()) != mprs.end()) {
00309             cproxy.set_mpr(n);
00310             changed = true;
00311           }
00312       }
00313 
00314       if (changed) {
00315         routes_recomp.set_mark();
00316         if (tc_redundancy >= mprselset_mprset)
00317           advset_changed.set_mark();
00318       }
00319     }
00320 
00321   } // namespace alg
00322 
00323 } // Namespace olsr
00324 
00325 #endif // !QOLYESTER_DAEMON_ALG_MPRSELECTION_HXX

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