00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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()) {
00043
00044 if (d.size() < Message::min_length + min_length)
00045 return true;
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
00061 mraw->type = TC_MESSAGE;
00062 mraw->vtime = utl::Vtime(cst::top_hold_time);
00063
00064 main_addr.dump(mraw->addr);
00065 mraw->ttl = 255;
00066 mraw->hopcount = 0;
00067 mraw->seqnum = htons(Message::seqnum);
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
00166
00167 utl::ConstData payload = d + sizeof (raw);
00168
00169
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
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
00183 for (toposet_t::toposet_t::iterator i = x.first;
00184 i != x.second; )
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
00192 x = topo_set.toposet().equal_range(set::TopologyEntry::
00193 make_key(mh.originator));
00194
00195
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
00210
00211
00212
00213
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
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 }
00240
00241 }
00242
00243 #endif // ! QOLYESTER_DAEMON_MSG_TC_HXX