EMANE  1.2.1
commonlayerstatistics.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013-2014 - Adjacent Link LLC, Bridgewater, New Jersey
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * * Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * * Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in
13  * the documentation and/or other materials provided with the
14  * distribution.
15  * * Neither the name of Adjacent Link LLC nor the names of its
16  * contributors may be used to endorse or promote products derived
17  * from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  */
32 
34 #include "emane/statisticnumeric.h"
36 #include "emane/statistictable.h"
37 
38 #include <vector>
39 #include <map>
40 
41 class EMANE::Utils::CommonLayerStatistics::Implementation
42 {
43 public:
44  Implementation(const StatisticTableLabels & unicastDropTableLabels,
45  const StatisticTableLabels & broadcastDropTableLabels,
46  const std::string & sInstance) :
47  sInstance_{sInstance},
48  bHaveDropTables_{},
49  unicastDropTableLabels_{"NEM"},
50  broadcastDropTableLabels_{"NEM"},
51  unicastAcceptTableLabels_{"NEM", "Num Pkts Tx", "Num Bytes Tx", "Num Pkts Rx", "Num Bytes Rx"},
52  broadcastAcceptTableLabels_{"NEM", "Num Pkts Tx", "Num Bytes Tx", "Num Pkts Rx", "Num Bytes Rx"},
53  pNumUpstreamPacketsUnicastTx_{},
54  pNumUpstreamBytesUnicastTx_{},
55  pNumUpstreamPacketsBroadcastTx_{},
56  pNumUpstreamBytesBroadcastTx_{},
57  pNumUpstreamPacketsUnicastRx_{},
58  pNumUpstreamBytesUnicastRx_{},
59  pNumUpstreamPacketsUnicastDrop_{},
60  pNumUpstreamPacketsBroadcastRx_{},
61  pNumUpstreamBytesBroadcastRx_{},
62  pNumUpstreamPacketsBroadcastDrop_{},
63  pNumDownstreamPacketsUnicastTx_{},
64  pNumDownstreamBytesUnicastTx_{},
65  pNumDownstreamPacketsBroadcastTx_{},
66  pNumDownstreamBytesBroadcastTx_{},
67  pNumDownstreamPacketsUnicastRx_{},
68  pNumDownstreamBytesUnicastRx_{},
69  pNumDownstreamPacketsUnicastDrop_{},
70  pNumDownstreamPacketsBroadcastRx_{},
71  pNumDownstreamBytesBroadcastRx_{},
72  pNumDownstreamPacketsBroadcastDrop_{},
73  pNumDownstreamPacketsUnicastGenerated_{},
74  pNumDownstreamBytesUnicastGenerated_{},
75  pNumDownstreamPacketsBroadcastGenerated_{},
76  pNumDownstreamBytesBroadcastGenerated_{},
77  pStatisticUnicastDropTable_{},
78  pStatisticBroadcastDropTable_{},
79  pStatisticUnicastAcceptTable_{},
80  pStatisticBroadcastAcceptTable_{}
81  {
82  if(unicastDropTableLabels.empty())
83  {
84  bHaveDropTables_ = false;
85  }
86  else
87  {
88  bHaveDropTables_ = true;
89 
90  unicastDropTableLabels_.insert(unicastDropTableLabels_.end(),
91  unicastDropTableLabels.begin(),
92  unicastDropTableLabels.end());
93 
94  if(broadcastDropTableLabels.empty())
95  {
96  broadcastDropTableLabels_ = unicastDropTableLabels_;
97  }
98  else
99  {
100  broadcastDropTableLabels_.insert(broadcastDropTableLabels_.end(),
101  broadcastDropTableLabels.begin(),
102  broadcastDropTableLabels.end());
103  }
104  }
105  }
106 
107  ~Implementation(){ }
108 
109  void registerStatistics(StatisticRegistrar & statisticRegistrar)
110  {
112  avgUpstreamProcessingDelay_.registerStatistic(
113  statisticRegistrar.registerNumeric<Average>("avgUpstreamProcessingDelay" + sInstance_,
115  "Average upstream processing delay"));
116 
117 
118  // upstream tx ucast
119  pNumUpstreamPacketsUnicastTx_ =
120  statisticRegistrar.registerNumeric<Counter>("numUpstreamPacketsUnicastTx" + sInstance_,
122  "Number of upstream unicast packets transmitted");
123 
124  pNumUpstreamBytesUnicastTx_ =
125  statisticRegistrar.registerNumeric<Counter>("numUpstreamBytesUnicastTx" + sInstance_,
127  "Number of upstream unicast bytes transmitted");
130  // upstream tx bcast
131  pNumUpstreamPacketsBroadcastTx_ =
132  statisticRegistrar.registerNumeric<Counter>("numUpstreamPacketsBroadcastTx" + sInstance_,
134  "Number of upstream broadcast packets transmitted");
135 
136  pNumUpstreamBytesBroadcastTx_ =
137  statisticRegistrar.registerNumeric<Counter>("numUpstreamBytesBroadcastTx" + sInstance_,
139  "Number of updtream broadcast bytes transmitted");
140 
141  // upstream rx ucast
142  pNumUpstreamPacketsUnicastRx_ =
143  statisticRegistrar.registerNumeric<Counter>("numUpstreamPacketsUnicastRx" + sInstance_,
145  "Number upstream unicast packets received");
146 
147  pNumUpstreamBytesUnicastRx_ =
148  statisticRegistrar.registerNumeric<Counter>("numUpstreamBytesUnicastRx" + sInstance_,
150  "Number upstream unicast bytes received");
151 
152  pNumUpstreamPacketsUnicastDrop_ =
153  statisticRegistrar.registerNumeric<Counter>("numUpstreamPacketsUnicastDrop" + sInstance_,
155  "Number of upstream unicast packets dropped");
156 
157  // upstream rx bcast
158  pNumUpstreamPacketsBroadcastRx_ =
159  statisticRegistrar.registerNumeric<Counter>("numUpstreamPacketsBroadcastRx" + sInstance_,
161  "Number of upstream broadcast packets received");
162 
163  pNumUpstreamBytesBroadcastRx_ =
164  statisticRegistrar.registerNumeric<Counter>("numUpstreamBytesBroadcastRx" + sInstance_,
166  "Number of upstream broadcast bytes received");
167 
168  pNumUpstreamPacketsBroadcastDrop_ =
169  statisticRegistrar.registerNumeric<Counter>("numUpstreamPacketsBroadcastDrop" + sInstance_,
171  "Number of upstream broadcast packets dropped");
172 
173  // downstream tx ucast
174  pNumDownstreamPacketsUnicastTx_ =
175  statisticRegistrar.registerNumeric<Counter>("numDownstreamPacketsUnicastTx" + sInstance_,
177  "Number of downstream unicast packets transmitted");
178 
179  pNumDownstreamBytesUnicastTx_ =
180  statisticRegistrar.registerNumeric<Counter>("numDownstreamBytesUnicastTx" + sInstance_,
182  "Number of downstream unicast bytes transmitted");
183 
184  // downstream tx bcast
185  pNumDownstreamPacketsBroadcastTx_ =
186  statisticRegistrar.registerNumeric<Counter>("numDownstreamPacketsBroadcastTx" + sInstance_,
188  "Number of downstream broadcast packets transmitted");
189 
190  pNumDownstreamBytesBroadcastTx_ =
191  statisticRegistrar.registerNumeric<Counter>("numDownstreamBytesBroadcastTx" + sInstance_,
193  "Number of downstream broadcast bytes transmitted");
194 
195  // downstream rx ucast
196  pNumDownstreamPacketsUnicastRx_ =
197  statisticRegistrar.registerNumeric<Counter>("numDownstreamPacketsUnicastRx" + sInstance_,
199  "Number of downstream unicast packets received");
200 
201  pNumDownstreamBytesUnicastRx_ =
202  statisticRegistrar.registerNumeric<Counter>("numDownstreamBytesUnicastRx" + sInstance_,
204  "Number of downstream unicast bytes received");
205 
206  pNumDownstreamPacketsUnicastDrop_ =
207  statisticRegistrar.registerNumeric<Counter>("numDownstreamPacketsUnicastDrop" + sInstance_,
209  "Number of downstream unicast packets dropped");
210 
211  // downstream rx bcast
212  pNumDownstreamPacketsBroadcastRx_ =
213  statisticRegistrar.registerNumeric<Counter>("numDownstreamPacketsBroadcastRx" + sInstance_,
215  "Number of downstream broadcast packets received");
216 
217  pNumDownstreamBytesBroadcastRx_ =
218  statisticRegistrar.registerNumeric<Counter>("numDownstreamBytesBroadcastRx" + sInstance_,
220  "Number of downstream broadcast bytes received");
221 
222  pNumDownstreamPacketsBroadcastDrop_ =
223  statisticRegistrar.registerNumeric<Counter>("numDownstreamPacketsBroadcastDrop" + sInstance_,
225  "Number of downstream broadcast packets dropped");
226 
227 
228  avgDownstreamProcessingDelay_.registerStatistic(
229  statisticRegistrar.registerNumeric<Average>("avgDownstreamProcessingDelay" + sInstance_,
230  StatisticProperties::CLEARABLE,
231  "Average downstream processing delay"));
232 
233 
234  // downstream generated ucast
235  pNumDownstreamPacketsUnicastGenerated_ =
236  statisticRegistrar.registerNumeric<Counter>("numDownstreamPacketsUnicastGenerated" + sInstance_,
238  "Number of layer generated downstream unicast packets");
239 
240  pNumDownstreamBytesUnicastGenerated_ =
241  statisticRegistrar.registerNumeric<Counter>("numDownstreamBytesUnicastGenerated" + sInstance_,
243  "Number of layer generated downstream unicast bytes");
244 
245  // downstream generated bcast
246  pNumDownstreamPacketsBroadcastGenerated_ =
247  statisticRegistrar.registerNumeric<Counter>("numDownstreamPacketsBroadcastGenerated" + sInstance_,
249  "Number of layer generated downstream broadcast packets");
250 
251  pNumDownstreamBytesBroadcastGenerated_ =
252  statisticRegistrar.registerNumeric<Counter>("numDownstreamBytesBroadcastGenerated" + sInstance_,
254  "Number of layer generated downstream broadcast bytes");
255 
256  if(bHaveDropTables_)
257  {
259  pStatisticUnicastDropTable_ =
260  statisticRegistrar.registerTable<NEMId>("UnicastPacketDropTable" + sInstance_,
261  unicastDropTableLabels_,
262  [this](StatisticTablePublisher * pTable)
263  {
264  std::lock_guard<std::mutex> m(nemUnicastDropTableMutex_);
265  nemUnicastDropCodeMap_.clear();
266  pTable->clear();
267  },
268  "Unicast packets dropped by reason code");
270  pStatisticBroadcastDropTable_ =
271  statisticRegistrar.registerTable<NEMId>("BroadcastPacketDropTable" + sInstance_,
272  broadcastDropTableLabels_,
273  [this](StatisticTablePublisher * pTable)
274  {
275  std::lock_guard<std::mutex> m(nemBroadcastDropTableMutex_);
276  nemBroadcastDropCodeMap_.clear();
277  pTable->clear();
278  },
279  "Broadcast packets dropped by reason code");
280  }
281 
282  pStatisticUnicastAcceptTable_ =
283  statisticRegistrar.registerTable<NEMId>("UnicastPacketAcceptTable" + sInstance_,
284  unicastAcceptTableLabels_,
285  [this](StatisticTablePublisher * pTable)
286  {
287  std::lock_guard<std::mutex> m(nemUnicastAcceptTableMutex_);
288  nemUnicastAcceptMap_.clear();
289  pTable->clear();
290  },
291  "Unicast packets accepted");
292 
293  pStatisticBroadcastAcceptTable_ =
294  statisticRegistrar.registerTable<NEMId>("BroadcastPacketAcceptTable" + sInstance_,
295  broadcastAcceptTableLabels_,
296  [this](StatisticTablePublisher * pTable)
297  {
298  std::lock_guard<std::mutex> m(nemBroadcastAcceptTableMutex_);
299  nemBroadcastAcceptMap_.clear();
300  pTable->clear();
301  },
302  "Broadcast packets accepted");
303  }
304 
305 
306  void processInbound(const UpstreamPacket & pkt)
307  {
308  if(isBroadcast(pkt))
309  {
310  ++*pNumUpstreamPacketsBroadcastRx_;
311 
312  *pNumUpstreamBytesBroadcastRx_ += pkt.length();
313  }
314  else
315  {
316  ++*pNumUpstreamPacketsUnicastRx_;
317 
318  *pNumUpstreamBytesUnicastRx_ += pkt.length();
319  }
320  }
321 
322 
323  void processOutbound(const UpstreamPacket & pkt, const Microseconds & delay, size_t dropCode)
324  {
325  if(dropCode)
326  {
327  // ensure tables are built for all src
328  updateDropTable(pkt.getPacketInfo(), dropCode, isBroadcast(pkt),true);
329  }
330  else
331  {
332  updateAcceptTable(pkt.getPacketInfo(), pkt.length(), isBroadcast(pkt), true, true);
333  }
334 
335  if(dropCode != 0)
336  {
337  if(isBroadcast(pkt))
338  {
339  ++*pNumUpstreamPacketsBroadcastDrop_;
340  }
341  else
342  {
343  ++*pNumUpstreamPacketsUnicastDrop_;
344  }
345  }
346  // update all tx stats
347  else
348  {
349  avgUpstreamProcessingDelay_.update(delay.count());
350 
351  if(isBroadcast(pkt))
352  {
353  ++*pNumUpstreamPacketsBroadcastTx_;
354 
355  *pNumUpstreamBytesBroadcastTx_ += pkt.length();
356  }
357  else
358  {
359  ++*pNumUpstreamPacketsUnicastTx_;
360 
361  *pNumUpstreamBytesUnicastTx_ += pkt.length();
362  }
363  }
364  }
365 
366 
367  void processInbound(const DownstreamPacket & pkt)
368  {
369  if(isBroadcast(pkt))
370  {
371  ++*pNumDownstreamPacketsBroadcastRx_;
372 
373  *pNumDownstreamBytesBroadcastRx_ += pkt.length();
374  }
375  else
376  {
377  ++*pNumDownstreamPacketsUnicastRx_;
378 
379  *pNumDownstreamBytesUnicastRx_ += pkt.length();
380  }
381  }
382 
383 
384  void processOutbound(const DownstreamPacket & pkt, const Microseconds & delay, size_t dropCode, bool bSelfGenerated)
385  {
386  if(dropCode)
387  {
388  updateDropTable(pkt.getPacketInfo(), dropCode, isBroadcast(pkt),false);
389  }
390  else
391  {
392  updateAcceptTable(pkt.getPacketInfo(), pkt.length(), isBroadcast(pkt), false, true);
393  }
394 
395  if(dropCode != 0)
396  {
397  if(isBroadcast(pkt))
398  {
399  ++*pNumDownstreamPacketsBroadcastDrop_;
400  }
401  else
402  {
403  ++*pNumDownstreamPacketsUnicastDrop_;
404  }
405  }
406  // update all tx stats
407  else
408  {
409  avgDownstreamProcessingDelay_.update(delay.count());
410 
411  if(bSelfGenerated)
412  {
413  if(isBroadcast(pkt))
414  {
415  ++*pNumDownstreamPacketsBroadcastGenerated_;
416 
417  pNumDownstreamBytesBroadcastGenerated_ += pkt.length();
418  }
419  else
420  {
421  ++*pNumDownstreamPacketsUnicastGenerated_;
422 
423  pNumDownstreamBytesUnicastGenerated_ += pkt.length();
424  }
425  }
426  else
427  {
428  if(isBroadcast(pkt))
429  {
430  ++*pNumDownstreamPacketsBroadcastTx_;
431 
432  *pNumDownstreamBytesBroadcastTx_ += pkt.length();
433  }
434  else
435  {
436  ++*pNumDownstreamPacketsUnicastTx_;
437 
438  *pNumDownstreamBytesUnicastTx_ += pkt.length();
439  }
440  }
441  }
442  }
443 
444 
445  void updateDropTable(const PacketInfo & packetInfo, size_t dropCode, bool bIsBroadcast, bool bIsUpstream)
446  {
447  if(bHaveDropTables_)
448  {
449  NEMDropCodeMap * pThisDropCodeMap{};
450 
451  StatisticTable<NEMId> * pThisTable{};
452 
453  size_t numColumns{};
454 
455  std::mutex * pThisMutex{};
456 
457  NEMId nemId{};
458 
459  if(bIsUpstream)
460  {
461  nemId = packetInfo.getSource();
462  }
463  else
464  {
465  nemId = packetInfo.getDestination();
466  }
467 
468  if(bIsBroadcast)
469  {
470  pThisDropCodeMap = &nemBroadcastDropCodeMap_;
471 
472  pThisTable = pStatisticBroadcastDropTable_;
473 
474  pThisMutex = &nemBroadcastDropTableMutex_;
475 
476  numColumns = broadcastDropTableLabels_.size();
477  }
478  else
479  {
480  pThisDropCodeMap = &nemUnicastDropCodeMap_;
481 
482  pThisTable = pStatisticUnicastDropTable_;
483 
484  pThisMutex = &nemUnicastDropTableMutex_;
485 
486  numColumns = unicastDropTableLabels_.size();
487  }
488 
489  // mutex syncronizes table map access
490  std::lock_guard<std::mutex> m(*pThisMutex);
491 
492  auto iter = pThisDropCodeMap->find(nemId);
493 
494  if(iter == pThisDropCodeMap->end())
495  {
496  // the first column is the nemid
497  std::vector<Any> v{Any{nemId}};
498 
499  // the rest are counters
500  v.insert(v.end(), numColumns - 1, Any{Counter{}});
501 
502  pThisTable->addRow(nemId, v);
503 
504  iter =
505  pThisDropCodeMap->insert(std::make_pair(nemId,
506  Counters(numColumns - 1, Counter{}))).first;
507  }
508 
509  if(dropCode > iter->second.size())
510  {
511  // throw exception XXX TODO
512  }
513  else if(dropCode != 0)
514  {
515  // bump internal table
516  ++(iter->second[dropCode - 1]);
517 
518  // set statistic table
519  pThisTable->setCell(nemId, dropCode, Any{iter->second[dropCode - 1]});
520  }
521  }
522  }
523 
524  void updateAcceptTable(const PacketInfo & packetInfo,
525  size_t sizeInBytes,
526  bool bIsBroadcast,
527  bool bIsUpstream,
528  bool bAccepted)
529  {
530  NEMAcceptMap * pThisAcceptMap{};
531 
532  StatisticTable<NEMId> * pThisTable{};
533 
534  size_t numColumns{};
535 
536  std::mutex * pThisMutex{};
537 
538  NEMId nemId{};
539 
540  if(bIsBroadcast)
541  {
542  pThisAcceptMap = &nemBroadcastAcceptMap_;
543 
544  pThisTable = pStatisticBroadcastAcceptTable_;
545 
546  pThisMutex = &nemBroadcastAcceptTableMutex_;
547 
548  numColumns = broadcastAcceptTableLabels_.size();
549 
550  nemId = packetInfo.getSource();
551  }
552  else
553  {
554  pThisAcceptMap = &nemUnicastAcceptMap_;
555 
556  pThisTable = pStatisticUnicastAcceptTable_;
557 
558  pThisMutex = &nemUnicastAcceptTableMutex_;
559 
560  numColumns = unicastAcceptTableLabels_.size();
561 
562  nemId = packetInfo.getSource();
563  }
564 
565  // mutex syncronizes table map access
566  std::lock_guard<std::mutex> m(*pThisMutex);
567 
568  auto iter = pThisAcceptMap->find(nemId);
569 
570  if(iter == pThisAcceptMap->end())
571  {
572  // the first column is the nemid
573  std::vector<Any> v{Any{nemId}};
574 
575  // the rest are counters
576  v.insert(v.end(), numColumns - 1, Any{Counter{}});
577 
578  pThisTable->addRow(nemId, v);
579 
580  iter =
581  pThisAcceptMap->insert(std::make_pair(nemId,
582  BasicCounts{})).first;
583  }
584 
585  if(bAccepted)
586  {
587  if(bIsUpstream)
588  {
589  // bump internal rx stats
590  ++(iter->second.numRxPackets_);
591  iter->second.numRxBytes_ += sizeInBytes;
592 
593  // set statistic table
594  pThisTable->setCell(nemId, NUM_PKTS_RX, Any{iter->second.numRxPackets_});
595  pThisTable->setCell(nemId, NUM_BYTES_RX, Any{iter->second.numRxBytes_});
596  }
597  else
598  {
599  // bump internal tx stats
600  ++(iter->second.numTxPackets_);
601  iter->second.numTxBytes_ += sizeInBytes;
602 
603  // set statistic table
604  pThisTable->setCell(nemId, NUM_PKTS_TX, Any{iter->second.numTxPackets_});
605  pThisTable->setCell(nemId, NUM_BYTES_TX , Any{iter->second.numTxBytes_});
606  }
607  }
608  }
609 
610 
611 private:
612 
613  // keep this is line with the AcceptTableLables
614  enum AcceptTableLabelIndex {NUM_PKTS_TX = 1, NUM_BYTES_TX = 2, NUM_PKTS_RX = 3, NUM_BYTES_RX = 4};
615 
616  using Counter = std::uint64_t;
617 
618  struct BasicCounts {
619  Counter numRxPackets_;
620  Counter numRxBytes_;
621  Counter numTxPackets_;
622  Counter numTxBytes_;
623 
624  BasicCounts() :
625  numRxPackets_{},
626  numRxBytes_{},
627  numTxPackets_{},
628  numTxBytes_{}
629  { }
630  };
631 
632  using Average = float;
633 
634  using Counters = std::vector<Counter>;
635 
636  using NEMDropCodeMap = std::map<NEMId, Counters>;
637 
638  using NEMAcceptMap = std::map<NEMId, BasicCounts>;
639 
640  NEMDropCodeMap nemUnicastDropCodeMap_;
641 
642  NEMDropCodeMap nemBroadcastDropCodeMap_;
643 
644  NEMAcceptMap nemUnicastAcceptMap_;
645 
646  NEMAcceptMap nemBroadcastAcceptMap_;
647 
648  std::mutex nemUnicastDropTableMutex_;
649 
650  std::mutex nemBroadcastDropTableMutex_;
651 
652  std::mutex nemUnicastAcceptTableMutex_;
653 
654  std::mutex nemBroadcastAcceptTableMutex_;
655 
656  const std::string sInstance_;
657 
658  bool bHaveDropTables_;
659 
660  StatisticTableLabels unicastDropTableLabels_;
661 
662  StatisticTableLabels broadcastDropTableLabels_;
663 
664  StatisticTableLabels unicastAcceptTableLabels_;
665 
666  StatisticTableLabels broadcastAcceptTableLabels_;
667 
668 
669  // upstream tx ucast
670  StatisticNumeric<Counter> * pNumUpstreamPacketsUnicastTx_;
671  StatisticNumeric<Counter> * pNumUpstreamBytesUnicastTx_;
672 
673  // upstream tx bcast
674  StatisticNumeric<Counter> * pNumUpstreamPacketsBroadcastTx_;
675  StatisticNumeric<Counter> * pNumUpstreamBytesBroadcastTx_;
676 
677  // upstream rx ucast
678  StatisticNumeric<Counter> * pNumUpstreamPacketsUnicastRx_;
679  StatisticNumeric<Counter> * pNumUpstreamBytesUnicastRx_;
680  StatisticNumeric<Counter> * pNumUpstreamPacketsUnicastDrop_;
681 
682  // upstream rx bcast
683  StatisticNumeric<Counter> * pNumUpstreamPacketsBroadcastRx_;
684  StatisticNumeric<Counter> * pNumUpstreamBytesBroadcastRx_;
685  StatisticNumeric<Counter> * pNumUpstreamPacketsBroadcastDrop_;
686 
687  // upstream processing delay
688  RunningAverage<Average> avgUpstreamProcessingDelay_;
689 
690  // downstream tx ucast
691  StatisticNumeric<Counter> * pNumDownstreamPacketsUnicastTx_;
692  StatisticNumeric<Counter> * pNumDownstreamBytesUnicastTx_;
693 
694  // downstream tx bcast
695  StatisticNumeric<Counter> * pNumDownstreamPacketsBroadcastTx_;
696  StatisticNumeric<Counter> * pNumDownstreamBytesBroadcastTx_;
697 
698  // downstream rx ucast
699  StatisticNumeric<Counter> * pNumDownstreamPacketsUnicastRx_;
700  StatisticNumeric<Counter> * pNumDownstreamBytesUnicastRx_;
701  StatisticNumeric<Counter> * pNumDownstreamPacketsUnicastDrop_;
702 
703  // downstream rx bcast
704  StatisticNumeric<Counter> * pNumDownstreamPacketsBroadcastRx_;
705  StatisticNumeric<Counter> * pNumDownstreamBytesBroadcastRx_;
706  StatisticNumeric<Counter> * pNumDownstreamPacketsBroadcastDrop_;
707 
708  // downstream processing delay
709  RunningAverage<Average> avgDownstreamProcessingDelay_;
710 
711  // downstream generated ucast
712  StatisticNumeric<Counter> * pNumDownstreamPacketsUnicastGenerated_;
713  StatisticNumeric<Counter> * pNumDownstreamBytesUnicastGenerated_;
714 
715  // downstream generated bcast
716  StatisticNumeric<Counter> * pNumDownstreamPacketsBroadcastGenerated_;
717  StatisticNumeric<Counter> * pNumDownstreamBytesBroadcastGenerated_;
718 
719  StatisticTable<NEMId> * pStatisticUnicastDropTable_;
720  StatisticTable<NEMId> * pStatisticBroadcastDropTable_;
721 
722  StatisticTable<NEMId> * pStatisticUnicastAcceptTable_;
723  StatisticTable<NEMId> * pStatisticBroadcastAcceptTable_;
724 
725 
726  inline bool isBroadcast(const DownstreamPacket & pkt)
727  {
728  return(pkt.getPacketInfo().getDestination() == NEM_BROADCAST_MAC_ADDRESS);
729  }
730 
731  inline bool isBroadcast(const UpstreamPacket & pkt)
732  {
733  return(pkt.getPacketInfo().getDestination() == NEM_BROADCAST_MAC_ADDRESS);
734  }
735 
736 };
737 
738 
739 
741  const StatisticTableLabels & broadcastDropTableLabels,
742  const std::string & sInstance):
743 pImpl_{new Implementation{unicastDropTableLabels, broadcastDropTableLabels, sInstance}}
744 { }
745 
746 
748 { }
749 
750 
752 {
753  pImpl_->registerStatistics(statisticRegistrar);
754 }
755 
756 
758 {
759  pImpl_->processInbound(pkt);
760 }
761 
762 
764  Microseconds delay,
765  size_t dropCode)
766 {
767  pImpl_->processOutbound(pkt, delay, dropCode);
768 }
769 
770 
772 {
773  pImpl_->processInbound(pkt);
774 }
775 
776 
778  Microseconds delay,
779  size_t dropCode,
780  bool bSelfGenerated)
781 {
782  pImpl_->processOutbound(pkt, delay, dropCode, bSelfGenerated);
783 }
A Packet class that allows upstream processing to strip layer headers as the packet travels up the st...
void processOutbound(const UpstreamPacket &pkt, Microseconds delay, size_t dropCode={})
constexpr NEMId NEM_BROADCAST_MAC_ADDRESS
Definition: types.h:69
void registerStatistics(StatisticRegistrar &statisticRegistrar)
The StatisticRegistrar allows NEM layers to register statistics and statistic tables. Statistics and Statistic tables are owned by the emulator framework and a borrowed reference is returned to the registering NEM layer.
std::vector< std::string > StatisticTableLabels
Specialized packet the allows downstream processing to add layer specific headers as the packet trave...
std::chrono::microseconds Microseconds
Definition: types.h:45
std::uint16_t NEMId
Definition: types.h:52
void processInbound(const UpstreamPacket &pkt)
CommonLayerStatistics(const StatisticTableLabels &unicastDropTableLabels, const StatisticTableLabels &broadcastDropTableLabels={}, const std::string &sInstance={})