EMANE  1.0.1
shim.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013-2014 - Adjacent Link LLC, Bridgewater, New Jersey
3  * Copyright (c) 2009-2010 - DRS CenGen, LLC, Columbia, Maryland
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * * Redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer.
12  * * Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in
14  * the documentation and/or other materials provided with the
15  * distribution.
16  * * Neither the name of DRS CenGen, LLC nor the names of its
17  * contributors may be used to endorse or promote products derived
18  * from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  *
33  */
34 
35 #include "shim.h"
36 #include "shimheader.h"
37 
39 #include "emane/commonphyheader.h"
40 #include "emane/phytypes.h"
42 #include "emane/startexception.h"
43 
44 
45 namespace
46 {
47  const char * pzLayerName = "CommEffect::Shim";
48 
49  const std::uint32_t TIMED_EVENT_UPSTREAM_PACKET{1};
50 
51  // time event arg
52  struct TimedEventArg {
53  std::uint32_t u32EventType_;
54  void * pData_;
55  EMANE::TimePoint timePoint_;
56  EMANE::Microseconds delay_;
57 
58  TimedEventArg(std::uint32_t type, void * pData, EMANE::TimePoint timePoint, EMANE::Microseconds delay) :
59  u32EventType_{type},
60  pData_{pData},
61  timePoint_{timePoint},
62  delay_{delay}
63  { }
64  };
65 
66 
67  const std::uint16_t DROP_CODE_DISCARD = 1;
68  const std::uint16_t DROP_CODE_GROUP_ID = 2;
69  const std::uint16_t DROP_CODE_REGISTRATION_ID = 3;
70  const std::uint16_t DROP_CODE_DST_MAC = 4;
71  const std::uint16_t DROP_CODE_BAD_MSG = 5;
72  const std::uint16_t DROP_CODE_NO_PROFILE_DATA = 6;
73  const std::uint16_t DROP_CODE_RX_BUFF = 7;
74  const std::uint16_t DROP_CODE_TIMER_ERROR = 8;
75 
76  EMANE::StatisticTableLabels STATISTIC_TABLE_LABELS {"Effect",
77  "Grp Id",
78  "Reg Id",
79  "Dst MAC",
80  "Bad Msg",
81  "No Profile",
82  "Rx Buff",
83  "Timer"};
84 }
85 
87  PlatformServiceProvider * pPlatformService,
88  RadioServiceProvider * pRadioService) :
89  ShimLayerImplementor{id,pPlatformService,pRadioService},
90  profileManager_{id, pPlatformService_},
91  u32UpstreamSequenceNumber_{},
92  u32DownstreamSequenceNumber_{},
93  bDefaultConnectivity_{true},
94  bEnablePromiscousMode_{},
95  bEnableTightTimingMode_{},
96  u32GroupId_{},
97  receiveBufferPeriod_{},
98  RNDZeroToOneHundred_{0.0f, 100.0f},
99  RNG_(std::chrono::system_clock::now().time_since_epoch().count()),
100  commonLayerStatistics_{STATISTIC_TABLE_LABELS,{},"0"}
101 { }
102 
104 { }
105 
106 
108 {
110  DEBUG_LEVEL,
111  "SHIMI %03hu %s::%s",
112  id_,
113  pzLayerName,
114  __func__);
115 
116  auto & configRegistrar = registrar.configurationRegistrar();
117 
118  configRegistrar.registerNumeric<bool>("defaultconnectivitymode",
120  {true},
121  "Defines the default connectivity mode for Comm Effects. When"
122  " set to on, full connectivity will be engaged until a valid"
123  " Comm Effect event is received.");
124 
125  configRegistrar.registerNonNumeric<std::string>("filterfile",
127  {},
128  "Defines the absolute URI of the effects filter XML"
129  " file which contains static filters to control"
130  " network impairments.");
131 
132 
133  configRegistrar.registerNumeric<std::uint32_t>("groupid",
135  {0},
136  "Defines the Comm Effect Group Id. Only NEMs in the"
137  " same Comm Effect Group can communicate.");
138 
139  configRegistrar.registerNumeric<bool>("enablepromiscuousmode",
141  {false},
142  "Defines whether promiscuous mode is enabled or not. If promiscuous"
143  " mode is enabled, all received packets (intended for the given node"
144  " or not) that pass the receive test are sent upstream to the transport.");
145 
146 
147  configRegistrar.registerNumeric<double>("receivebufferperiod",
149  {1.0},
150  "Defines the max buffering time in seconds for packets received from an NEM."
151  " The buffering interval for a given packet is determined by the bitrate"
152  " for the source NEM and the packet size. Packets are then placed in a"
153  " timed queue based on this interval and all packets that would cause the"
154  " receive buffer period to be exceeded are discarded. A value of 0.0"
155  " disables the limit and allows all received packets to stack up in the"
156  " queue.");
157 
158  auto & statisticRegistrar = registrar.statisticRegistrar();
159 
160  commonLayerStatistics_.registerStatistics(statisticRegistrar);
161 
162  auto & eventRegistrar = registrar.eventRegistrar();
163 
165 }
166 
167 
169 {
171  DEBUG_LEVEL,
172  "SHIMI %03hu %s::%s",
173  id_,
174  pzLayerName,
175  __func__);
176 
177  for(const auto & item : update)
178  {
179  if(item.first == "defaultconnectivitymode")
180  {
181  bDefaultConnectivity_ = item.second[0].asBool();
182 
184  INFO_LEVEL,
185  "SHIMI %03hu %s::%s: %s = %d",
186  id_,
187  pzLayerName,
188  __func__,
189  item.first.c_str(),
190  bDefaultConnectivity_);
191  }
192  else if(item.first == "enablepromiscuousmode")
193  {
194  bEnablePromiscousMode_ = item.second[0].asBool();
195 
197  INFO_LEVEL,
198  "SHIMI %03hu %s::%s: %s = %d",
199  id_,
200  pzLayerName,
201  __func__,
202  item.first.c_str(),
203  bEnablePromiscousMode_);
204  }
205  else if(item.first == "groupid")
206  {
207  u32GroupId_ = item.second[0].asUINT32();
208 
210  INFO_LEVEL,
211  "SHIMI %03hu %s::%s: %s = %u",
212  id_,
213  pzLayerName,
214  __func__,
215  item.first.c_str(),
216  u32GroupId_);
217  }
218  else if(item.first == "filterfile")
219  {
220  sFilterFile_ = item.second[0].asString();
221 
222 
224  INFO_LEVEL,
225  "SHIMI %03hu %s::%s: %s = %s",
226  id_,
227  pzLayerName,
228  __func__,
229  item.first.c_str(),
230  sFilterFile_.c_str());
231  }
232  else if(item.first == "receivebufferperiod")
233  {
234  DoubleSeconds receiveBufferPeriodSeconds{item.second[0].asDouble()};
235 
236  receiveBufferPeriod_ =
237  std::chrono::duration_cast<Microseconds>(receiveBufferPeriodSeconds);
238 
240  INFO_LEVEL,
241  "SHIMI %03hu %s::%s: %s = %lf",
242  id_,
243  pzLayerName,
244  __func__,
245  item.first.c_str(),
246  receiveBufferPeriodSeconds.count());
247  }
248  }
249 }
250 
251 
253 {
255  DEBUG_LEVEL,
256  "SHIMI %03hu %s::%s",
257  id_,
258  pzLayerName,
259  __func__);
260 
261  if(!sFilterFile_.empty() && profileManager_.load(sFilterFile_.c_str()) < 0)
262  {
263  throw makeException<StartException>("%s : Could not open filter file %s",
264  pzLayerName,
265  sFilterFile_.c_str());
266  }
267 }
268 
269 
271 {
273  DEBUG_LEVEL,
274  "SHIMI %03hu %s::%s",
275  id_,
276  pzLayerName,
277  __func__);
278 
279  // clear EOR map
280  EORTimeMap_.clear();
281 }
282 
283 
285  throw()
286 {
288  DEBUG_LEVEL,
289  "SHIMI %03hu %s::%s",
290  id_,
291  pzLayerName,
292  __func__);
293 }
294 
295 
297 {
299  DEBUG_LEVEL,
300  "SHIMI %03hu %s::%s, unexpected control message, drop",
301  id_,
302  pzLayerName,
303  __func__);
304 }
305 
306 
308 {
310  DEBUG_LEVEL,
311  "SHIMI %03hu %s::%s, unexpected control message, drop",
312  id_,
313  pzLayerName,
314  __func__);
315 }
316 
317 
319 {
320  TimePoint beginTime{Clock::now()};
321 
322  commonLayerStatistics_.processInbound(pkt);
323 
324  const PacketInfo & pktInfo = pkt.getPacketInfo();
325 
326  CommonPHYHeader commonPHYHeader(pkt);
327 
328  // check phy type
329  if(commonPHYHeader.getRegistrationId() != REGISTERED_EMANE_PHY_COMM_EFFECT)
330  {
332  DEBUG_LEVEL,
333  "SHIMI %03hu %s::%s, ignore phy type %hu != %hu, from %hu to %hu",
334  id_,
335  pzLayerName,
336  __func__,
337  commonPHYHeader.getRegistrationId(),
339  pktInfo.getSource(),
340  pktInfo.getDestination());
341 
342  commonLayerStatistics_.processOutbound(pkt,
343  std::chrono::duration_cast<Microseconds>(Clock::now() - beginTime),
344  DROP_CODE_REGISTRATION_ID);
345 
346  // drop
347  return;
348  }
349 
350  std::uint32_t u32GroupId{};
351 
352  TimePoint txTime{};
353 
354  auto len = pkt.stripLengthPrefixFraming();
355 
356  if(len && pkt.length() >= len)
357  {
358  ShimHeader header(pkt.get(),len);
359 
360  u32GroupId = header.getGroupId();
361 
362  txTime = header.getTxTimePoint();
363 
364  pkt.strip(len);
365  }
366  else
367  {
368  commonLayerStatistics_.processOutbound(pkt,
369  std::chrono::duration_cast<Microseconds>(Clock::now() - beginTime),
370  DROP_CODE_BAD_MSG);
371  //drop
372  return;
373  }
374 
375  // check promiscous mode
376  if(!bEnablePromiscousMode_)
377  {
378  // drop if not broadcast or for this NEM
379  if((pktInfo.getDestination() != NEM_BROADCAST_MAC_ADDRESS) && (id_ != pktInfo.getDestination()))
380  {
382  DEBUG_LEVEL,
383  "SHIMI %03hu %s::%s, ignore transmission from %hu to %hu",
384  id_,
385  pzLayerName,
386  __func__,
387  pktInfo.getSource(),
388  pktInfo.getDestination());
389 
390  commonLayerStatistics_.processOutbound(pkt,
391  std::chrono::duration_cast<Microseconds>(Clock::now() - beginTime),
392  DROP_CODE_DST_MAC);
393 
394  // drop
395  return;
396  }
397  }
398 
399  // check group id
400  if(u32GroupId != u32GroupId_)
401  {
403  DEBUG_LEVEL,
404  "SHIMI %03hu %s::%s, group id mismatch src %hu, src grp %u != our grp %u",
405  id_,
406  pzLayerName,
407  __func__,
408  pktInfo.getSource(),
409  u32GroupId,
410  u32GroupId_);
411 
412  commonLayerStatistics_.processOutbound(pkt,
413  std::chrono::duration_cast<Microseconds>(Clock::now() - beginTime),
414  DROP_CODE_GROUP_ID);
415 
416  // drop
417  return;
418  }
419 
420  // lookup pkt profile data, will check filters first then event data for the source NEM
421  auto ret = profileManager_.getProfileData(pkt.get(), pkt.length(), pktInfo.getSource());
422 
423  // check result
424  if(!ret.second)
425  {
426  // no info found, check default connectivity mode
427  if(bDefaultConnectivity_)
428  {
430  DEBUG_LEVEL,
431  "SHIMI %03hu %s::%s, default connectivity mode, src %hu",
432  id_,
433  pzLayerName,
434  __func__,
435  pktInfo.getSource());
436 
437  commonLayerStatistics_.processOutbound(pkt,
438  std::chrono::duration_cast<Microseconds>(Clock::now() - beginTime));
439 
440  // send pkt upstream, no effects
441  sendUpstreamPacket(pkt);
442 
443  // done
444  return;
445  }
446  else
447  {
449  DEBUG_LEVEL,
450  "SHIMI %03hu %s::%s, drop, no profile data for src %hu, "
451  "default connectivity is off",
452  id_,
453  pzLayerName,
454  __func__,
455  pktInfo.getSource());
456 
457  commonLayerStatistics_.processOutbound(pkt,
458  std::chrono::duration_cast<Microseconds>(Clock::now() - beginTime),
459  DROP_CODE_NO_PROFILE_DATA);
460 
461  // drop
462  return;
463  }
464  }
465  else
466  {
467  // get bitrate based on pkt destination unicast or broadcast
468  std::uint64_t u64BitRate{pktInfo.getDestination() == NEM_BROADCAST_MAC_ADDRESS ?
469  ret.first.getBroadcastBitRate() :
470  ret.first.getUnicastBitRate()};
471 
472 
473  // reception interval
474  Microseconds rxIntervalMicroseconds{
475  std::chrono::duration_cast<Microseconds>(DoubleSeconds{u64BitRate == 0 ?
476  0.0 : (pkt.length() * 8) / static_cast<double>(u64BitRate)})};
477 
478  // get previous EOR time for this src NEM
479  auto optionalEORTime = getEORTime(pktInfo.getSource());
480 
481  // check backlog if receiver buffer period is set and we have history for this src NEM
482  if(receiveBufferPeriod_ != Microseconds::zero() && optionalEORTime.second)
483  {
484  // check if there is any time remaining in the recieve window period
485  if((optionalEORTime.first - beginTime) > receiveBufferPeriod_)
486  {
488  DEBUG_LEVEL,
489  "SHIMI %03hu %s::%s, drop src %hu, receive buffer period exceeded %lf",
490  id_,
491  pzLayerName,
492  __func__,
493  pktInfo.getSource(),
494  std::chrono::duration_cast<DoubleSeconds>(receiveBufferPeriod_).count());
495 
496 
497  commonLayerStatistics_.processOutbound(pkt,
498  std::chrono::duration_cast<Microseconds>(Clock::now() - beginTime),
499  DROP_CODE_RX_BUFF);
500 
501  // drop
502  return;
503  }
504  }
505 
506  if(optionalEORTime.first > beginTime)
507  {
508  // add rx interval to end of the previous EOR time
509  optionalEORTime.first += rxIntervalMicroseconds;
510  }
511  else
512  {
513  // set EOR time to current time plus rx interval
514  optionalEORTime.first = beginTime + rxIntervalMicroseconds;
515  }
516 
517  // update the EOR for this NEM
518  setEORTime(pktInfo.getSource(),optionalEORTime.first);
519 
521  DEBUG_LEVEL,
522  "SHIMI %03hu %s::%s, src %hu, dst %hu, len %zd, latency %lf,"
523  " jitter %lf, loss %f, dups %f, bitrate %ju, rxtime %lf",
524  id_, pzLayerName, __func__,
525  pktInfo.getSource(),
526  pktInfo.getDestination(),
527  pkt.length(),
528  std::chrono::duration_cast<DoubleSeconds>(ret.first.getLatency()).count(),
529  std::chrono::duration_cast<DoubleSeconds>(ret.first.getJitter()).count(),
530  ret.first.getProbabilityLoss(),
531  ret.first.getProbabilityDuplicate(),
532  u64BitRate,
533  std::chrono::duration_cast<DoubleSeconds>(rxIntervalMicroseconds).count());
534 
535 
536  // get number of task(s) to create for loss and dups result is 0 or more tasks, each represent an rx frame
537  const size_t taskCount = getTaskCount(ret.first.getProbabilityLoss(),
538  ret.first.getProbabilityDuplicate());
539 
540  if(!taskCount)
541  {
542  commonLayerStatistics_.processOutbound(pkt,
543  std::chrono::duration_cast<Microseconds>(Clock::now() - beginTime),
544  DROP_CODE_DISCARD);
545  }
546 
547  // create tasks
548  for(size_t n = 0; n < taskCount; ++n)
549  {
550  // set absolute timeout delay = latency + jitter + EOR time
551  TimePoint tpTimeout{ret.first.getLatency() + randomize(ret.first.getJitter()) + optionalEORTime.first};
552 
553  // if tight timing mode enabled subtract out the ota processing time of the packet (now - tx time)
554  if(bEnableTightTimingMode_)
555  {
556  tpTimeout -= beginTime - txTime;
557  }
558 
559  UpstreamPacket * pPacket{new UpstreamPacket(pkt)};
560 
561  TimedEventArg * pTimedEventArg{new TimedEventArg{TIMED_EVENT_UPSTREAM_PACKET,
562  pPacket,
563  beginTime,
564  std::chrono::duration_cast<Microseconds>(tpTimeout - Clock::now())}};
565 
566  // schedule the time event, id, pkt, timeout
567  pPlatformService_->timerService().scheduleTimedEvent(tpTimeout, pTimedEventArg);
568 
569 
571  DEBUG_LEVEL,
572  "SHIMI %03hu %s::%s, enqueue task %zu, seq %u, delay %lf",
573  id_,
574  pzLayerName,
575  __func__,
576  n,
577  u32UpstreamSequenceNumber_,
578  std::chrono::duration_cast<DoubleSeconds>(tpTimeout - Clock::now()).count());
579 
580  }
581  }
582 }
583 
584 
586  const ControlMessages &)
587 {
588  TimePoint beginTime{Clock::now()};
589 
590  commonLayerStatistics_.processInbound(pkt);
591 
593  DEBUG_LEVEL,
594  "SHIMI %03hu %s::%s, src %hu, dst %hu, seq %u",
595  id_,
596  pzLayerName,
597  __func__,
598  pkt.getPacketInfo().getSource(),
600  u32DownstreamSequenceNumber_);
601 
602  // create shim header with current time, group id, sequence number
603  ShimHeader shimHeader{Clock::now(), u32GroupId_, u32DownstreamSequenceNumber_};
604 
605  Serialization serialization{shimHeader.serialize()};
606 
607  // prepend shim header
608  pkt.prepend(serialization.c_str(),serialization.size());
609 
610  pkt.prependLengthPrefixFraming(serialization.size());
611 
613  static_cast<std::uint16_t>(u32DownstreamSequenceNumber_),
614  0,
615  0,
616  Clock::now(),
618  Transmitters{{id_,0}},
619  {0,false}};
620 
621  // prepend phy header to outgoing packet
622  commonPHYHeader.prependTo(pkt);
623 
624  commonLayerStatistics_.processOutbound(pkt,
625  std::chrono::duration_cast<Microseconds>(Clock::now() - beginTime));
626 
627  // send packet
629 
630  // bump tx seq number
631  ++u32DownstreamSequenceNumber_;
632 }
633 
634 
635 
637  const Serialization & serialization)
638 {
640  {
641  Events::CommEffectEvent event(serialization);
642 
644  DEBUG_LEVEL,
645  "SHIMI %03hu %s::%s,event id %03hu",
646  id_,
647  pzLayerName,
648  __func__,
649  eventId);
650 
651  // load profile data entries
652  profileManager_.load(event.getCommEffects());
653 
654  // connectivity information receieved - no longer in default mode
655  bDefaultConnectivity_ = false;
656  }
657 }
658 
659 
660 
662  const TimePoint & expireTime,
663  const TimePoint &,
664  const TimePoint &,
665  const void * arg)
666 
667 {
668  Microseconds latencyMicroseconds{std::chrono::duration_cast<Microseconds>(Clock::now() - expireTime)};
669 
670  const TimedEventArg * pTimedEventArg {reinterpret_cast<const TimedEventArg *>(arg)};
671 
672 #ifdef VERY_VERBOSE_LOGGING
674  DEBUG_LEVEL,
675  "SHIMI %03hu %s::%s: eventId %ld, latency %lf",
676  id_,
677  pzLayerName,
678  __func__,
679  eventId,
680  std::chrono::duration_cast<DoubleSeconds>(latencyMicroseconds).count());
681 #endif
682 
683  if(pTimedEventArg->u32EventType_ == TIMED_EVENT_UPSTREAM_PACKET)
684  {
685  // pkt ptr passed in as arg
686  UpstreamPacket *pPacket{reinterpret_cast<UpstreamPacket*>(pTimedEventArg->pData_)};
687 
688  // processing delay is when we rx the pkt to now, minus the intended delay and latency
689  commonLayerStatistics_.processOutbound(
690  *pPacket, std::chrono::duration_cast<Microseconds>(
691  Clock::now() - pTimedEventArg->timePoint_) - pTimedEventArg->delay_ - latencyMicroseconds);
692 
693  sendUpstreamPacket(*pPacket);
694 
696  DEBUG_LEVEL,
697  "SHIMI %03hu %s::%s, latency %lf",
698  id_,
699  pzLayerName,
700  __func__,
701  std::chrono::duration_cast<DoubleSeconds>(latencyMicroseconds).count());
702 
703  // delete pkt
704  delete pPacket;
705 
706  // delete the arg
707  delete pTimedEventArg;
708  }
709 }
710 
711 
712 size_t EMANE::Models::CommEffect::Shim::getTaskCount(float fLoss, float fDups)
713 {
714  size_t count = 0;
715 
716  if(fLoss < 100)
717  {
718  if(fLoss > 0)
719  {
720  // if loss is less then random value
721  if((RNDZeroToOneHundred_()) >= fLoss)
722  {
723  // add to count
724  ++count;
725  }
726  }
727  else
728  {
729  // no loss, add to count
730  ++count;
731  }
732  }
733 
734 
735  // you can only duplicate a packet you receive
736  if(count)
737  {
738  // calculate probability of duplicate
739  // and add to the current count if any
740  if(fDups >= 100.0f)
741  {
742  // add to count
743  count += fDups / 100.0f;
744 
745  // reduce
746  fDups = fmodf(fDups,100.0f);
747  }
748 
749  if((fDups > 0.0f) && (fDups < 100.0f))
750  {
751  // if dups is greater/equal then random value
752  if((RNDZeroToOneHundred_()) <= fDups)
753  {
754  // add to count
755  ++count;
756  }
757  }
758  }
759 
760  return count;
761 }
762 
763 /* each commeffect entry may have its own jitter value so apply the range here */
765 EMANE::Models::CommEffect::Shim::randomize(const Microseconds & duration)
766 {
767  Microseconds randomized{};
768 
769  if(duration != Microseconds::zero())
770  {
771  // scale up and roll the dice
772  randomized = Microseconds{RNG_() % (2 * duration.count())};
773 
774  // scale back
775  randomized -= duration;
776  }
777 
778  return randomized;
779 }
780 
781 
782 std::pair<EMANE::TimePoint,bool> EMANE::Models::CommEffect::Shim::getEORTime(NEMId src)
783 {
784  // search for EOR time data based on NEM src id
785  auto iter = EORTimeMap_.find(src);
786 
787  if(iter != EORTimeMap_.end())
788  {
789  // return EOR time
790  return std::make_pair(iter->second,true);
791  }
792 
793  // no history
794  return std::make_pair(EMANE::TimePoint{},false);
795 }
796 
797 
798 
799 void EMANE::Models::CommEffect::Shim::setEORTime(NEMId src, const TimePoint & timePoint)
800 {
801  // search for EOR time data based on NEM src id
802  auto iter = EORTimeMap_.find(src);
803 
804  if(iter != EORTimeMap_.end())
805  {
806  // update EOR time
807  iter->second = timePoint;
808  }
809  else
810  {
811  // add new entry
812  EORTimeMap_.insert(std::make_pair(src,timePoint));
813  }
814 }
815 
std::string Serialization
Definition: serializable.h:42
A Packet class that allows upstream processing to strip layer headers as the packet travels up the st...
const PacketInfo & getPacketInfo() const
void processUpstreamControl(const ControlMessages &msgs) override
Definition: shim.cc:296
The Registrar interface provides access to all of the emulator registrars.
Definition: registrar.h:50
void start() override
Definition: shim.cc:252
EMANE::NetworkAdapterException __attribute__
DECLARE_SHIM_LAYER(EMANE::Models::CommEffect::Shim)
virtual ConfigurationRegistrar & configurationRegistrar()=0
virtual TimerEventId scheduleTimedEvent(const TimePoint &timePoint, const void *arg=nullptr, const Duration &interval=Duration::zero())=0
#define LOGGER_VERBOSE_LOGGING(logger, level, fmt, args...)
void destroy() override
Definition: shim.cc:284
virtual StatisticRegistrar & statisticRegistrar()=0
void processOutbound(const UpstreamPacket &pkt, Microseconds delay, size_t dropCode={})
std::pair< Events::CommEffect, bool > getProfileData(const void *buf, size_t len, NEMId id) const
Shim(NEMId id, PlatformServiceProvider *pPlatformService, RadioServiceProvider *pRadioService)
Definition: shim.cc:86
std::list< const ControlMessage * > ControlMessages
void processDownstreamControl(const ControlMessages &msgs) override
Definition: shim.cc:307
NEMId getSource() const
Definition: packetinfo.inl:64
NEMId getDestination() const
Definition: packetinfo.inl:70
std::uint16_t stripLengthPrefixFraming()
constexpr NEMId NEM_BROADCAST_MAC_ADDRESS
Definition: types.h:69
size_t strip(size_t size)
void prepend(const void *buf, size_t size)
void stop() override
Definition: shim.cc:270
std::uint16_t EventId
Definition: types.h:53
The PlatformServiceProvider interface provides access to emulator services.
virtual EventRegistrar & eventRegistrar()=0
void registerStatistics(StatisticRegistrar &statisticRegistrar)
Store source, destination, creation time and priority information for a packet.
Definition: packetinfo.h:50
Interface used to create a Shim layer plugin implementation.
Definition: shimlayerimpl.h:47
The common physical layer header used to facilitate heterogeneous radio model experimentation.
std::vector< std::string > StatisticTableLabels
const PacketInfo & getPacketInfo() const
void processEvent(const EventId &, const Serialization &) override
Definition: shim.cc:636
void processDownstreamPacket(DownstreamPacket &pkt, const ControlMessages &msgs) override
Definition: shim.cc:585
Specialized packet the allows downstream processing to add layer specific headers as the packet trave...
Comm Effect events are used to set asynchronous link characteristics from one or more transmitting NE...
const RegistrationId REGISTERED_EMANE_PHY_COMM_EFFECT
Definition: phytypes.h:77
std::chrono::microseconds Microseconds
Definition: types.h:45
std::chrono::duration< double > DoubleSeconds
Definition: types.h:47
std::uint16_t NEMId
Definition: types.h:52
PlatformServiceProvider * pPlatformService_
The RadioServiceProvider interface provides access to radio (RF) model specific services.
std::uint32_t getGroupId() const
Definition: shimheader.inl:40
const void * get() const
virtual LogServiceProvider & logService()=0
std::list< FrequencySegment > FrequencySegments
void initialize(Registrar &registrar) override
Definition: shim.cc:107
const CommEffects & getCommEffects() const
std::vector< ConfigurationNameAnyValues > ConfigurationUpdate
void processTimedEvent(TimerEventId eventId, const TimePoint &expireTime, const TimePoint &scheduleTime, const TimePoint &fireTime, const void *arg) override
Definition: shim.cc:661
virtual void registerEvent(EventId eventId)=0
union EtherAddr src
Definition: netutils.h:391
std::size_t TimerEventId
Definition: types.h:54
void registerNumeric(const std::string &sName, const ConfigurationProperties &properties=ConfigurationProperties::NONE, const std::initializer_list< T > &values={}, const std::string &sUsage="", T minValue=std::numeric_limits< T >::lowest(), T maxValue=std::numeric_limits< T >::max(), std::size_t minOccurs=1, std::size_t maxOccurs=1, const std::string &sRegexPattern={})
Clock::time_point TimePoint
Definition: types.h:50
std::list< Transmitter > Transmitters
Definition: transmitter.h:85
void sendUpstreamPacket(UpstreamPacket &pkt, const ControlMessages &msgs=empty)
void prependLengthPrefixFraming(std::uint16_t u16Length)
#define LOGGER_STANDARD_LOGGING(logger, level, fmt, args...)
void sendDownstreamPacket(DownstreamPacket &pkt, const ControlMessages &msgs=empty)
void configure(const ConfigurationUpdate &update) override
Definition: shim.cc:168
void processUpstreamPacket(UpstreamPacket &pkt, const ControlMessages &msgs) override
Definition: shim.cc:318
void processInbound(const UpstreamPacket &pkt)
RegistrationId getRegistrationId() const
virtual TimerServiceProvider & timerService()=0