55 const char * pzLayerName =
"PHYAPITest::ShimLayer";
57 static std::uint8_t PAYLOAD_BUFFER[0xffff] = {0xBE};
69 dAntennaAzimuthDegrees_{},
70 dAntennaElevationDegrees_{},
93 "Packet size in bytes.");
96 configRegistrar.registerNumeric<
float>(
"packetrate",
99 "Defines the transmit rate in packets per second.");
101 configRegistrar.registerNumeric<std::uint16_t>(
"destination",
104 "Defines the destination NEM Id.",
107 configRegistrar.registerNumeric<std::uint64_t>(
"bandwidth",
110 "Defines the transmitter bandwidth in Hz.",
113 configRegistrar.registerNumeric<std::uint16_t>(
"antennaprofileid",
116 "Defines the antenna profile id. The antenna profile id is" 117 " used to identify the appropriate antenna pattern and" 118 " blockage pattern to use when calculating the receive" 119 " power for each packet.");
121 configRegistrar.registerNumeric<
double>(
"antennaazimuth",
124 "Defines the antenna azimuth pointing angle in degrees.",
128 configRegistrar.registerNumeric<
double>(
"antennaelevation",
131 "Defines the antenna elevation pointing angle in degrees.",
136 configRegistrar.registerNonNumeric<std::string>(
"frequency",
139 "Defines a list of transmit frquency segments with each item" 140 " containing the following 3 elements: 1) frequency (center" 141 " frequency Hz), 2) duration (semgent duraton in usec), and 3)" 142 " offset (transmit offset from TxTime in usec)." 143 " <Frequency>:<Duration>:<Offset>",
146 "^\\d+(\\.\\d+)?[GMK]?:\\d+(\\.\\d+)?:\\d+(\\.\\d+)?$");
148 configRegistrar.registerNumeric<
float>(
"txpower",
151 "Defines the transmit power in dBm.");
153 configRegistrar.registerNonNumeric<std::string>(
"transmitter",
156 "Defines a list of additional collaborative transmitters to be" 157 " included. Each item in the list will include NEM ID and" 158 " transmit power in dBm. <NEM Id>:<Tx Power>.",
161 "^\\d+:\\d+(\\.\\d+)?$");
176 for(
const auto & item : update)
178 if(item.first ==
"packetsize")
180 u16PacketSize_ = item.second[0].asUINT16();
184 "SHIMI %03d %s::%s %s = %hu bytes",
191 else if(item.first ==
"packetrate")
193 float fPacketRate = item.second[0].asFloat();
197 "SHIMI %03d %s::%s %s = %3.2f pps",
204 if(fPacketRate > 0.0)
210 else if(item.first ==
"destination")
212 dst_ = item.second[0].asUINT16();
216 "SHIMI %03d %s::%s %s = %hu",
223 else if(item.first ==
"bandwidth")
225 u64BandwidthHz_ = item.second[0].asUINT64();
229 "SHIMI %03d %s::%s %s = %ju",
236 else if(item.first ==
"antennaprofileid")
238 antennaProfileId_ = item.second[0].asUINT16();
242 "SHIMI %03d %s::%s %s = %hu",
249 else if(item.first ==
"antennaazimuth")
251 dAntennaAzimuthDegrees_ = item.second[0].asDouble();
255 "SHIMI %03d %s::%s %s = %lf deg",
260 dAntennaAzimuthDegrees_);
262 else if(item.first ==
"antennaelevation")
264 dAntennaElevationDegrees_ = item.second[0].asDouble();
268 "SHIMI %03d %s::%s %s = %lf deg",
273 dAntennaElevationDegrees_);
275 else if(item.first ==
"txpower")
277 fTxPowerdBm_ = item.second[0].asFloat();
281 "SHIMI %03d %s::%s %s = %f dBm",
288 else if(item.first ==
"transmitter")
290 for(
const auto & any : item.second)
292 std::string sValue = any.asString();
298 if(tokens.size() == 2)
305 "SHIMI %03d %s::%s %s NEM = %hu, txpwr = %f dBm",
314 transmitters_.push_back({u16TxNEM, fTxPower});
320 "SHIMI %03d %s::%s invalid format %s (%s), expected (NEM:txpwr)",
327 throw makeException<ConfigurationException>(
"PHYAPITestShimLayer: Invalid format %s = %s",
333 else if(item.first ==
"frequency")
335 for(
const auto & any : item.second)
337 std::string sValue = any.asString();
343 if(tokens.size() == 3)
351 "SHIMI %03d %s::%s %s freq %ju Hz, duration %lf, offset %lf",
361 frequencySegments_.push_back({u64TxFrequency,
363 std::chrono::duration_cast<Microseconds>(offset)});
369 "SHIMI %03d %s::%s invalid format %s (%s), expected (freq:duration:offset)",
376 throw makeException<ConfigurationException>(
"PHYAPITestShimLayer: Invalid format %s = %s",
384 throw makeException<ConfigureException>(
"%s: Unexpected configuration item %s",
413 if(txTimedEventId_ != 0)
432 if(txInterval_ > DoubleSeconds::zero())
437 scheduleTimedEvent(Clock::now() + std::chrono::duration_cast<Microseconds>(txInterval_),
439 std::chrono::duration_cast<Microseconds>(txInterval_));
462 "SHIMI %03d %s::%s, unexpected control message, drop",
474 "SHIMI %03d %s::%s, unexpected control message, drop",
490 "SHIMI %03d %s::%s src %hu dst %hu size %zu controls %zu",
499 for(
const auto & pControlMessage : msgs)
501 switch(pControlMessage->getId())
505 const auto pFrequencyControlMessage =
511 "SHIMI %03d %s::%s Frequency Control Message",
522 const auto pReceivePropertiesControlMessage =
528 "SHIMI %03d %s::%s Receive Properties Control Message",
540 "SHIMI %03d %s::%s Unknown control message id %hu",
544 pControlMessage->getId());
556 "SHIMI %03d %s::%s, unexpected packet, drop",
577 frequencySegments_)};
579 if(antennaProfileId_)
582 dAntennaAzimuthDegrees_,
583 dAntennaElevationDegrees_));
A Packet class that allows upstream processing to strip layer headers as the packet travels up the st...
The Registrar interface provides access to all of the emulator registrars.
static AntennaProfileControlMessage * create(AntennaProfileId id, double dAntennaAzimuthDegrees, double dAntennaElevationDegrees)
virtual ConfigurationRegistrar & configurationRegistrar()=0
std::vector< std::string > getTokens(const std::string &sInput, const char *pzDelimeter)
void postStart() override
#define LOGGER_VERBOSE_LOGGING(logger, level, fmt, args...)
Recieve Properties Control Message is sent from the emulator physical layer with every upstream packe...
static TransmitterControlMessage * create(const Transmitters &transmitters)
std::uint16_t toUINT16(std::uint16_t u16Min=std::numeric_limits< std::uint16_t >::min(), std::uint16_t u16Max=std::numeric_limits< std::uint16_t >::max()) const
std::list< const ControlMessage * > ControlMessages
void processUpstreamPacket(UpstreamPacket &pkt, const ControlMessages &msgs) override
float toFloat(float fMin=std::numeric_limits< float >::lowest(), float fMax=std::numeric_limits< float >::max()) const
void processUpstreamControl(const ControlMessages &msgs) override
NEMId getDestination() const
constexpr NEMId NEM_BROADCAST_MAC_ADDRESS
std::uint64_t toUINT64(std::uint64_t u64Min=std::numeric_limits< std::uint64_t >::min(), std::uint64_t u64Max=std::numeric_limits< std::uint64_t >::max()) const
Store source, destination, creation time and priority information for a packet.
static FrequencyControlMessage * create(std::uint64_t u64BandwidthHz, const FrequencySegments &frequencySegments)
void processTimedEvent(TimerEventId eventId, const TimePoint &expireTime, const TimePoint &scheduleTime, const TimePoint &fireTime, const void *arg) override
Interface used to create a Shim layer plugin implementation.
The Frequency Control Message is sent to the emulator physical layer to specify the frequency segment...
void initialize(Registrar ®istrar) override
const PacketInfo & getPacketInfo() const
Specialized packet the allows downstream processing to add layer specific headers as the packet trave...
std::chrono::microseconds Microseconds
void processDownstreamPacket(DownstreamPacket &pkt, const ControlMessages &msgs) override
std::chrono::duration< double > DoubleSeconds
DECLARE_SHIM_LAYER(EMANE::Models::PHYAPITest::ShimLayer)
void processDownstreamControl(const ControlMessages &msgs) override
The RadioServiceProvider interface provides access to radio (RF) model specific services.
void configure(const ConfigurationUpdate &update) override
std::vector< ConfigurationNameAnyValues > ConfigurationUpdate
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
virtual bool cancelTimedEvent(TimerEventId eventId)=0
#define LOGGER_STANDARD_LOGGING(logger, level, fmt, args...)
#define LOGGER_STANDARD_LOGGING_FN_VARGS(logger, level, fn, fmt, args...)
shim layer used to test the universal phy send/recv api
void sendDownstreamPacket(DownstreamPacket &pkt, const ControlMessages &msgs=empty)
Parameter conversion class with range checks.
ShimLayer(NEMId id, PlatformServiceProvider *pPlatformService, RadioServiceProvider *pRadioService)