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