EMANE  1.2.1
models/shim/timinganalysis/shimlayer.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013-2014 - Adjacent Link LLC, Bridgewater, New Jersey
3  * Copyright (c) 2009 - 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 #include "shimlayer.h"
35 #include "shimheadermessage.h"
37 
38 namespace
39 {
41  {
43 
44  for(const auto & msg : msgs)
45  {
46  clones.push_back(msg->clone());
47  }
48 
49  return clones;
50  }
51 }
52 
53 
55  PlatformServiceProvider * pPlatformService,
56  RadioServiceProvider * pRadioService) :
57  ShimLayerImplementor{id,pPlatformService,pRadioService},
58  u32MaxQueueSize_{0},
59  u16PacketId_{0}
60 { }
61 
63 { }
64 
66 {
69  "SHIM %03hu TimingAnalysis::ShimLayer::%s",
70  id_,
71  __func__);
72 
73  auto & configRegistrar = registrar.configurationRegistrar();
74 
75  configRegistrar.registerNumeric<std::uint32_t>("maxqueuesize",
77  {0},
78  "Max size of the delta time storage queue.");
79 
80 }
81 
83 {
86  "SHIM %03hu TimingAnalysis::ShimLayer::%s",
87  id_,
88  __func__);
89 
90  for(const auto & item : update)
91  {
92  if(item.first == "maxqueuesize")
93  {
94  u32MaxQueueSize_ = item.second[0].asUINT32();
95 
97  INFO_LEVEL,
98  "SHIM %03hu TimingAnalysis::ShimLayer::%s,%s = %u",
99  id_,
100  __func__,
101  item.first.c_str(),
102  u32MaxQueueSize_);
103  }
104  else
105  {
106  throw makeException<ConfigureException>("TimingAnalysis::ShimLayer: "
107  "Unexpected configuration item %s",
108  item.first.c_str());
109 
110  }
111  }
112 }
113 
115 {
117  DEBUG_LEVEL,
118  "SHIM %03hu TimingAnalysis::ShimLayer::%s",
119  id_,
120  __func__);
121 }
122 
124 {
126  DEBUG_LEVEL,
127  "SHIM %03hu TimingAnalysis::ShimLayer::%s",
128  id_,
129  __func__);
130 
131  char filename[256] = {0};
132 
133  QueueEntry entry;
134 
135  sprintf(filename,"/tmp/timinganalysis%hu.txt",id_);
136 
137  FILE *fp{fopen(filename,"w")};
138 
139  if(fp != nullptr)
140  {
141  while(!queue_.empty())
142  {
143  entry = queue_.front();
144 
145  fprintf(fp,"%hu %hu %f %f\n",
146  entry.u16Source,
147  entry.u16PacketId,
148  std::chrono::duration_cast<DoubleSeconds>(entry.txTime.time_since_epoch()).count(),
149  std::chrono::duration_cast<DoubleSeconds>(entry.rxTime.time_since_epoch()).count());
150 
151  queue_.pop();
152  }
153 
154  fclose(fp);
155  }
156  else
157  {
159  ERROR_LEVEL,
160  "SHIM %03hu TimingAnalysis::ShimLayer::%s: Can't open file (%s)",
161  id_,
162  __func__,
163  filename);
164  }
165 }
166 
167 
169  throw()
170 {
172  DEBUG_LEVEL,
173  "SHIM %03hu TimingAnalysis::ShimLayer::%s",
174  id_,
175  __func__);
176 }
177 
178 
180 {
182  DEBUG_LEVEL,
183  "SHIM %03hu TimingAnalysis::ShimLayer::%s",
184  id_,
185  __func__);
186 
187  sendUpstreamControl(clone(msgs));
188 }
189 
190 
192 {
194  DEBUG_LEVEL,
195  "SHIM %03hu TimingAnalysis::ShimLayer::%s",
196  id_,
197  __func__);
198 
199  sendDownstreamControl(clone(msgs));
200 }
201 
202 
204  const ControlMessages & msgs)
205 {
206  TimePoint beginTime {Clock::now()};
207 
208  size_t len{pkt.stripLengthPrefixFraming()};
209 
210  if(len && pkt.length() >= len)
211  {
212  ShimHeaderMessage shimHeader{pkt.get(), len};
213 
214  pkt.strip(len);
215 
216  QueueEntry entry;
217 
218  entry.txTime = shimHeader.getTxTime();
219 
220  entry.u16Source = shimHeader.getSource();
221 
222  entry.u16PacketId = shimHeader.getPacketId();
223 
224  entry.rxTime = beginTime;
225 
227  DEBUG_LEVEL,
228  "SHIM %03hu TimingAnalysis::ShimLayer::%s "
229  "Src: %hu PktID: %hu TxTime: %f RxTime: %f, deltaT %f sec",
230  id_,
231  __func__,
232  entry.u16Source,
233  entry.u16PacketId,
234  std::chrono::duration_cast<DoubleSeconds>(entry.txTime.time_since_epoch()).count(),
235  std::chrono::duration_cast<DoubleSeconds>(entry.rxTime.time_since_epoch()).count(),
236  std::chrono::duration_cast<DoubleSeconds>(entry.rxTime - entry.txTime).count());
237 
238  if(u32MaxQueueSize_ != 0)
239  {
240  if(queue_.size() >= u32MaxQueueSize_)
241  {
242  queue_.pop();
243  }
244  }
245 
246  queue_.push(entry);
247  }
248 
249  sendUpstreamPacket(pkt, clone(msgs));
250 }
251 
252 
254  const ControlMessages & msgs)
255 {
256  TimePoint beginTime{Clock::now()};
257 
258  ShimHeaderMessage shimHeader{beginTime, u16PacketId_++, id_};
259 
260  Serialization serialization{shimHeader.serialize()};
261 
262  // prepend mac header to outgoing packet
263  pkt.prepend(serialization.c_str(), serialization.size());
264 
265  // now prepend the serialization length
266  pkt.prependLengthPrefixFraming(serialization.size());
267 
269  DEBUG_LEVEL,
270  "SHIM %03hu TimingAnalysis::ShimLayer::%s",
271  id_,
272  __func__);
273 
274  sendDownstreamPacket(pkt, clone(msgs));
275 }
276 
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...
The Registrar interface provides access to all of the emulator registrars.
Definition: registrar.h:50
ShimLayer(NEMId id, PlatformServiceProvider *pPlatformService, RadioServiceProvider *pRadioServiceProvider)
virtual ConfigurationRegistrar & configurationRegistrar()=0
#define LOGGER_VERBOSE_LOGGING(logger, level, fmt, args...)
std::list< const ControlMessage * > ControlMessages
DECLARE_SHIM_LAYER(EMANE::Models::TimingAnalysis::ShimLayer)
void processDownstreamPacket(DownstreamPacket &pkt, const ControlMessages &msgs) override
std::uint16_t stripLengthPrefixFraming()
void sendDownstreamControl(const ControlMessages &msgs)
size_t strip(size_t size)
void prepend(const void *buf, size_t size)
The PlatformServiceProvider interface provides access to emulator services.
Interface used to create a Shim layer plugin implementation.
Definition: shimlayerimpl.h:47
Specialized packet the allows downstream processing to add layer specific headers as the packet trave...
void processUpstreamPacket(UpstreamPacket &pkt, const ControlMessages &msgs) override
std::chrono::duration< double > DoubleSeconds
Definition: types.h:47
std::uint16_t NEMId
Definition: types.h:52
PlatformServiceProvider * pPlatformService_
void configure(const ConfigurationUpdate &update) override
The RadioServiceProvider interface provides access to radio (RF) model specific services.
void sendUpstreamControl(const ControlMessages &msgs)
void processDownstreamControl(const ControlMessages &msgs) override
const void * get() const
virtual LogServiceProvider & logService()=0
Shim class that produces latency numbers from one Shim Layer to another.
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
Definition: types.h:50
void processUpstreamControl(const ControlMessages &msgs) override
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)