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