00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifndef QOLYESTER_DAEMON_MSG_HELLO_HXX
00020 # define QOLYESTER_DAEMON_MSG_HELLO_HXX 1
00021
00022 # include <ostream>
00023 # include <list>
00024
00025 # include "alg/mainaddrof.hh"
00026 # include "utl/vtime.hh"
00027 # include "set/neighbors.hh"
00028
00029 # include "hello.hh"
00030
00031 namespace olsr {
00032
00033 extern std::ostream dump_hello;
00034 extern bool do_dump_hello;
00035 extern cproxy_t cproxy;
00036 extern thnset_t thn_set;
00037
00038 namespace msg {
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061 bool
00062 HELLOMessage::dump(utl::Data& d, const address_t& interface) const {
00063
00064
00065 if (d.size() < Message::min_length + min_length)
00066 return true;
00067
00068 if (do_dump_hello) {
00069 dump_hello << "HELLO preparation (" << interface << ") "
00070 << Message::seqnum << " {\n";
00071 }
00072
00073
00074
00075 Message::raw* mraw = reinterpret_cast<Message::raw*>(d.raw());
00076
00077 mraw->type = HELLO_MESSAGE;
00078 mraw->vtime = utl::Vtime(cst::neighb_hold_time);
00079
00080 main_addr.dump(mraw->addr);
00081 mraw->ttl = 1;
00082 mraw->hopcount = 0;
00083 mraw->seqnum = htons(Message::seqnum);
00084
00085
00086
00087 raw* hraw = reinterpret_cast<raw*>(mraw->data);
00088
00089 hraw->reserved = 0;
00090 hraw->htime = utl::Vtime(cst::hello_interval);
00091 hraw->willingness = willingness;
00092
00093 d += sizeof *mraw + sizeof *hraw;
00094
00095
00096
00097
00098
00099 typedef std::pair<address_t,
00100 cproxy_t::hello_linkset_t::iterator> lpair_t;
00101 typedef std::list<lpair_t> linklist_t;
00102
00103 typedef enum {
00104 nu = NOT_NEIGH << 2 | UNSPEC_LINK,
00105 na = NOT_NEIGH << 2 | ASYM_LINK,
00106 nl = NOT_NEIGH << 2 | LOST_LINK,
00107
00108 su = SYM_NEIGH << 2 | UNSPEC_LINK,
00109 sa = SYM_NEIGH << 2 | ASYM_LINK,
00110 ss = SYM_NEIGH << 2 | SYM_LINK,
00111 sl = SYM_NEIGH << 2 | LOST_LINK,
00112
00113 mu = MPR_NEIGH << 2 | UNSPEC_LINK,
00114 ma = MPR_NEIGH << 2 | ASYM_LINK,
00115 ms = MPR_NEIGH << 2 | SYM_LINK,
00116 ml = MPR_NEIGH << 2 | LOST_LINK
00117 } linkcode_t;
00118
00119 linklist_t nu_list;
00120 linklist_t na_list;
00121 linklist_t nl_list;
00122
00123 linklist_t su_list;
00124 linklist_t sa_list;
00125 linklist_t ss_list;
00126 linklist_t sl_list;
00127
00128 linklist_t mu_list;
00129 linklist_t ma_list;
00130 linklist_t ms_list;
00131 linklist_t ml_list;
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141 ::size_t bytes_so_far = 0;
00142 bool ret = false;
00143
00144 std::set<address_t> already_advertised;
00145
00146 for (cproxy_t::hello_linkset_t::iterator l =
00147 cproxy.hello_linkset().begin(interface);
00148 l != cproxy.hello_linkset().end(interface); ++l) {
00149
00150
00151
00152
00153
00154
00155 if (cproxy.hello_linkset().stamp(l) == timeval_t::now())
00156 break;
00157
00158
00159 if (d.size() - bytes_so_far < ADDRESS_SIZE) {
00160
00161
00162
00163
00164 if (cproxy.hello_linkset().expired(l, cst::refresh_interval,
00165 timeval_t::in(cst::hello_interval))) {
00166 ret = true;
00167 break;
00168 }
00169
00170
00171
00172 continue;
00173 }
00174
00175
00176 cproxy_t::neighborset_t::iterator n =
00177 cproxy.neighborset().find(set::Neighbor::make_key(l->main_addr()));
00178
00179 assert(n != cproxy.neighborset().end());
00180
00181 int link_type = 0;
00182
00183 if (l->local_addr() != interface) {
00184
00185 std::pair<set::Neighbor::linkset_t::const_iterator,
00186 set::Neighbor::linkset_t::const_iterator> er =
00187 n->find_lifaces(interface);
00188
00189
00190
00191
00192 if (er.first != er.second ||
00193 already_advertised.find(n->main_addr()) != already_advertised.end()) {
00194 cproxy.hello_linkset().set_stamp(l);
00195 continue;
00196 }
00197
00198 already_advertised.insert(n->main_addr());
00199
00200 link_type = UNSPEC_LINK;
00201 } else {
00202 # ifdef QOLYESTER_ENABLE_LINKHYS
00203 if (!l->losttime().is_past())
00204 link_type = LOST_LINK;
00205 else if (l->pending())
00206 continue;
00207 else
00208 # endif // !QOLYESTER_ENABLE_LINKHYS
00209 if (!l->symtime().is_past())
00210 link_type = SYM_LINK;
00211 else if (!l->asymtime().is_past())
00212 link_type = ASYM_LINK;
00213 else
00214 link_type = LOST_LINK;
00215 }
00216
00217
00218 int neighbor_type = 0;
00219
00220 if (n->is_mpr())
00221 neighbor_type = MPR_NEIGH;
00222 else if (n->is_sym())
00223 neighbor_type = SYM_NEIGH;
00224 else
00225 neighbor_type = NOT_NEIGH;
00226
00227 if (do_dump_hello) {
00228 dump_hello << " " << (link_type != UNSPEC_LINK ?
00229 l->remote_addr() :
00230 n->main_addr()) << " ";
00231 switch (link_type) {
00232 case UNSPEC_LINK: dump_hello << "U "; break;
00233 case ASYM_LINK: dump_hello << "A "; break;
00234 case SYM_LINK: dump_hello << "S "; break;
00235 case LOST_LINK: dump_hello << "L "; break;
00236 }
00237 switch (neighbor_type) {
00238 case NOT_NEIGH: dump_hello << "N\n"; break;
00239 case SYM_NEIGH: dump_hello << "S\n"; break;
00240 case MPR_NEIGH: dump_hello << "M\n"; break;
00241 }
00242 }
00243
00244
00245
00246
00247
00248 linklist_t* list_ptr = 0;
00249
00250 switch (linkcode_t(neighbor_type << 2 | link_type)) {
00251
00252 case nu: list_ptr = &nu_list; break;
00253 case na: list_ptr = &na_list; break;
00254 case nl: list_ptr = &nl_list; break;
00255
00256 case su: list_ptr = &su_list; break;
00257 case sa: list_ptr = &sa_list; break;
00258 case ss: list_ptr = &ss_list; break;
00259 case sl: list_ptr = &sl_list; break;
00260
00261 case mu: list_ptr = &mu_list; break;
00262 case ma: list_ptr = &ma_list; break;
00263 case ms: list_ptr = &ms_list; break;
00264 case ml: list_ptr = &ml_list; break;
00265
00266
00267 default: list_ptr = 0; assert(list_ptr != 0);
00268 }
00269
00270
00271
00272
00273 if (list_ptr->empty())
00274
00275 if (d.size() - bytes_so_far <
00276 sizeof (linksetraw) + ADDRESS_SIZE) {
00277
00278
00279 if (cproxy.hello_linkset().expired(l, cst::refresh_interval,
00280 timeval_t::in(cst::hello_interval)))
00281 ret = true;
00282
00283 continue;
00284 } else
00285 bytes_so_far += sizeof (linksetraw) + ADDRESS_SIZE;
00286 else
00287 bytes_so_far += ADDRESS_SIZE;
00288
00289
00290
00291
00292
00293 if (link_type == UNSPEC_LINK)
00294 list_ptr->push_back(lpair_t(n->main_addr(), l));
00295 else
00296 list_ptr->push_back(lpair_t(l->remote_addr(), l));
00297 }
00298
00299 if (do_dump_hello)
00300 dump_hello << "}" << std::endl;
00301
00302
00303
00304
00305 # define PROC_XX_SET(Code) \
00306 do { \
00307 if (Code ## _list.empty()) \
00308 break; \
00309 \
00310 linksetraw* lraw = reinterpret_cast<linksetraw*>(d.raw()); \
00311 \
00312 lraw->linkcode = linkcode_t(Code); \
00313 lraw->reserved = 0; \
00314 \
00315 d += sizeof *lraw; \
00316 \
00317 for (linklist_t::iterator i = Code ## _list.begin(); \
00318 i != Code ## _list.end(); \
00319 d += ADDRESS_SIZE, ++i) { \
00320 i->first.dump(d.raw()); \
00321 cproxy.hello_linkset().set_stamp(i->second); \
00322 } \
00323 \
00324 lraw->linkmessagesize = htons(d.raw() - \
00325 reinterpret_cast<u_int8_t*>(lraw)); \
00326 } while (0)
00327
00328 PROC_XX_SET(nu);
00329 PROC_XX_SET(na);
00330 PROC_XX_SET(nl);
00331
00332 PROC_XX_SET(su);
00333 PROC_XX_SET(sa);
00334 PROC_XX_SET(ss);
00335 PROC_XX_SET(sl);
00336
00337 PROC_XX_SET(mu);
00338 PROC_XX_SET(ma);
00339 PROC_XX_SET(ms);
00340 PROC_XX_SET(ml);
00341
00342 mraw->size = htons(d.raw() - reinterpret_cast<u_int8_t*>(mraw));
00343
00344 return ret;
00345 }
00346
00347
00348 void HELLOMessage::parse(const utl::ConstData& d,
00349 const Message::header& mh) {
00350
00351
00352 const raw* h = reinterpret_cast<const raw*>(d.raw());
00353
00354 if (do_dump_hello) {
00355 dump_hello << "HELLO from " << mh.originator
00356 << " (" << mh.sender << " -> " << mh.receiver
00357 << ") M(" << mh.mseqnum << ") P("
00358 << mh.pseqnum << ") Ht(" << (float) utl::Vtime(h->htime) << ") {\n";
00359 }
00360
00361 utl::ConstData payload = d + sizeof (raw);
00362
00363 int link_type = UNSPEC_LINK;
00364 int neigh_type = NOT_NEIGH;
00365 typedef std::set<address_t> thns_t;
00366 thns_t thns;
00367
00368
00369 for (const linksetraw* lraw =
00370 reinterpret_cast<const linksetraw*>(payload.raw());
00371
00372 payload.size() > 0;
00373
00374 payload += ntohs(lraw->linkmessagesize),
00375
00376 lraw = reinterpret_cast<const linksetraw*>
00377 ((lraw->data - sizeof (linksetraw) +
00378 ntohs(lraw->linkmessagesize)))) {
00379
00380 unsigned len = (ntohs(lraw->linkmessagesize) -
00381 sizeof (linksetraw)) / ADDRESS_SIZE;
00382 const u_int8_t (*addrs)[ADDRESS_SIZE] =
00383 reinterpret_cast<const u_int8_t (*)[ADDRESS_SIZE]>(lraw->data);
00384
00385
00386 u_int8_t ltype = lraw->linkcode & 0x3;
00387 u_int8_t ntype = lraw->linkcode >> 2 & 0x03;
00388
00389
00390 for (unsigned i = 0; i < len; ++i) {
00391
00392 address_t addr(addrs[i], ADDRESS_SIZE);
00393 address_t maddr = alg::main_addr_of(addr);
00394
00395 if (do_dump_hello) {
00396 dump_hello << " " << addr << " ";
00397 switch (ltype) {
00398 case UNSPEC_LINK: dump_hello << "U "; break;
00399 case ASYM_LINK: dump_hello << "A "; break;
00400 case SYM_LINK: dump_hello << "S "; break;
00401 case LOST_LINK: dump_hello << "L "; break;
00402 }
00403 switch (ntype) {
00404 case NOT_NEIGH: dump_hello << "N\n"; break;
00405 case SYM_NEIGH: dump_hello << "S\n"; break;
00406 case MPR_NEIGH: dump_hello << "M\n"; break;
00407 }
00408 }
00409
00410 if (addr == mh.receiver) {
00411
00412
00413
00414 link_type = ltype;
00415 neigh_type = ntype;
00416 } else {
00417
00418 if (addr != maddr)
00419
00420
00421
00422
00423
00424 thn_set.erase(set::TwoHopNeighbor::make_key(mh.originator,
00425 addr));
00426 if (ntype == SYM_NEIGH || ntype == MPR_NEIGH) {
00427
00428
00429 thns.insert(maddr);
00430 } else {
00431
00432
00433 thn_set.erase(set::TwoHopNeighbor::make_key(mh.originator,
00434 maddr));
00435 }
00436 }
00437 }
00438 }
00439
00440 if (do_dump_hello)
00441 dump_hello << "}" << std::endl;
00442
00443
00444 cproxy_t::neighborset_t::iterator n =
00445 # ifdef QOLYESTER_ENABLE_LINKHYS
00446 cproxy.insert_link(mh, link_type, h->willingness,
00447 utl::Vtime(h->htime)).first;
00448 # else // !QOLYESTER_ENABLE_LINKHYS
00449 cproxy.insert_link(mh, link_type, h->willingness).first;
00450 # endif
00451
00452 if (link_type != UNSPEC_LINK)
00453 if (neigh_type == MPR_NEIGH)
00454 cproxy.set_mprsel(n, mh.validity);
00455 else if (neigh_type == SYM_NEIGH)
00456 cproxy.unset_mprsel(n);
00457
00458 if (n->is_sym()) {
00459
00460 for (thns_t::const_iterator i = thns.begin(); i != thns.end(); ++i)
00461 thn_set.insert(set::TwoHopNeighbor(mh.originator, *i, mh.validity));
00462
00463 }
00464
00465 }
00466
00467 }
00468
00469 }
00470
00471 #endif // ! QOLYESTER_DAEMON_MSG_HELLO_HXX