00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef WIFI_FRAME_STATS_HXX_
00023 # define WIFI_FRAME_STATS_HXX_
00024
00025 # include <wipal/wifi/frame/stats.hh>
00026
00027 # include <wipal/wifi/frame/dissector/dissector.hh>
00028
00029 namespace wifi
00030 {
00031
00032 namespace frame
00033 {
00034
00035 namespace stats
00036 {
00037
00038
00039
00040
00041
00042 inline
00043 abstract_stats::~abstract_stats()
00044 {
00045 }
00046
00047
00048
00049
00050
00051 inline
00052 simple_counters::simple_counters(): total_ (0),
00053 retransmitted_ (0)
00054 {
00055 memset(type_count_, 0, sizeof (type_count_));
00056 memset(subtype_count_, 0, sizeof (subtype_count_));
00057 }
00058
00059 inline
00060 void
00061 simple_counters::operator () (unsigned type,
00062 unsigned subtype,
00063 bool retransmitted)
00064 {
00065 assert(type < 4);
00066 assert(subtype < 16);
00067
00068 ++total_;
00069 if (retransmitted)
00070 ++retransmitted_;
00071 ++type_count_[type];
00072 ++subtype_count_[type][subtype];
00073 }
00074
00075 inline
00076 std::ostream&
00077 simple_counters::print(std::ostream& o) const
00078 {
00079 o << "frame count: " << total_ << '\n'
00080 << "retransmissions: " << retransmitted_ << '\n'
00081 << "retransmissions: " << (100.l * retransmitted_ / total_) << "%\n"
00082 "\n"
00083 "begin frame types/subtypes\n";
00084 for (unsigned t = 0; t < 4; ++t)
00085 {
00086 const unsigned tc = type_count_[t];
00087
00088 if (not tc)
00089 continue;
00090
00091 o << " " << type::names[t] << ": " << (100.l * tc / total_) << "%"
00092 " (" << tc << ")\n";
00093
00094 for (unsigned st = 0; st < 16; ++st)
00095 {
00096 const unsigned stc = subtype_count_[t][st];
00097
00098 if (not stc)
00099 continue;
00100
00101 o << "\t" << subtype::names[t][st] << ": "
00102 << (100.l * stc / total_) << "% of total, "
00103 << (100.l * stc / tc) << "% of this type"
00104 " (" << stc << ")\n";
00105 }
00106 }
00107 o << "end frame types/subtypes" << std::endl;
00108 return o;
00109 }
00110
00111 inline
00112 unsigned
00113 simple_counters::total() const
00114 {
00115 return total_;
00116 }
00117
00118
00119
00120
00121
00122 inline
00123 gap_lengths::gap_lengths(): gl_freqs_ (gl_freqs_size),
00124 gap_count_ (0)
00125 {
00126 }
00127
00128 inline
00129 void
00130 gap_lengths::operator () (unsigned gap_length)
00131 {
00132 assert(1 < gap_length);
00133 assert(gap_length < gl_max);
00134
00135 ++gl_freqs_[gap_length / gl_freqs_resolution];
00136 ++gap_count_;
00137 }
00138
00139 inline
00140 std::ostream&
00141 gap_lengths::print(std::ostream& o) const
00142 {
00143 for (unsigned i = 0; i < gl_freqs_.size(); ++i)
00144 {
00145 const unsigned f = gl_freqs_[i];
00146
00147 if (not f)
00148 continue;
00149
00150 o << " " << (i * gl_freqs_resolution + (gl_freqs_resolution / 2))
00151 << '\t' << (double (f) / gap_count_) << '\n';
00152 }
00153 return o << std::flush;
00154 }
00155
00156
00157
00158
00159
00160 inline
00161 missed_estimations::missed_estimations(const simple_counters& c): c_ (&c)
00162 {
00163 memset(missed_, 0, sizeof (missed_));
00164 }
00165
00166 inline
00167 void
00168 missed_estimations::operator () ()
00169 {
00170 for (unsigned i = 0; i < sizeof (missed_) / sizeof (*missed_); ++i)
00171 ++missed_[i];
00172 }
00173
00174 inline
00175 void
00176 missed_estimations::operator () (unsigned gap_length)
00177 {
00178 for (unsigned i = 0; i < sizeof (missed_) / sizeof (*missed_); ++i)
00179 if (int (gap_length) < (int (i) + 1) * threshold_steps)
00180 missed_[i] += gap_length - 1;
00181 }
00182
00183 inline
00184 std::ostream&
00185 missed_estimations::print(std::ostream& o) const
00186 {
00187 for (unsigned i = 0; i < sizeof (missed_) / sizeof (*missed_); ++i)
00188 o << " " << ((int (i) + 1) * threshold_steps) << '\t'
00189 << (double (missed_[i]) / (missed_[i] + c_->total())) << '\n';
00190 return o << std::flush;
00191 }
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201 inline
00202 stats::stats(): missed_ (counters_)
00203 {
00204 }
00205
00206 inline
00207 stats::hooks::hooks(): type (-1),
00208 subtype (-1),
00209 retx (false),
00210 receiver (0)
00211 {
00212 }
00213
00214
00215 inline
00216 stats::state::state(unsigned last_frame_id,
00217 const seqctl& last_sc,
00218 const tool::microseconds& last_rx_stamp):
00219 last_frame_id (last_frame_id),
00220 last_sc (last_sc),
00221 last_rx_stamp (last_rx_stamp)
00222 {
00223 }
00224
00225
00226
00227
00228
00229 inline
00230 void
00231 stats::clear_states()
00232 {
00233 states_.clear();
00234 }
00235
00236 inline
00237 std::ostream&
00238 stats::print(std::ostream& o) const
00239 {
00240 return o << counters()
00241 << "\n"
00242 "begin gap length frequencies\n"
00243 << gaplens()
00244 << "end gap length frequencies\n"
00245 "\n"
00246 "begin missed frames estimations\n"
00247 << missed()
00248 << "end missed frames estimation" << std::endl;
00249 }
00250
00251 inline
00252 const simple_counters&
00253 stats::counters() const
00254 {
00255 return counters_;
00256 }
00257
00258 inline
00259 const gap_lengths&
00260 stats::gaplens() const
00261 {
00262 return gap_lengths_;
00263 }
00264
00265 inline
00266 const missed_estimations&
00267 stats::missed() const
00268 {
00269 return missed_;
00270 }
00271
00272
00273
00274
00275
00276 inline
00277 void
00278 stats::hooks::addr_hook(const void* f, size_t,
00279 unsigned i, const addr& a)
00280 {
00281 switch (i)
00282 {
00283 case 1:
00284 type = type_of(f);
00285 subtype = subtype_of(f);
00286 retx = control_flag(3, f);
00287 receiver = &a;
00288 break;
00289
00290 case 2:
00291 if (type == frame::type::management or type == frame::type::data)
00292 id = state_id (a, addr::broadcast());
00293 break;
00294 }
00295 }
00296
00297 inline
00298 void
00299 stats::hooks::seq_ctl_hook(const void*, size_t, unsigned fn, unsigned sn)
00300 {
00301 sc = seqctl (sn, fn);
00302 }
00303
00304 inline
00305 void
00306 stats::hooks::qos_ctl_hook(const void*, size_t,
00307 unsigned tid,
00308 bool, unsigned, unsigned)
00309 {
00310 assert(id);
00311
00312 if (*receiver == addr::broadcast())
00313 return;
00314
00315 id->get<1>() = *receiver;
00316 id->get<2>() = tid;
00317 }
00318
00319 template <class PhyHeader, class Frame>
00320 void
00321 stats::account(const Frame& f)
00322 {
00323 const dissector<hooks> d = dissect<PhyHeader, hooks>(f);
00324
00325 if (d.status() == dissector_status::invalid)
00326 return;
00327
00328 counters_(d.type, d.subtype, d.retx);
00329
00330 if (not d.id or not d.sc)
00331 return;
00332
00333 const unsigned frame_id = f.pcap_header()->id;
00334 const tool::microseconds& rx_stamp = f.microseconds();
00335 const states::iterator i = states_.find(*d.id);
00336
00337 state new_state (frame_id, *d.sc, rx_stamp);
00338
00339
00340 if (i == states_.end())
00341 {
00342 states_.insert(std::make_pair(*d.id, new_state));
00343 return;
00344 }
00345
00346 const state& s = i->second;
00347
00348
00349 if (rx_stamp - s.last_rx_stamp < state_lifetime)
00350 {
00351
00352 if (*d.sc < s.last_sc and d.retx)
00353 return;
00354
00355
00356 if (*d.sc > s.last_sc and d.retx)
00357 missed_();
00358
00359 const int delta = d.sc->seqnum_get() - s.last_sc.seqnum_get();
00360
00361
00362 if (1 < delta)
00363 {
00364 gap_lengths_(delta);
00365 missed_(delta);
00366 }
00367 }
00368 i->second = new_state;
00369 }
00370
00371
00372
00373
00374
00375 inline
00376 std::ostream&
00377 operator << (std::ostream& os, const abstract_stats& s)
00378 {
00379 return s.print(os);
00380 }
00381
00382 }
00383
00384 }
00385
00386 }
00387
00388 #endif // ! WIFI_FRAME_STATS_HXX_