OverSim
I3LatencyStretch.cc
Go to the documentation of this file.
1 // Copyright (C) 2006 Institut fuer Telematik, Universitaet Karlsruhe (TH)
2 //
3 // This program is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU General Public License
5 // as published by the Free Software Foundation; either version 2
6 // of the License, or (at your option) any later version.
7 //
8 // This program is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 // GNU General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with this program; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16 //
17 
23 #include "I3BaseApp.h"
24 #include "I3.h"
25 
26 #define TRIGGER_TIMER 1234
27 
28 #define STRETCH_HELLO 12345
29 #define STRETCH_HELLOACK 12346
30 #define STRETCH_I3MSG 12347
31 #define STRETCH_IPMSG 12348
32 
33 #define USE_NO_SAMPLING 0
34 #define USE_QUERY_FLAG 1
35 #define USE_CLOSEST_ID 2
36 #define USE_SAMPLING (USE_QUERY_FLAG | USE_CLOSEST_ID)
37 
38 using namespace std;
39 
40 enum Stats {
45 };
46 
47 static cStdDev stats[NUM_STATS];
48 static bool statsDumped = false;
49 
50 struct NodeIdentity {
53 };
54 
55 struct LatencyInfo {
56  simtime_t i3Time;
57  simtime_t ipTime;
58 };
59 
60 struct MsgContent {
63  simtime_t creationTime;
64 };
65 
66 class I3LatencyStretch : public I3BaseApp {
72  cStdDev myStats[NUM_STATS];
73 
74  std::map<I3IPAddress, LatencyInfo> latencies;
75 
76 
77  void initializeApp(int stage);
78  void initializeI3();
79  void handleTimerEvent(cMessage *msg);
80  void handleUDPMessage(cMessage* msg);
81  void deliver(I3Trigger &trigger, I3IdentifierStack &stack, cPacket *msg);
82  void finish();
83 };
84 
86 
87 
89  statsDumped = false;
91 }
92 
94  recordScalar("Number of samples", myStats[STAT_RATIO].getCount());
95 
96  recordScalar("IP Min ", myStats[STAT_IP].getMin());
97  recordScalar("IP Max ", myStats[STAT_IP].getMax());
98  recordScalar("IP Mean ", myStats[STAT_IP].getMean());
99  recordScalar("IP Stdev", myStats[STAT_IP].getStddev());
100 
101  recordScalar("I3 Min ", myStats[STAT_I3].getMin());
102  recordScalar("I3 Max ", myStats[STAT_I3].getMax());
103  recordScalar("I3 Mean ", myStats[STAT_I3].getMean());
104  recordScalar("I3 Stdev", myStats[STAT_I3].getStddev());
105 
106  recordScalar("Ratio Min ", myStats[STAT_RATIO].getMin());
107  recordScalar("Ratio Max ", myStats[STAT_RATIO].getMax());
108  recordScalar("Ratio Mean ", myStats[STAT_RATIO].getMean());
109  recordScalar("Ratio Stdev", myStats[STAT_RATIO].getStddev());
110 
111  if (!statsDumped) {
112  statsDumped = true;
113  recordScalar("General Number of samples", stats[STAT_RATIO].getCount());
114 
115  recordScalar("General IP Min ", stats[STAT_IP].getMin());
116  recordScalar("General IP Max ", stats[STAT_IP].getMax());
117  recordScalar("General IP Mean ", stats[STAT_IP].getMean());
118  recordScalar("General IP Stdev", stats[STAT_IP].getStddev());
119  stats[STAT_IP].clearResult();
120 
121  recordScalar("General I3 Min ", stats[STAT_I3].getMin());
122  recordScalar("General I3 Max ", stats[STAT_I3].getMax());
123  recordScalar("General I3 Mean ", stats[STAT_I3].getMean());
124  recordScalar("General I3 Stdev", stats[STAT_I3].getStddev());
125  stats[STAT_I3].clearResult();
126 
127  recordScalar("General Ratio Min ", stats[STAT_RATIO].getMin());
128  recordScalar("General Ratio Max ", stats[STAT_RATIO].getMax());
129  recordScalar("General Ratio Mean ", stats[STAT_RATIO].getMean());
130  recordScalar("General Ratio Stdev", stats[STAT_RATIO].getStddev());
131  stats[STAT_RATIO].clearResult();
132  }
133 }
134 
136  foundPartner = false;
137  samplingType = par("useSampling");
138 
139  generalId.createFromHash("LatencyStretch");
140  generalId.setName("LatencyStretch");
141  generalId.createRandomSuffix();
142  insertTrigger(generalId);
143 
144  if (samplingType & USE_CLOSEST_ID) {
145  myId = retrieveClosestIdentifier();
146  } else {
147  myId.createRandomKey();
148  }
149  insertTrigger(myId);
150 
151  cMessage *msg = new cMessage();
152  msg->setKind(TRIGGER_TIMER);
153  scheduleAt(simTime() + 5, msg);
154 }
155 
157  if (msg->getContextPointer() != 0) {
158  MsgContent *mc = (MsgContent*)msg->getContextPointer();
159 
160  if (!latencies.count(mc->sourceIp)) opp_error("Unknown Id!");
161 
162  LatencyInfo &info = latencies[mc->sourceIp];
163 
164  info.ipTime = simTime() - mc->creationTime;
165  delete mc;
166  delete msg;
167  } else {
169  }
170 }
171 
172 void I3LatencyStretch::deliver(I3Trigger &trigger, I3IdentifierStack &stack, cPacket *msg)
173 {
174  if (msg->getKind() == STRETCH_HELLO) {
175  NodeIdentity *nid = (NodeIdentity*)msg->getContextPointer();
176  I3Identifier otherId = nid->id;
177 
178  latencies[nid->address] = LatencyInfo();
179  latencies[nid->address].i3Time = 0;
180  latencies[nid->address].ipTime = 0;
181 
182  msg->setKind(STRETCH_HELLOACK);
183  nid->id = myId;
184  nid->address = I3IPAddress(nodeIPAddress, par("clientPort"));
185  msg->setContextPointer(nid);
186  sendPacket(otherId, msg, samplingType & USE_QUERY_FLAG);
187 
188  } else if (msg->getKind() == STRETCH_HELLOACK) {
189 
190  NodeIdentity *nid = (NodeIdentity*)msg->getContextPointer();
191  partner = *nid;
192  foundPartner = true;
193  delete nid;
194  delete msg;
195 
196  } else if (msg->getKind() == STRETCH_I3MSG) {
197 
198  MsgContent *mc = (MsgContent*)msg->getContextPointer();
199 
200  if (!latencies.count(mc->sourceIp)) opp_error("Unknown Id!");
201 
202  LatencyInfo &info = latencies[ mc->sourceIp ];
203 
204  info.i3Time = simTime() - mc->creationTime;
205 
206  if (info.ipTime != 0) {
207  if (simTime() > 100) {
208  stats[STAT_IP].collect(info.ipTime);
209  stats[STAT_I3].collect(info.i3Time );
210  stats[STAT_RATIO].collect(info.i3Time / info.ipTime);
211 
212  myStats[STAT_IP].collect(info.ipTime);
213  myStats[STAT_I3].collect(info.i3Time );
214  myStats[STAT_RATIO].collect(info.i3Time / info.ipTime);
215  }
216  info.i3Time = 0;
217  info.ipTime = 0;
218  }
219 
220 
221  delete mc;
222  delete msg;
223  }
224 }
225 
227  if (msg->getKind() == TRIGGER_TIMER) {
228  if (!foundPartner) {
229  I3Identifier otherId;
230 
231  otherId.createFromHash("LatencyStretch");
232  otherId.createRandomSuffix();
233 
234  cPacket *hmsg = new cPacket();
235  NodeIdentity *nid = new NodeIdentity();
236 
237  nid->id = myId;
238  nid->address = I3IPAddress(nodeIPAddress, par("clientPort"));
239 
240  hmsg->setKind(STRETCH_HELLO);
241  hmsg->setContextPointer(nid);
242  sendPacket(otherId, hmsg, samplingType & USE_QUERY_FLAG);
243 
244  } else {
245  int length = (intrand(512) + 32) * 8;
246 
247  MsgContent *mc1 = new MsgContent();
248  mc1->creationTime = simTime();
249  mc1->sourceId = myId;
250  mc1->sourceIp = I3IPAddress(nodeIPAddress, par("clientPort"));
251 
252  cPacket *i3msg = new cPacket();
253  i3msg->setKind(STRETCH_I3MSG);
254  i3msg->setContextPointer(mc1);
255  i3msg->setBitLength(length);
256 
257  MsgContent *mc2 = new MsgContent(*mc1);
258  cPacket *ipmsg = new cPacket();
259  ipmsg->setKind(STRETCH_IPMSG);
260  ipmsg->setContextPointer(mc2);
261  ipmsg->setBitLength(length);
262 
263  sendPacket(partner.id, i3msg, samplingType & USE_QUERY_FLAG);
264  sendThroughUDP(ipmsg, partner.address);
265 
266  }
267 
268  scheduleAt(simTime() + truncnormal(15, 5), msg);
269 
270  }
271 }