NetEmuPerf.cc
Go to the documentation of this file.
1 //
2 // Copyright (c) 2020 Fraunhofer Institute for Applied Information Technology (FIT)
3 // Network Research Group (NET)
4 // Schloss Birlinghoven, 53754 Sankt Augustin, GERMANY
5 // Contact: support@wiback.org
6 //
7 // This file is part of the SENF code tree.
8 // It is licensed under the 3-clause BSD License (aka New BSD License).
9 // See LICENSE.txt in the top level directory for details or visit
10 // https://opensource.org/licenses/BSD-3-Clause
11 //
12 
13 
17 //#include "main.hh"
18 //#include "main.ih"
19 
20 // Custom includes
21 #include <boost/lexical_cast.hpp>
22 #include <iostream>
23 #include <senf/PPI.hh>
34 #include <senf/Utils/Logger.hh>
35 #include <senf/Utils/Console.hh>
36 
37 #include "Configuration.hh"
38 #include "Interfaces.hh"
39 #include "Rx.hh"
40 #include "Tx.hh"
41 
42 //#include "main.mpp"
43 #define prefix_
44 
46 namespace module = senf::ppi::module;
48 namespace ppi = senf::ppi;
49 namespace emu = senf::emu;
50 
51 namespace {
52 
53  template <class Interface>
54  class App : public module::Module
55  {
56  SENF_PPI_MODULE(App);
57  public:
58  typedef typename OurDecoration::template apply<Interface>::type DecoInterface;
59  DecoInterface iface;
60 
68 
69  App(Configuration const & config)
70  : iface (config.iface),
71  timer_("APP", senf::membind(&App::timerEvent, this), senf::ClockService::clock_type(0), false),
72  startTime(senf::scheduler::now()),
73  duration_(config.duration),
74  period(config.reportingInterval),
75  nextTime(startTime + period),
76  sigint (SIGINT, boost::bind(&App::terminate, this)),
77  sigterm (SIGTERM, boost::bind(&App::terminate, this))
78  {
79  iface.interface().maxBurst(config.maxBurst);
80  iface.interface().qlen(config.qlen);
81  iface.interface().sndBuf(config.txBuf);
82  iface.interface().enable();
83 
84  timer_.timeout(nextTime);
85  }
86 
87  virtual void v_stats(senf::ClockService::clock_type const & tstamp, senf::ClockService::clock_type const & period) = 0;
88 
89  void timerEvent()
90  {
91  if (duration_ and (senf::scheduler::now() - startTime) >= duration_){
92  terminate();
93  }
94 
95  v_stats(nextTime - startTime, period);
96  nextTime += period;
97  timer_.timeout(nextTime);
98  };
99 
100  void terminate()
101  {
103  }
104  };
105 
106  template <class Interface>
107  class AppRx : public App<Interface>
108  {
109  public:
110  Receiver receiver;
111 
112  AppRx(Configuration const & config)
113  : App<Interface> (config),
114  receiver(config.peer, App<Interface>::iface.interface().id())
115  {
116  ppi::connect(App<Interface>::iface, receiver);
117 
118  WLANInterface *wif (dynamic_cast<WLANInterface*>(&App<Interface>::iface.interface()));
119  if (wif) {
120  wif->join(config.frequency, config.ht40 ? 40 : 20, 4711u);
121  }
122 
123  std::cerr << "Receiver ready on " << config.iface << ", mac " << App<Interface>::iface.interface().id() << ", peer " << config.peer << std::endl;
124  }
125 
126  void v_stats(senf::ClockService::clock_type const & tstamp, senf::ClockService::clock_type const & period) {
127  std::cout << senf::ClockService::in_seconds(tstamp) << '.' << std::setw(3) << std::setfill('0') << (senf::ClockService::in_milliseconds(tstamp) % 1000);
128  std::cout << " queue-drops " << App<Interface>::iface.interface().rxQueueDropped() << "; ";
129  receiver.report(std::cout, period);
130  receiver.clear();
131  std::cout << std::endl;
132  }
133  };
134 
135  template <class Interface>
136  class AppTx : public App<Interface>
137  {
138  public:
139  Sender sender;
140 
141  AppTx(Configuration const & config)
142  : App<Interface> (config),
143  sender(App<Interface>::iface.interface().id(), config.peer, config.label)
144  {
145  ppi::connect(sender, App<Interface>::iface);
146 
147  WLANInterface *wif (dynamic_cast<WLANInterface*>(&App<Interface>::iface.interface()));
148  if (wif) {
149  wif->join(config.frequency, config.ht40 ? 40 : 20, 4711u);
150  }
151 
152  sender.bitrate(config.bitrate);
153 
154  std::cerr << "Transmitter ready on " << config.iface << ", mac " << App<Interface>::iface.interface().id()
155  << ", peer " << config.peer << ", label " << config.label << ", bitrate " << config.bitrate << "kbps" << std::endl;
156  }
157 
158  void v_stats(senf::ClockService::clock_type const & tstamp, senf::ClockService::clock_type const & period) {
159  std::cout << senf::ClockService::in_seconds(tstamp) << '.' << std::setw(3) << std::setfill('0') << (senf::ClockService::in_milliseconds(tstamp) % 1000);
160  std::cout << " seqNo " << sender.seqNo;
161  WLANInterface *wif (dynamic_cast<WLANInterface*>(&App<Interface>::iface.interface()));
162  if (wif) {
163  std::cout << ", mmStats ";
164  wif->dumpMmapStats(std::cout);
165  }
166  EthernetInterface *eif (dynamic_cast<EthernetInterface*>(&App<Interface>::iface.interface()));
167  if (eif) {
168  std::cout << ", mmStats ";
169  eif->dumpMmapStats(std::cout);
170  }
171  std::cout << std::endl;
172  }
173  };
174 
175  template <class Application>
176  void run(Configuration const & config)
177  {
178  Application app (config);
179  ppi::run();
180  }
181 }
182 
183 int main(int argc, const char ** argv)
184 {
186 
187  Configuration config;
188 
189  if (!config.parse( argc, argv)) {
190  exit(1);
191  }
192 
193  // enable console for (remote) logging
194  if (config.consolePort > 0) {
196  }
197 
198  if (config.iface.find("phy") == 0){
199  if (config.bitrate == 0)
200  run< AppRx<WLANInterface> >(config);
201  else
202  run< AppTx<WLANInterface> >(config);
203  }
204  else {
205  if (config.bitrate == 0)
206  run< AppRx<EthernetInterface>>(config);
207  else
208  run< AppTx<EthernetInterface> >(config);
209  }
210 
211  return 0;
212 }
213 
215 #undef prefix_
216 //#include "main.mpp"
217 
218 
219 // Local Variables:
220 // mode: c++
221 // indent-tabs-mode: nil
222 // End:
senf::ClockService::clock_type duration
config::time_type clock_type
static Server & start(senf::INet4SocketAddress const &address)
main non-inline non-template implementation
static SENF_CLOCKSERVICE_CONSTEXPR int64_type in_milliseconds(clock_type const &v)
static void logToStderr()
WirelessExtController public header.
int main(int argc, const char **argv)
Definition: NetEmuPerf.cc:183
u8 type
virtual void terminate() const
unsigned maxBurst
boost::function< R(Args)> membind(R(T::*fn)(Args), T *ob)
main non-inline non-template implementation
unsigned frequency
static INet4Address const None
unsigned txBuf
void timeout(ClockService::clock_type const &timeout, bool initiallyEnabled=true)
int run(int argc, char const *argv[])
Definition: dfstest.cc:83
unsigned label
senf::ClockService::clock_type reportingInterval
unsigned consolePort
#define SENF_PPI_MODULE(name)
bool parse(int argc, char const *argv[])
unsigned bitrate
static SENF_CLOCKSERVICE_CONSTEXPR int64_type in_seconds(clock_type const &v)
senf::MACAddress peer
HardwareEthernetInterface public header.
std::string iface
HardwareWLANInterface public header.
main non-inline non-template implementation