EMANE  1.2.1
frameworkphy.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013-2014,2016-2017 - Adjacent Link LLC, Bridgewater,
3  * New Jersey
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 Adjacent Link 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 #include "frameworkphy.h"
35 
36 #include "emane/commonphyheader.h"
39 
41 
50 
58 
62 
66 
67 namespace
68 {
69  const std::uint16_t DROP_CODE_OUT_OF_BAND = 1;
70  const std::uint16_t DROP_CODE_RX_SENSITIVITY = 2;
71  const std::uint16_t DROP_CODE_PROPAGATIONMODEL = 3;
72  const std::uint16_t DROP_CODE_GAINMANAGER_LOCATION = 4;
73  const std::uint16_t DROP_CODE_GAINMANAGER_HORIZON = 5;
74  const std::uint16_t DROP_CODE_GAINMANAGER_ANTENNAPROFILE = 6;
75  const std::uint16_t DROP_CODE_NOT_FOI = 7;
76  const std::uint16_t DROP_CODE_SPECTRUM_CLAMP = 8;
77  const std::uint16_t DROP_CODE_FADINGMANAGER_LOCATION = 9;
78  const std::uint16_t DROP_CODE_FADINGMANAGER_ALGORITHM = 10;
79  const std::uint16_t DROP_CODE_FADINGMANAGER_SELECTION = 11;
80 
81  EMANE::StatisticTableLabels STATISTIC_TABLE_LABELS{"Out-of-Band",
82  "Rx Sensitivity",
83  "Propagation Model",
84  "Gain Location",
85  "Gain Horizon",
86  "Gain Profile",
87  "Not FOI",
88  "Spectrum Clamp",
89  "Fade Location",
90  "Fade Algorithm",
91  "Fade Select"};
92 
93  const std::string FADINGMANAGER_PREFIX{"fading."};
94 }
95 
97  PlatformServiceProvider * pPlatformService,
98  SpectrumMonitor * pSpectrumMonitor):
99  PHYLayerImplementor{id, pPlatformService},
100  pSpectrumMonitor_{pSpectrumMonitor},
101  gainManager_{id},
102  locationManager_{id},
103  u64BandwidthHz_{},
104  dTxPowerdBm_{},
105  u64TxFrequencyHz_{},
106  dReceiverSensitivitydBm_{},
107  noiseMode_{},
108  u16SubId_{},
109  u16TxSequenceNumber_{},
110  commonLayerStatistics_{STATISTIC_TABLE_LABELS,{},"0"},
111  eventTablePublisher_{id},
112  noiseBinSize_{},
113  maxSegmentOffset_{},
114  maxMessagePropagation_{},
115  maxSegmentDuration_{},
116  timeSyncThreshold_{},
117  bNoiseMaxClamp_{},
118  dSystemNoiseFiguredB_{},
119  fadingManager_{id, pPlatformService,FADINGMANAGER_PREFIX}{}
120 
122 
124 {
125  auto & configRegistrar = registrar.configurationRegistrar();
126 
127  configRegistrar.registerNumeric<double>("fixedantennagain",
130  {0},
131  "Defines the antenna gain in dBi and is valid only when"
132  " fixedantennagainenable is enabled.");
133 
134  configRegistrar.registerNumeric<bool>("fixedantennagainenable",
136  {true},
137  "Defines whether fixed antenna gain is used or whether"
138  " antenna profiles are in use.");
139 
140  configRegistrar.registerNumeric<std::uint64_t>("bandwidth",
142  {1000000},
143  "Defines receiver bandwidth in Hz and also serves as the"
144  " default bandwidth for OTA transmissions when not provided"
145  " by the MAC.",
146  1);
147 
148  configRegistrar.registerNumeric<std::uint64_t>("frequency",
150  {2347000000},
151  "Defines the default transmit center frequency in Hz when not"
152  " provided by the MAC. This value is included in the Common PHY"
153  " Header of all transmitted OTA packets.",
154  1);
155 
156  configRegistrar.registerNumeric<std::uint64_t>("frequencyofinterest",
158  {2347000000},
159  "Defines a set of center frequencies in Hz that are monitored"
160  " for reception as either in-band or out-of-band.",
161  std::numeric_limits<std::uint64_t>::min(),
162  std::numeric_limits<std::uint64_t>::max(),
163  1,
164  std::numeric_limits<std::size_t>::max());
165 
166  configRegistrar.registerNonNumeric<std::string>("noisemode",
168  {"all"},
169  "Defines the noise processing mode of operation:"
170  " none, all or outofband.",
171  1,
172  1,
173  "^(none|all|outofband)$");
174 
175 
176  configRegistrar.registerNumeric<std::uint64_t>("noisebinsize",
178  {20},
179  "Defines the noise bin size in microseconds and translates"
180  " into timing accuracy associated with aligning the start and"
181  " end of reception times of multiple packets for modeling of"
182  " interference effects.",
183  1);
184 
185  configRegistrar.registerNumeric<bool>("noisemaxclampenable",
187  {false},
188  "Defines whether segment offset, segment duration and message"
189  " propagation associated with a received packet will be clamped"
190  " to their respective maximums defined by noisemaxsegmentoffset,"
191  " noisemaxsegmentduration and noisemaxmessagepropagation. When"
192  " disabled, any packet with an above max value will be dropped.");
193 
194 
195  configRegistrar.registerNumeric<std::uint64_t>("noisemaxsegmentoffset",
197  {300000},
198  "Noise maximum segment offset in microseconds.",
199  1);
200 
201  configRegistrar.registerNumeric<std::uint64_t>("noisemaxmessagepropagation",
203  {200000},
204  "Noise maximum message propagation in microseconds.",
205  1);
206 
207  configRegistrar.registerNumeric<std::uint64_t>("noisemaxsegmentduration",
209  {1000000},
210  "Noise maximum segment duration in microseconds.",
211  1);
212 
213  configRegistrar.registerNumeric<std::uint64_t>("timesyncthreshold",
215  {10000},
216  "Defines the time sync detection threshold in microseconds."
217  " If a received OTA message is more than this threshold, the"
218  " message reception time will be used as the source transmission"
219  " time instead of the time contained in the Common PHY Header."
220  " This allows the emulator to be used across distributed nodes"
221  " without time sync.",
222  1);
223 
224  configRegistrar.registerNonNumeric<std::string>("propagationmodel",
226  {"precomputed"},
227  "Defines the pathloss mode of operation:"
228  " precomputed, 2ray or freespace.",
229  1,
230  1,
231  "^(precomputed|2ray|freespace)$");
232 
233  configRegistrar.registerNumeric<double>("systemnoisefigure",
235  {4.0},
236  "Defines the system noise figure in dB and is used to determine the"
237  " receiver sensitivity.");
238 
239  configRegistrar.registerNumeric<std::uint16_t>("subid",
241  {},
242  "Defines the emulator PHY subid used by multiple NEM"
243  " definitions. Once instantiated, these NEMs may be using the"
244  " same frequency. In order to differentiate between emulator"
245  " PHY instances for different waveforms, the subid is used as"
246  " part of the unique waveform identifying tuple: PHY Layer"
247  " Registration Id, emulator PHY subid and packet center"
248  " frequency.",
249  1);
250 
251  configRegistrar.registerNumeric<double>("txpower",
252  EMANE::ConfigurationProperties::DEFAULT |
254  {0.0},
255  "Defines the transmit power in dBm.");
257  auto & eventRegistrar = registrar.eventRegistrar();
258 
260 
261  eventRegistrar.registerEvent(Events::LocationEvent::IDENTIFIER);
262 
263  eventRegistrar.registerEvent(Events::AntennaProfileEvent::IDENTIFIER);
264 
265  eventRegistrar.registerEvent(Events::FadingSelectionEvent::IDENTIFIER);
266 
269  auto & statisticRegistrar = registrar.statisticRegistrar();
270 
271  commonLayerStatistics_.registerStatistics(statisticRegistrar);
272 
273  eventTablePublisher_.registerStatistics(statisticRegistrar);
274 
275  receivePowerTablePublisher_.registerStatistics(statisticRegistrar);
276 
277  pTimeSyncThresholdRewrite_ =
278  statisticRegistrar.registerNumeric<std::uint64_t>("numTimeSyncThresholdRewrite",
280 
281  fadingManager_.initialize(registrar);
282 }
283 
285 {
286  FrequencySet foi{};
287  ConfigurationUpdate fadingManagerConfiguration{};
288 
289  for(const auto & item : update)
290  {
291  if(item.first == "bandwidth")
292  {
293  u64BandwidthHz_ = item.second[0].asUINT64();
294 
296  INFO_LEVEL,
297  "PHYI %03hu FrameworkPHY::%s: %s = %ju Hz",
298  id_,
299  __func__,
300  item.first.c_str(),
301  u64BandwidthHz_);
302  }
303  else if(item.first == "fixedantennagain")
304  {
305  optionalFixedAntennaGaindBi_.first = item.second[0].asDouble();
306 
308  INFO_LEVEL,
309  "PHYI %03hu FrameworkPHY::%s: %s = %3.2f dBi",
310  id_,
311  __func__,
312  item.first.c_str(),
313  optionalFixedAntennaGaindBi_.first);
314 
315  }
316  else if(item.first == "fixedantennagainenable")
317  {
318  optionalFixedAntennaGaindBi_.second = item.second[0].asBool();
319 
321  INFO_LEVEL,
322  "PHYI %03hu FrameworkPHY::%s: %s = %s",
323  id_,
324  __func__,
325  item.first.c_str(),
326  optionalFixedAntennaGaindBi_.second ? "on" : "off");
327  }
328  else if(item.first == "propagationmodel")
329  {
330  std::string sPropagationModel{item.second[0].asString()};
331 
332  // regex has already validated values
333  if(sPropagationModel == "precomputed")
334  {
335  pPropagationModelAlgorithm_.reset(new PrecomputedPropagationModelAlgorithm{id_});
336  }
337  else if(sPropagationModel == "2ray")
338  {
339  pPropagationModelAlgorithm_.reset(new TwoRayPropagationModelAlgorithm{id_});
340  }
341  else
342  {
343  pPropagationModelAlgorithm_.reset(new FreeSpacePropagationModelAlgorithm{id_});
344  }
345 
347  INFO_LEVEL,
348  "PHYI %03hu FrameworkPHY::%s: %s = %s",
349  id_,
350  __func__,
351  item.first.c_str(),
352  sPropagationModel.c_str());
353  }
354  else if(item.first == "noisemode")
355  {
356  std::string sNoiseMode{item.second[0].asString()};
357 
358  // regex has already validated values
359  if(sNoiseMode == "all")
360  {
361  noiseMode_ = SpectrumMonitor::NoiseMode::ALL;
362  }
363  else if(sNoiseMode == "none")
364  {
366  }
367  else
368  {
370  }
371 
373  INFO_LEVEL,
374  "PHYI %03hu FrameworkPHY::%s: %s = %s",
375  id_,
376  __func__,
377  item.first.c_str(),
378  sNoiseMode.c_str());
379  }
380  else if(item.first == "noisebinsize")
381  {
382  noiseBinSize_ = Microseconds{item.second[0].asUINT64()};
383 
385  INFO_LEVEL,
386  "PHYI %03hu FrameworkPHY::%s: %s = %ju usec",
387  id_,
388  __func__,
389  item.first.c_str(),
390  noiseBinSize_.count());
391  }
392  else if(item.first == "noisemaxclampenable")
393  {
394  bNoiseMaxClamp_ = item.second[0].asBool();
395 
397  INFO_LEVEL,
398  "PHYI %03hu FrameworkPHY::%s: %s = %s",
399  id_,
400  __func__,
401  item.first.c_str(),
402  bNoiseMaxClamp_ ? "on" : "off");
403  }
404  else if(item.first == "noisemaxsegmentoffset")
405  {
406  maxSegmentOffset_ = Microseconds{item.second[0].asUINT64()};
407 
409  INFO_LEVEL,
410  "PHYI %03hu FrameworkPHY::%s: %s = %ju usec",
411  id_,
412  __func__,
413  item.first.c_str(),
414  maxSegmentOffset_.count());
415  }
416  else if(item.first == "noisemaxmessagepropagation")
417  {
418  maxMessagePropagation_ = Microseconds{item.second[0].asUINT64()};
419 
421  INFO_LEVEL,
422  "PHYI %03hu FrameworkPHY::%s: %s = %ju usec",
423  id_,
424  __func__,
425  item.first.c_str(),
426  maxMessagePropagation_.count());
427  }
428  else if(item.first == "noisemaxsegmentduration")
429  {
430  maxSegmentDuration_ = Microseconds{item.second[0].asUINT64()};
431 
433  INFO_LEVEL,
434  "PHYI %03hu FrameworkPHY::%s: %s = %ju usec",
435  id_,
436  __func__,
437  item.first.c_str(),
438  maxSegmentDuration_.count());
439  }
440  else if(item.first == "timesyncthreshold")
441  {
442  timeSyncThreshold_ = Microseconds{item.second[0].asUINT64()};
443 
445  INFO_LEVEL,
446  "PHYI %03hu FrameworkPHY::%s: %s = %ju usec",
447  id_,
448  __func__,
449  item.first.c_str(),
450  timeSyncThreshold_.count());
451  }
452  else if(item.first == "systemnoisefigure")
453  {
454  dSystemNoiseFiguredB_ = item.second[0].asDouble();
455 
457  INFO_LEVEL,
458  "PHYI %03hu FrameworkPHY::%s: %s = %3.2f dB",
459  id_,
460  __func__,
461  item.first.c_str(),
462  dSystemNoiseFiguredB_);
463  }
465  else if(item.first == "frequencyofinterest")
466  {
467  for(const auto & any : item.second)
468  {
469  std::uint64_t u64Value{any.asUINT64()};
470 
471  // try to add value to foi set
472  if(foi.insert(u64Value).second)
473  {
475  INFO_LEVEL,
476  "PHYI %03hu FrameworkPHY::%s: %s = %ju Hz",
477  id_,
478  __func__,
479  item.first.c_str(),
480  u64Value);
481  }
482  else
483  {
484  throw makeException<ConfigureException>("FrameworkPHY duplicate frequency of interest found: %ju",
485  u64Value);
486 
487  }
488  }
489  }
492  else if(item.first == "txpower")
493  {
494  dTxPowerdBm_ = item.second[0].asDouble();
495 
497  INFO_LEVEL,
498  "PHYI %03hu FrameworkPHY::%s: %s = %3.2f dBm",
499  id_,
500  __func__,
501  item.first.c_str(),
502  dTxPowerdBm_);
503  }
505  else if(item.first == "frequency")
506  {
507  u64TxFrequencyHz_ = item.second[0].asUINT64();
508 
510  INFO_LEVEL,
511  "PHYI %03hu FrameworkPHY::%s: %s = %ju Hz",
512  id_,
513  __func__,
514  item.first.c_str(),
515  u64TxFrequencyHz_);
516  }
517  else if(item.first == "subid")
518  {
519  u16SubId_ = item.second[0].asUINT16();
520 
522  INFO_LEVEL,
523  "PHYI %03hu FrameworkPHY::%s: %s = %hu",
524  id_,
525  __func__,
526  item.first.c_str(),
527  u16SubId_);
528  }
529  else
530  {
531  if(!item.first.compare(0,FADINGMANAGER_PREFIX.size(),FADINGMANAGER_PREFIX))
532  {
533  fadingManagerConfiguration.push_back(item);
534  }
535  else
536  {
537  throw makeException<ConfigureException>("FrameworkPHY: Unexpected configuration item %s",
538  item.first.c_str());
539  }
540  }
541  }
542 
543  fadingManager_.configure(fadingManagerConfiguration);
544 
545  dReceiverSensitivitydBm_ = THERMAL_NOISE_DB + dSystemNoiseFiguredB_ + 10.0 * log10(u64BandwidthHz_);
546 
547  if((maxSegmentOffset_ + maxMessagePropagation_ + 2 * maxSegmentDuration_) % noiseBinSize_ !=
548  Microseconds::zero())
549  {
550  throw makeException<ConfigureException>("noisemaxsegmentoffset + noisemaxmessagepropagation"
551  " + 2 * noisemaxsegmentduration not evenly divisible by the"
552  " noisebinsize");
553  }
554 
555  pSpectrumMonitor_->initialize(foi,
556  u64BandwidthHz_,
557  Utils::DB_TO_MILLIWATT(dReceiverSensitivitydBm_),
558  noiseMode_,
559  noiseBinSize_,
560  maxSegmentOffset_,
561  maxMessagePropagation_,
562  maxSegmentDuration_,
563  timeSyncThreshold_,
564  bNoiseMaxClamp_);
565 }
566 
568 {
570  DEBUG_LEVEL,
571  "PHYI %03hu FrameworkPHY::%s",
572  id_,
573  __func__);
574 }
575 
577 {
579  DEBUG_LEVEL,
580  "PHYI %03hu FrameworkPHY::%s",
581  id_,
582  __func__);
583 }
584 
586 {
588  DEBUG_LEVEL,
589  "PHYI %03hu FrameworkPHY::%s",
590  id_,
591  __func__);
592 
593 }
594 
596 {
597  ConfigurationUpdate fadingManagerConfiguration{};
598 
599  for(const auto & item : update)
600  {
601  if(item.first == "fixedantennagain")
602  {
603  optionalFixedAntennaGaindBi_.first = item.second[0].asDouble();
604 
606  INFO_LEVEL,
607  "PHYI %03hu FrameworkPHY::%s: %s = %3.2f dBi",
608  id_,
609  __func__,
610  item.first.c_str(),
611  optionalFixedAntennaGaindBi_.first);
612 
613  }
614  else if(item.first == "txpower")
615  {
616  dTxPowerdBm_ = item.second[0].asDouble();
617 
619  INFO_LEVEL,
620  "PHYI %03hu FrameworkPHY::%s: %s = %3.2f dBm",
621  id_,
622  __func__,
623  item.first.c_str(),
624  dTxPowerdBm_);
625  }
626  else
627  {
628  if(!item.first.compare(0,FADINGMANAGER_PREFIX.size(),FADINGMANAGER_PREFIX))
629  {
630  fadingManagerConfiguration.push_back(item);
631  }
632  }
633  }
634 
635  fadingManager_.modify(fadingManagerConfiguration);
636 }
637 
639 {
641  DEBUG_LEVEL,
642  "PHYI %03hu FrameworkPHY::%s",
643  id_,
644  __func__);
645 
646  for(const auto & pMessage : msgs)
647  {
648  switch(pMessage->getId())
649  {
651  {
652  const auto pAntennaProfileControlMessage =
653  reinterpret_cast<const Controls::AntennaProfileControlMessage *>(pMessage);
654 
656  Events::AntennaProfiles profiles{{id_,
657  pAntennaProfileControlMessage->getAntennaProfileId(),
658  pAntennaProfileControlMessage->getAntennaAzimuthDegrees(),
659  pAntennaProfileControlMessage->getAntennaElevationDegrees()}};
660 
661  gainManager_.update(profiles);
662 
665  }
666  break;
667 
669  {
670  const auto pFrequencyOfInterestControlMessage =
671  reinterpret_cast<const Controls::FrequencyOfInterestControlMessage *>(pMessage);
672 
674  DEBUG_LEVEL,
675  Controls::FrequencyOfInterestControlMessageFormatter(pFrequencyOfInterestControlMessage),
676  "PHYI %03hu FrameworkPHY::%s Frequency of Interest Control Message",
677  id_,
678  __func__);
679 
680  u64BandwidthHz_ = pFrequencyOfInterestControlMessage->getBandwidthHz();
681 
682  dReceiverSensitivitydBm_ =
683  THERMAL_NOISE_DB + dSystemNoiseFiguredB_ + 10.0 * log10(u64BandwidthHz_);
684 
685  pSpectrumMonitor_->initialize(pFrequencyOfInterestControlMessage->getFrequencySet(),
686  u64BandwidthHz_,
687  Utils::DB_TO_MILLIWATT(dReceiverSensitivitydBm_),
688  noiseMode_,
689  noiseBinSize_,
690  maxSegmentOffset_,
691  maxMessagePropagation_,
692  maxSegmentDuration_,
693  timeSyncThreshold_,
694  bNoiseMaxClamp_);
695 
696  }
697 
698  break;
699 
700  default:
702  DEBUG_LEVEL,
703  "PHYI %03hu FrameworkPHY::%s, unexpected contoll message, ignore",
704  id_,
705  __func__);
706  }
707  }
708 }
709 
711  const ControlMessages & msgs)
712 {
713  auto now = Clock::now();
714 
715  const PacketInfo & pktInfo{pkt.getPacketInfo()};
716 
718  DEBUG_LEVEL,
719  "PHYI %03hu FrameworkPHY::%s src %hu, dst %hu",
720  id_,
721  __func__,
722  pktInfo.getSource(),
723  pktInfo.getDestination());
724 
725  commonLayerStatistics_.processInbound(pkt);
726 
727  // use the default unless provided below
728  std::uint64_t u64BandwidthHz{u64BandwidthHz_};
729 
730  // use the default unless provided below
731  Transmitters transmitters{{id_, dTxPowerdBm_}};
732 
733  // use the default unless provided below
734  FrequencySegments frequencySegments{{u64TxFrequencyHz_,Microseconds::zero()}};
735 
736  Controls::OTATransmitters otaTransmitters;
737 
738  TimePoint txTimeStamp{now};
739 
740  for(const auto & pMessage : msgs)
741  {
742  switch(pMessage->getId())
743  {
745  {
746  const auto pTransmitterControlMessage =
747  static_cast<const Controls::TransmitterControlMessage *>(pMessage);
748 
749 
751  DEBUG_LEVEL,
752  Controls::TransmitterControlMessageFormatter(pTransmitterControlMessage),
753  "PHYI %03hu FrameworkPHY::%s Transmitter Control Message",
754  id_,
755  __func__);
756 
757  transmitters = pTransmitterControlMessage->getTransmitters();
758 
759  // build the list of OTA transmitters
760  std::for_each(transmitters.begin(),
761  transmitters.end(),
762  [&otaTransmitters](const Transmitter & transmitter)
763  {
764  otaTransmitters.insert(transmitter.getNEMId());
765  });
766  }
767 
768  break;
769 
771  {
772  const auto pFrequencyControlMessage =
773  static_cast<const Controls::FrequencyControlMessage *>(pMessage);
774 
775  // the mac will be supplying frequency segment info so lets clear the defaults
776  frequencySegments.clear();
777 
778  for(const auto & segment : pFrequencyControlMessage->getFrequencySegments())
779  {
780  // for convience a mac can set duration and offset without specifying frequency
781  // by using 0 Hz.
782  if(segment.getFrequencyHz() == 0)
783  {
784  if(segment.getPowerdBm().second)
785  {
786  frequencySegments.push_back({u64TxFrequencyHz_, // use our frequency
787  segment.getPowerdBm().first,
788  segment.getDuration(), // duration
789  segment.getOffset()}); // offset
790  }
791  else
792  {
793  frequencySegments.push_back({u64TxFrequencyHz_, // use our frequency
794  segment.getDuration(), // duration
795  segment.getOffset()}); // offset
796  }
797  }
798  else
799  {
800  frequencySegments.push_back(segment);
801  }
802  }
803 
804  // if bandwidth provided is not 0, use the provided value,
805  // otherwise keep our default value from above
806  if(pFrequencyControlMessage->getBandwidthHz() != 0)
807  {
808  u64BandwidthHz = pFrequencyControlMessage->getBandwidthHz();
809  }
810 
812  DEBUG_LEVEL,
813  Controls::FrequencyControlMessageFormatter(pFrequencyControlMessage),
814  "PHYI %03hu FrameworkPHY::%s Frequency Control Message",
815  id_,
816  __func__);
817  }
818 
819  break;
820 
822  {
823  const auto pAntennaProfileControlMessage =
824  static_cast<const Controls::AntennaProfileControlMessage *>(pMessage);
825 
827  DEBUG_LEVEL,
828  "PHYI %03hu FrameworkPHY::%s Antenna Profile Control Message "
829  "profile %hu azimuth %lf elevation %lf",
830  id_,
831  __func__,
832  pAntennaProfileControlMessage->getAntennaProfileId(),
833  pAntennaProfileControlMessage->getAntennaAzimuthDegrees(),
834  pAntennaProfileControlMessage->getAntennaElevationDegrees());
835 
837  Events::AntennaProfiles profiles{{id_,
838  pAntennaProfileControlMessage->getAntennaProfileId(),
839  pAntennaProfileControlMessage->getAntennaAzimuthDegrees(),
840  pAntennaProfileControlMessage->getAntennaElevationDegrees()}};
841 
842  gainManager_.update(profiles);
843 
844  pkt.attachEvent(0,Events::AntennaProfileEvent{profiles});
846  }
847 
848  break;
849 
851  {
852  const auto pTimestampControlMessage =
853  static_cast<const Controls::TimeStampControlMessage *>(pMessage);
854 
855 
856  txTimeStamp = pTimestampControlMessage->getTimeStamp();
857 
859  DEBUG_LEVEL,
860  "PHYI %03hu FrameworkPHY::%s Time Stamp Control Message "
861  "timestamp %.6f",
862  id_,
863  __func__,
864  std::chrono::duration_cast<DoubleSeconds>(txTimeStamp.time_since_epoch()).count());
865  }
866 
867  break;
868 
870  {
871  const auto pFrequencyOfInterestControlMessage =
872  reinterpret_cast<const Controls::FrequencyOfInterestControlMessage *>(pMessage);
873 
875  DEBUG_LEVEL,
876  Controls::FrequencyOfInterestControlMessageFormatter(pFrequencyOfInterestControlMessage),
877  "PHYI %03hu FrameworkPHY::%s Frequency of Interest Control Message",
878  id_,
879  __func__);
880 
881  u64BandwidthHz_ = pFrequencyOfInterestControlMessage->getBandwidthHz();
882 
883  dReceiverSensitivitydBm_ =
884  THERMAL_NOISE_DB + dSystemNoiseFiguredB_ + 10.0 * log10(u64BandwidthHz_);
885 
886  pSpectrumMonitor_->initialize(pFrequencyOfInterestControlMessage->getFrequencySet(),
887  u64BandwidthHz_,
888  Utils::DB_TO_MILLIWATT(dReceiverSensitivitydBm_),
889  noiseMode_,
890  noiseBinSize_,
891  maxSegmentOffset_,
892  maxMessagePropagation_,
893  maxSegmentDuration_,
894  timeSyncThreshold_,
895  bNoiseMaxClamp_);
896 
897 
898  }
899 
900  break;
901  }
902  }
903 
904 
905  // verify the transmitters list include this nem
906  if(std::find_if(transmitters.begin(),
907  transmitters.end(),
908  [this](const Transmitter & transmitter)
909  {
910  return transmitter.getNEMId() == this->id_;
911  }) == transmitters.end())
912  {
913  transmitters.push_back({id_,dTxPowerdBm_});
914  }
915 
916 
917  CommonPHYHeader phyHeader{REGISTERED_EMANE_PHY_FRAMEWORK, // phy registration id
918  u16SubId_,
919  u16TxSequenceNumber_++,
920  u64BandwidthHz,
921  txTimeStamp,
922  frequencySegments,
923  transmitters,
924  optionalFixedAntennaGaindBi_};
925 
927  DEBUG_LEVEL,
928  std::bind(&CommonPHYHeader::format, std::ref(phyHeader)),
929  "PHYI %03hu FrameworkPHY::%s Common PHY Header",
930  id_,
931  __func__);
932 
933  ControlMessages downstreamControlMessages{};
934 
935  if(!otaTransmitters.empty())
936  {
937  downstreamControlMessages.
938  push_back(Controls::OTATransmitterControlMessage::create(otaTransmitters));
939  }
940 
941  commonLayerStatistics_.processOutbound(pkt,
942  std::chrono::duration_cast<Microseconds>(Clock::now() - now));
943 
944 
945  sendDownstreamPacket(std::move(phyHeader),pkt,std::move(downstreamControlMessages));
946 }
947 
948 
950  UpstreamPacket & pkt,
951  const ControlMessages &)
952 {
953  processUpstreamPacket_i(Clock::now(),commonPHYHeader,pkt,{});
954 }
955 
957  const CommonPHYHeader & commonPHYHeader,
958  UpstreamPacket & pkt,
959  const ControlMessages &)
960 {
962  DEBUG_LEVEL,
963  std::bind(&CommonPHYHeader::format, std::ref(commonPHYHeader)),
964  "PHYI %03hu FrameworkPHY::%s Common PHY Header",
965  id_,
966  __func__);
967 
968  commonLayerStatistics_.processInbound(pkt);
969 
970  const auto & pktInfo = pkt.getPacketInfo();
971 
972  bool bInBand{commonPHYHeader.getRegistrationId() == REGISTERED_EMANE_PHY_FRAMEWORK &&
973  u16SubId_ == commonPHYHeader.getSubId()};
974 
975  // unless this is an in-band packet, it will only be processed if
976  // noise processing is on
977  if(bInBand || noiseMode_ != SpectrumMonitor::NoiseMode::NONE)
978  {
979  bool bDrop{};
980 
981  const auto & frequencySegments = commonPHYHeader.getFrequencySegments();
982 
983  std::vector<double> rxPowerSegments(frequencySegments.size(),0);
984 
985  Microseconds propagation{};
986 
987  bool bHavePropagationDelay{};
988 
989  std::vector<NEMId> transmitters{};
990 
991  for(const auto & transmitter : commonPHYHeader.getTransmitters())
992  {
993  transmitters.push_back(transmitter.getNEMId());
994 
995  // get the location info for a pair of nodes
996  auto locationPairInfoRet = locationManager_.getLocationInfo(transmitter.getNEMId());
997 
998  // get the propagation model pathloss between a pair of nodes for *each* segment
999  auto pathlossInfo = (*pPropagationModelAlgorithm_)(transmitter.getNEMId(),
1000  locationPairInfoRet.first,
1001  frequencySegments);
1002 
1003  // if pathloss is available
1004  if(pathlossInfo.second)
1005  {
1006  // calculate the combined gain (Tx + Rx antenna gain) dBi
1007  // note: gain manager accesses antenna profiles, knows self node profile info
1008  // if available, and is updated with all nodes profile info
1009  auto gainInfodBi = gainManager_.determineGain(transmitter.getNEMId(),
1010  locationPairInfoRet.first,
1011  optionalFixedAntennaGaindBi_,
1012  commonPHYHeader.getOptionalFixedAntennaGaindBi());
1013 
1014  // if gain is available
1015  if(gainInfodBi.second == EMANE::GainManager::GainStatus::SUCCESS)
1016  {
1017  using ReceivePowerPubisherUpdate = std::tuple<NEMId,std::uint64_t,double>;
1018 
1019  // set to prevent multiple ReceivePowerTablePublisher updates
1020  // for the same NEM frequency pair in a frequency segment list
1021  std::set<ReceivePowerPubisherUpdate> receivePowerTableUpdate{};
1022 
1023  // frequency segment iterator to map pathloss per segment to
1024  // the associated segment
1025  FrequencySegments::const_iterator freqIter{frequencySegments.begin()};
1026 
1027  std::size_t i{};
1028 
1029  // sum up the rx power for each segment
1030  for(const auto & dPathlossdB : pathlossInfo.first)
1031  {
1032  auto optionalSegmentPowerdBm = freqIter->getPowerdBm();
1033 
1034  double powerdBm{(optionalSegmentPowerdBm.second ?
1035  optionalSegmentPowerdBm.first :
1036  transmitter.getPowerdBm()) +
1037  gainInfodBi.first -
1038  dPathlossdB};
1039 
1040  auto powerdBmInfo = fadingManager_.calculate(transmitter.getNEMId(),
1041  powerdBm,
1042  locationPairInfoRet);
1043 
1044  if(powerdBmInfo.second == FadingManager::FadingStatus::SUCCESS)
1045  {
1046  receivePowerTableUpdate.insert(ReceivePowerPubisherUpdate{transmitter.getNEMId(),
1047  freqIter->getFrequencyHz(),
1048  powerdBmInfo.first});
1049 
1050  ++freqIter;
1051 
1052  rxPowerSegments[i++] += Utils::DB_TO_MILLIWATT(powerdBmInfo.first);
1053  }
1054  else
1055  {
1056  // drop due to FadingManager not enough info
1057  bDrop = true;
1058 
1059  std::uint16_t u16Code{};
1060 
1061  const char * pzReason{};
1062 
1063  switch(powerdBmInfo.second)
1064  {
1066  pzReason = "fading missing location info";
1067  u16Code = DROP_CODE_FADINGMANAGER_LOCATION;
1068  break;
1070  pzReason = "fading algorithm error/missing info";
1071  u16Code = DROP_CODE_FADINGMANAGER_ALGORITHM;
1072  break;
1074  pzReason = "fading algorithm selection unkown";
1075  u16Code = DROP_CODE_FADINGMANAGER_SELECTION;
1076  break;
1077  default:
1078  pzReason = "unknown";
1079  break;
1080  }
1081 
1082  commonLayerStatistics_.processOutbound(pkt,
1083  std::chrono::duration_cast<Microseconds>(Clock::now() - now),
1084  u16Code);
1085 
1087  DEBUG_LEVEL,
1088  "PHYI %03hu FrameworkPHY::%s transmitter %hu,"
1089  " src %hu, dst %hu, drop %s",
1090  id_,
1091  __func__,
1092  transmitter.getNEMId(),
1093  pktInfo.getSource(),
1094  pktInfo.getDestination(),
1095  pzReason);
1096 
1097  break;
1098  }
1099  }
1100 
1101  for(const auto & entry : receivePowerTableUpdate)
1102  {
1103  receivePowerTablePublisher_.update(std::get<0>(entry),
1104  std::get<1>(entry),
1105  std::get<2>(entry),
1106  commonPHYHeader.getTxTime());
1107  }
1108 
1109 
1110  // calculate propagation delay from 1 of the transmitters
1111  // note: these are collaborative (constructive) transmissions, all
1112  // the messages are arriving at or near the same time. Destructive
1113  // transmission should be sent as multiple messages
1114  if(locationPairInfoRet.second && !bHavePropagationDelay)
1115  {
1116  if(locationPairInfoRet.first.getDistanceMeters() > 0.0)
1117  {
1118  propagation =
1119  Microseconds{static_cast<std::uint64_t>(std::round(locationPairInfoRet.first.getDistanceMeters() / SOL_MPS * 1000000))};
1120  }
1121 
1122  bHavePropagationDelay = true;
1123  }
1124  }
1125  else
1126  {
1127  // drop due to GainManager not enough info
1128  bDrop = true;
1129 
1130  std::uint16_t u16Code{};
1131 
1132  const char * pzReason{};
1133 
1134  switch(gainInfodBi.second)
1135  {
1137  pzReason = "missing location info";
1138  u16Code = DROP_CODE_GAINMANAGER_LOCATION;
1139  break;
1141  pzReason = "missing profile info";
1142  u16Code = DROP_CODE_GAINMANAGER_ANTENNAPROFILE;
1143  break;
1145  pzReason = "below the horizon";
1146  u16Code = DROP_CODE_GAINMANAGER_HORIZON;
1147  break;
1148  default:
1149  pzReason = "unknown";
1150  break;
1151  }
1152 
1153  commonLayerStatistics_.processOutbound(pkt,
1154  std::chrono::duration_cast<Microseconds>(Clock::now() - now),
1155  u16Code);
1156 
1158  DEBUG_LEVEL,
1159  "PHYI %03hu FrameworkPHY::%s transmitter %hu, src %hu, dst %hu, drop %s",
1160  id_,
1161  __func__,
1162  transmitter.getNEMId(),
1163  pktInfo.getSource(),
1164  pktInfo.getDestination(),
1165  pzReason);
1166 
1167 
1168  break;
1169  }
1170  }
1171  else
1172  {
1173  // drop due to PropagationModelAlgorithm not enough info
1174  bDrop = true;
1175 
1176  commonLayerStatistics_.processOutbound(pkt,
1177  std::chrono::duration_cast<Microseconds>(Clock::now() - now),
1178  DROP_CODE_PROPAGATIONMODEL);
1179 
1181  DEBUG_LEVEL,
1182  "PHYI %03hu FrameworkPHY::%s transmitter %hu, src %hu, dst %hu,"
1183  " drop propagation model missing info",
1184  id_,
1185  __func__,
1186  transmitter.getNEMId(),
1187  pktInfo.getSource(),
1188  pktInfo.getDestination());
1189  break;
1190  }
1191  }
1192 
1193  if(!bDrop)
1194  {
1195 
1196  // update the spectrum monitor with the signal information
1197  // note: spectrum monitor will remove any frequency segments that are
1198  // below the receiver sensitivity. Any frequency segment not in
1199  // the foi will cause the entire message to be treated as out-of-band
1200  // regardless of the subid. Spectrum monitor will adjust SoT, propagation
1201  // delay, offset and duration if out of acceptable value range.
1202  try
1203  {
1204  auto spectrumInfo = pSpectrumMonitor_->update(now,
1205  commonPHYHeader.getTxTime(),
1206  propagation,
1207  frequencySegments,
1208  commonPHYHeader.getBandwidthHz(),
1209  rxPowerSegments,
1210  bInBand,
1211  transmitters);
1212 
1213  TimePoint sot{};
1214  Microseconds propagationDelay{};
1215  Microseconds span{};
1216  FrequencySegments resultingFrequencySegments{};
1217  bool bTreatAsInBand{};
1218 
1219  std::tie(sot,
1220  propagationDelay,
1221  span,
1222  resultingFrequencySegments,
1223  bTreatAsInBand) = spectrumInfo;
1224 
1225  if(bTreatAsInBand)
1226  {
1227  if(!resultingFrequencySegments.empty())
1228  {
1229  commonLayerStatistics_.processOutbound(pkt,
1230  std::chrono::duration_cast<Microseconds>(Clock::now() - now));
1231 
1232 
1234  DEBUG_LEVEL,
1235  "PHYI %03hu FrameworkPHY::%s src %hu, dst %hu,"
1236  " pass",
1237  id_,
1238  __func__,
1239  pktInfo.getSource(),
1240  pktInfo.getDestination());
1241 
1242  if(sot != commonPHYHeader.getTxTime())
1243  {
1244  ++*pTimeSyncThresholdRewrite_;
1245  }
1246 
1248  // send to mac with associated control messages
1249  sendUpstreamPacket(pkt,
1251  resultingFrequencySegments),
1253  propagationDelay,
1254  span,
1255  dReceiverSensitivitydBm_)});
1257  }
1258  else
1259  {
1260  commonLayerStatistics_.processOutbound(pkt,
1261  std::chrono::duration_cast<Microseconds>(Clock::now() - now),
1262  DROP_CODE_RX_SENSITIVITY);
1263 
1265  DEBUG_LEVEL,
1266  "PHYI %03hu FrameworkPHY::%s src %hu, dst %hu,"
1267  " drop below receiver sensitivity",
1268  id_,
1269  __func__,
1270  pktInfo.getSource(),
1271  pktInfo.getDestination());
1272 
1273  }
1274  }
1275  else
1276  {
1277  // was this packet actually in-band, if so at least 1 freq was not in the foi
1278  if(bInBand)
1279  {
1280  commonLayerStatistics_.processOutbound(pkt,
1281  std::chrono::duration_cast<Microseconds>(Clock::now() - now),
1282  DROP_CODE_NOT_FOI);
1283 
1285  DEBUG_LEVEL,
1286  "PHYI %03hu FrameworkPHY::%s src %hu, dst %hu,"
1287  " drop one or more frequencies not in frequency of interest list",
1288  id_,
1289  __func__,
1290  pktInfo.getSource(),
1291  pktInfo.getDestination());
1292  }
1293  else
1294  {
1295  // must be subid
1296  commonLayerStatistics_.processOutbound(pkt,
1297  std::chrono::duration_cast<Microseconds>(Clock::now() - now),
1298  DROP_CODE_OUT_OF_BAND);
1299 
1301  DEBUG_LEVEL,
1302  "PHYI %03hu FrameworkPHY::%s src %hu, dst %hu,"
1303  " drop out of band",
1304  id_,
1305  __func__,
1306  pktInfo.getSource(),
1307  pktInfo.getDestination());
1308  }
1309 
1310  }
1311  }
1312  catch(SpectrumServiceException & exp)
1313  {
1314  commonLayerStatistics_.processOutbound(pkt,
1315  std::chrono::duration_cast<Microseconds>(Clock::now() - now),
1316  DROP_CODE_SPECTRUM_CLAMP);
1317 
1319  DEBUG_LEVEL,
1320  "PHYI %03hu FrameworkPHY::%s src %hu, dst %hu,"
1321  " drop spectrum out of bound %s",
1322  id_,
1323  __func__,
1324  pktInfo.getSource(),
1325  pktInfo.getDestination(),
1326  exp.what());
1327  }
1328  }
1329  }
1330  else
1331  {
1332  commonLayerStatistics_.processOutbound(pkt,
1333  std::chrono::duration_cast<Microseconds>(Clock::now() - now),
1334  DROP_CODE_OUT_OF_BAND);
1335 
1337  DEBUG_LEVEL,
1338  "PHYI %03hu FrameworkPHY::%s src %hu, dst %hu,"
1339  " drop out of band",
1340  id_,
1341  __func__,
1342  pktInfo.getSource(),
1343  pktInfo.getDestination());
1344  }
1345 }
1346 
1349  const Serialization & serialization)
1350 {
1352  DEBUG_LEVEL,
1353  "PHYI %03hu FrameworkPHY::%s event id: %hu",
1354  id_,
1355  __func__,
1356  eventId);
1357 
1358  switch(eventId)
1359  {
1361  {
1362  Events::AntennaProfileEvent antennaProfile{serialization};
1363  gainManager_.update(antennaProfile.getAntennaProfiles());
1364  eventTablePublisher_.update(antennaProfile.getAntennaProfiles());
1365 
1367  DEBUG_LEVEL,
1368  Events::AntennaProfileEventFormatter(antennaProfile),
1369  "PHYI %03hu FrameworkPHY::%s antenna profile event: ",
1370  id_,
1371  __func__);
1372 
1373  }
1374  break;
1375 
1377  {
1378  Events::FadingSelectionEvent fadingSelection{serialization};
1379  fadingManager_.update(fadingSelection.getFadingSelections());
1380  eventTablePublisher_.update(fadingSelection.getFadingSelections());
1381 
1383  DEBUG_LEVEL,
1384  Events::FadingSelectionEventFormatter(fadingSelection),
1385  "PHYI %03hu FrameworkPHY::%s fading selection event: ",
1386  id_,
1387  __func__);
1388  }
1389  break;
1390 
1392  {
1393  Events::LocationEvent locationEvent{serialization};
1394  locationManager_.update(locationEvent.getLocations());
1395  eventTablePublisher_.update(locationEvent.getLocations());
1396 
1398  DEBUG_LEVEL,
1399  Events::LocationEventFormatter(locationEvent),
1400  "PHYI %03hu FrameworkPHY::%s location event: ",
1401  id_,
1402  __func__);
1403  }
1404  break;
1405 
1407  {
1408  Events::PathlossEvent pathlossEvent{serialization};
1409  pPropagationModelAlgorithm_->update(pathlossEvent.getPathlosses());
1410  eventTablePublisher_.update(pathlossEvent.getPathlosses());
1411 
1413  DEBUG_LEVEL,
1414  Events::PathlossEventFormatter(pathlossEvent),
1415  "PHYI %03hu FrameworkPHY::%s pathloss event: ",
1416  id_,
1417  __func__);
1418  }
1419  break;
1420  }
1421 }
Callable formatter object for FrequencyOfInterestControlMessage instances.
std::set< NEMId > OTATransmitters
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 attachEvent(NEMId nemId, const Event &event)
The Registrar interface provides access to all of the emulator registrars.
Definition: registrar.h:50
The Transmitter Control Message is sent to the emulator physical layer to specify the NEM Id of the s...
void configure(const ConfigurationUpdate &update) override
virtual ConfigurationRegistrar & configurationRegistrar()=0
An antenna profile event is used to set the antenna profile selection and pointing information for on...
std::pair< double, GainStatus > determineGain(NEMId transmitterId, const LocationInfo &locationPairInfo, const std::pair< double, bool > &optionalRxFixedGaindBi, const std::pair< double, bool > &optionalTxFixedGaindBi) const
Definition: gainmanager.cc:85
Callable formatter object for LocationEvent instances.
static OTATransmitterControlMessage * create(const Serialization &serialization)
#define LOGGER_VERBOSE_LOGGING(logger, level, fmt, args...)
void start() override
Holds transmitter id and power level.
Definition: transmitter.h:49
void update(const Events::Locations &locations)
virtual StatisticRegistrar & statisticRegistrar()=0
A pathloss event is used to set the pathloss from one or more transmitting NEMs to a receiving NEM...
Definition: pathlossevent.h:52
void processOutbound(const UpstreamPacket &pkt, Microseconds delay, size_t dropCode={})
Interface used to create a PHY layer plugin implementation.
Definition: phylayerimpl.h:53
void destroy() override
std::list< const ControlMessage * > ControlMessages
void processUpstreamPacket(const CommonPHYHeader &hdr, UpstreamPacket &pkt, const ControlMessages &msgs) override
const std::pair< double, bool > & getOptionalFixedAntennaGaindBi() const
An fading selection event is used to set the fading model for one or more NEMs.
const double SOL_MPS
Definition: constants.h:58
void update(NEMId nemId, std::uint64_t u64Frequency, double dReceivePower, const TimePoint &rxTime)
Antenna Profile Control Message is sent to the emulator physical layer to update antenna profile sele...
SpectrumServiceException is thrown when an exception occurs during spectrum service processing...
void initialize(Registrar &registrar)
void processEvent(const EventId &eventId, const Serialization &serialization) override
void update(const Events::Locations &locations)
void sendDownstreamPacket(const CommonPHYHeader &hdr, DownstreamPacket &pkt, const ControlMessages &msgs=DownstreamTransport::empty)
std::uint64_t getBandwidthHz() const
A location event is usd to set the position, orientation and velocity information for one or more NEM...
Definition: locationevent.h:52
std::uint16_t EventId
Definition: types.h:53
The PlatformServiceProvider interface provides access to emulator services.
virtual EventRegistrar & eventRegistrar()=0
The Frequency of Interest Control Message is sent to the emulator physical layer to specify receive f...
void registerStatistics(StatisticRegistrar &statisticRegistrar)
Store source, destination, creation time and priority information for a packet.
Definition: packetinfo.h:50
static FrequencyControlMessage * create(std::uint64_t u64BandwidthHz, const FrequencySegments &frequencySegments)
void processConfiguration(const ConfigurationUpdate &update) override
void initialize(Registrar &registrar) override
Callable formatter object for PathlossEvent instances.
std::set< std::uint64_t > FrequencySet
const TimePoint & getTxTime() const
virtual EventServiceProvider & eventService()=0
const char * what() const
Definition: exception.h:62
The Frequency Control Message is sent to the emulator physical layer to specify the frequency segment...
The common physical layer header used to facilitate heterogeneous radio model experimentation.
#define LOGGER_VERBOSE_LOGGING_FN_VARGS(logger, level, fn, fmt, args...)
std::vector< std::string > StatisticTableLabels
const PacketInfo & getPacketInfo() const
void update(const Events::FadingSelections &fadingSelections)
void registerStatistics(StatisticRegistrar &registrar)
Specialized packet the allows downstream processing to add layer specific headers as the packet trave...
std::tuple< TimePoint, Microseconds, Microseconds, FrequencySegments, bool > update(const TimePoint &now, const TimePoint &txTime, const Microseconds &propagationDelay, const FrequencySegments &segments, std::uint64_t u64SegmentBandwidthHz, const std::vector< double > &rxPowersMilliWatt, bool bInBand, const std::vector< NEMId > &transmitters)
void processDownstreamPacket(DownstreamPacket &pkt, const ControlMessages &msgs) override
const RegistrationId REGISTERED_EMANE_PHY_FRAMEWORK
Definition: phytypes.h:90
const FrequencySegments & getFrequencySegments() const
void stop() override
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
std::pair< LocationInfo, bool > getLocationInfo(NEMId remoteNEMId)
PlatformServiceProvider * pPlatformService_
void initialize(const FrequencySet &foi, std::uint64_t u64BandwidthHz, double dReceiverSensitivityMilliWatt, NoiseMode mode, const Microseconds &binSize, const Microseconds &maxOffset, const Microseconds &maxPropagation, const Microseconds &maxDuration, const Microseconds &timeSyncThreshold, bool bMaxClamp)
void processUpstreamPacket_i(const TimePoint &now, const CommonPHYHeader &hdr, UpstreamPacket &pkt, const ControlMessages &msgs)
void processDownstreamControl(const ControlMessages &msgs) override
void configure(const ConfigurationUpdate &update)
std::uint16_t getSubId() const
Callable formatter object for TransmitterControlMessage instances.
std::pair< double, FadingStatus > calculate(NEMId txNEMId, double dPowerdBm, const std::pair< LocationInfo, bool > &location)
const Transmitters & getTransmitters() const
virtual LogServiceProvider & logService()=0
std::list< FrequencySegment > FrequencySegments
Callable formatter object for FrequencyControlMessage instances.
std::vector< ConfigurationNameAnyValues > ConfigurationUpdate
Callable formatter object for AntennaProfileEvent instances.
void update(const Events::AntennaProfiles &antennaProfiles)
Definition: gainmanager.cc:50
double DB_TO_MILLIWATT(double ddB)
static ReceivePropertiesControlMessage * create(const TimePoint &txTime, const Microseconds &propagation, const Microseconds &span, double dReceiverSensitivitydBm)
virtual void registerEvent(EventId eventId)=0
Time Stamp Control Message is sent to the emulator physical layer to specify the time that should be ...
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
const double THERMAL_NOISE_DB
Definition: constants.h:42
void sendUpstreamPacket(UpstreamPacket &pkt, const ControlMessages &msgs=empty)
#define LOGGER_STANDARD_LOGGING(logger, level, fmt, args...)
#define LOGGER_STANDARD_LOGGING_FN_VARGS(logger, level, fn, fmt, args...)
FrameworkPHY(NEMId id, PlatformServiceProvider *pPlatformService, SpectrumMonitor *pSpectrumMonitor)
Definition: frameworkphy.cc:96
virtual void sendEvent(NEMId nemId, const Event &event)=0
void modify(const ConfigurationUpdate &update)
std::list< AntennaProfile > AntennaProfiles
void processInbound(const UpstreamPacket &pkt)
Callable formatter object for FadingSelectionEvent instances.
void registerStatistics(StatisticRegistrar &registrar)
RegistrationId getRegistrationId() const