OverSim
SimpleNodeEntry.cc
Go to the documentation of this file.
1 //
2 // Copyright (C) 2006 Institut fuer Telematik, Universitaet Karlsruhe (TH)
3 //
4 // This program is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU General Public License
6 // as published by the Free Software Foundation; either version 2
7 // of the License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 //
18 
24 #include <sstream>
25 #include <cassert>
26 
27 #include "SimpleNodeEntry.h"
28 #include "SimpleUDP.h"
29 #include "SimpleTCP.h"
30 #include "SHA1.h"
31 #include "OverlayKey.h"
32 #include "BinaryValue.h"
33 #include "IPAddressResolver.h"
34 
35 
36 uint8_t NodeRecord::dim;
37 
39 {
40  coords = new double[dim];
41 }
42 
44 {
45  delete[] coords;
46  coords = NULL;
47 }
48 
50 {
51  coords = new double[dim];
52  for (uint32_t i = 0; i < dim; ++i)
53  coords[i] = nodeRecord.coords[i];
54 }
55 
57 {
58  delete[] coords;
59  coords = new double[dim];
60  for (uint32_t i = 0; i < dim; ++i)
61  coords[i] = nodeRecord.coords[i];
62 
63  return *this;
64 }
65 
66 // beginning of behaviour code
68 {
69  const NodeRecord* temp = dynamic_cast<const NodeRecord*>(&rhs);
70 
71  if (this->getDim() != temp->getDim()) {
72  return false;
73  }
74 
75  bool ret = true;
76 
77  for (int i = 0; i < this->getDim(); i++) {
78  if (abs(this->coords[i] - temp->coords[i]) > 0.00000001){
79  ret = false;
80  }
81  }
82  return ret;
83 }
84 
85 // end of behaviour code
86 
88  cChannelType* typeRx,
89  cChannelType* typeTx,
90  uint32_t sendQueueLength,
91  uint32_t fieldSize)
92 {
93  assert(NodeRecord::dim == 2);
94 
95  nodeRecord = new NodeRecord;
96  index = -1;
97 
98  // use random values as coordinates
99  nodeRecord->coords[0] = uniform(0, fieldSize) - fieldSize / 2;
100  nodeRecord->coords[1] = uniform(0, fieldSize) - fieldSize / 2;
101 
102  SimpleNodeEntry(node, typeRx, typeTx, sendQueueLength, nodeRecord, index);
103 }
104 
106  cChannelType* typeRx,
107  cChannelType* typeTx,
108  uint32_t sendQueueLength,
109  NodeRecord* nodeRecord, int index)
110 {
111  cModule* udpModule = node->getSubmodule("udp");
112  UdpIPv4ingate = udpModule->gate("ipIn");
113  UdpIPv6ingate = udpModule->gate("ipv6In");
114  cModule* tcpModule = node->getSubmodule("tcp", 0);
115  if (tcpModule) {
116  TcpIPv4ingate = tcpModule->gate("ipIn");
117  TcpIPv6ingate = tcpModule->gate("ipv6In");
118  }
119 
120  this->nodeRecord = nodeRecord;
121  this->index = index;
122 
123  cDatarateChannel* tempRx = dynamic_cast<cDatarateChannel*>(typeRx->create("temp"));
124  cDatarateChannel* tempTx = dynamic_cast<cDatarateChannel*>(typeTx->create("temp"));
125 
126  rx.bandwidth = tempRx->par("datarate");
127  rx.errorRate = tempRx->par("ber");
128  rx.accessDelay = tempRx->par("delay");
129  rx.maxQueueTime = (sendQueueLength * 8.0) / rx.bandwidth;
130  rx.finished = 0;
131 
132  tx.bandwidth = tempTx->par("datarate");
133  tx.errorRate = tempTx->par("ber");
134  tx.accessDelay = tempTx->par("delay");
135  tx.maxQueueTime = (sendQueueLength * 8.0) / tx.bandwidth;
136  tx.finished = 0;
137 
138  delete tempRx;
139  delete tempTx;
140 }
141 
143 {
144  double sum_of_squares = 0;
145  for (uint32_t i = 0; i < nodeRecord->dim; i++) {
146  sum_of_squares += pow(nodeRecord->coords[i] -
147  entry.nodeRecord->coords[i], 2);
148  }
149  return sqrt(sum_of_squares);
150 }
151 
153  const SimpleNodeEntry& dest,
154  bool faultyDelay)
155 {
156  if ((pow(1 - tx.errorRate, msg->getByteLength() * 8) <= uniform(0, 1)) ||
157  (pow(1 - dest.rx.errorRate, msg->getByteLength() * 8) <= uniform(0, 1))) {
158  msg->setBitError(true);
159  }
160 
161  simtime_t now = simTime();
162  simtime_t bandwidthDelay = ((msg->getByteLength() * 8) / tx.bandwidth);
163  simtime_t newTxFinished = std::max(tx.finished, now) + bandwidthDelay;
164 
165  // send queue
166  if ((newTxFinished > now + tx.maxQueueTime) && (tx.maxQueueTime != 0)) {
167  EV << "[SimpleNodeEntry::calcDelay()]\n"
168  << " Send queue overrun"
169  << "\n newTxFinished = fmax(txFinished, now) + bandwidthDelay"
170  << "\n newTxFinished = " << newTxFinished
171  << "\n tx.finished = " << tx.finished
172  << "\n now = " << now
173  << "\n bandwidthDelay = " << bandwidthDelay
174  << "\n (newTxFinished > now + txMaxQueueTime) == true"
175  << "\n tx.maxQueueTime = " << tx.maxQueueTime
176  << endl;
177  return SimpleDelay(0, false);
178  }
179 
180  tx.finished = newTxFinished;
181 
182  simtime_t destBandwidthDelay = (msg->getByteLength() * 8) / dest.rx.bandwidth;
183  simtime_t coordDelay = 0.001 * (*this - dest);
184 
185  if (faultyDelay)
186  coordDelay = getFaultyDelay(coordDelay);
187 
188  return SimpleDelay(tx.finished - now
189  + tx.accessDelay
190  + coordDelay
191  + destBandwidthDelay + dest.rx.accessDelay, true);
192 }
193 
195 {
196  simtime_t now = simTime();
197  simtime_t bandwidthDelay = ((msg->getByteLength() * 8) / rx.bandwidth);
198  simtime_t newRxFinished = std::max(rx.finished + rx.accessDelay +
199  bandwidthDelay, now);
200 
201  // access router send queue
202  if ((newRxFinished > (now + rx.maxQueueTime)) && (rx.maxQueueTime != 0)) {
203  EV << "[SimpleNodeEntry::calcAccessRouterDelay()]\n"
204  << " Access router send queue overrun"
205  << "\n newRxFinished = fmax(rxFinished + accessDelay + bandwidthDelay, now)"
206  << "\n newRxFinished = " << newRxFinished
207  << "\n rx.finished = " << rx.finished
208  << "\n now = " << now
209  << "\n bandwidthDelay = " << bandwidthDelay
210  << "\n (newRxFinished > now + rxMaxQueueTime) == true"
211  << "\n rx.maxQueueTime = " << rx.maxQueueTime
212  << endl;
213  return SimpleDelay(0, false);
214  }
215 
216  rx.finished = newRxFinished;
217 
218  std::cout << "RouterDelay: " << rx.finished - now << std::endl;
219 
220  return SimpleDelay(rx.finished - now, true);
221 }
222 
223 
224 simtime_t SimpleNodeEntry::getFaultyDelay(simtime_t oldDelay) {
225 
226  // hash over string of oldDelay
227  char delaystring[35];
228  sprintf(delaystring, "%.30f", SIMTIME_DBL(oldDelay));
229 
230  CSHA1 sha1;
231  uint8_t hashOverDelays[20];
232  sha1.Reset();
233  sha1.Update((uint8_t*)delaystring, 32);
234  sha1.Final();
235  sha1.GetHash(hashOverDelays);
236 
237  // get the hash's first 4 bytes == 32 bits as one unsigned integer
238  unsigned int decimalhash = 0;
239  for (int i = 0; i < 4; i++) {
240  decimalhash += (unsigned int) hashOverDelays[i] * (2 << (8*(3 - i) - 1));
241  }
242 
243  // normalize decimal hash value onto 0..1 (decimal number / 2^32-1)
244  double fraction = (double) decimalhash / (unsigned int) ((2 << 31) - 1);
245 
246  // flip a coin if faulty rtt is larger or smaller
247  char sign = (decimalhash % 2 == 0) ? 1 : -1;
248 
249  // get the error ratio according to the distributions in
250  // "Network Coordinates in the Wild", Figure 7
251  double errorRatio = 0;
254  // Kumaraswamy, a=2.03, b=14, moved by 0.04 to the right
255  errorRatio = pow((1.0 - pow(fraction, 1.0/14.0)), 1.0/2.03) + 0.04;
256  break;
257 
259  // Kumaraswamy, a=1.95, b=50, moved by 0.105 to the right
260  errorRatio = pow((1.0 - pow(fraction, 1.0/50.0)), 1.0/1.95) + 0.105;
261  break;
262 
264  // Kumaraswamy, a=1.96, b=23, moved by 0.02 to the right
265  errorRatio = pow((1.0 - pow(fraction, 1.0/23.0)), 1.0/1.96) + 0.02;
266  std::cout << "ErrorRatio: " << errorRatio << std::endl;
267  break;
268 
269  default:
270  break;
271  }
272  /*
273  std::cout << "decimalhash: " << decimalhash << " -- fraction: " << fraction << " -- errorRatio: " << errorRatio << std::endl;
274  std::cout << SimpleUDP::delayFaultTypeString << " -- " << "old: " << oldDelay << " -- new: " << oldDelay + sign * errorRatio * oldDelay << std::endl;
275  */
276 
277  // If faulty rtt is smaller, set errorRatio to max 0.6
278  //errorRatio = (sign == -1 && errorRatio > 0.6) ? 0.6 : errorRatio;
279 
280  errorRatio = (errorRatio > 0.6) ? 0.6 : errorRatio;
281 
282  return (oldDelay + sign * errorRatio * oldDelay); // * 0.789; //TODO
283 }
284 
285 std::string SimpleNodeEntry::info() const
286 {
287  std::ostringstream str;
288  str << *this;
289  return str.str();
290 }
291 
292 std::ostream& operator<<(std::ostream& out, const SimpleNodeEntry& entry)
293 {
294  out << "(";
295  for (uint8_t i = 0; i < NodeRecord::dim; i++) {
296  out << "dim" << i <<": " << entry.nodeRecord->coords[i];
297  out << ", ";
298  }
299  // out << ", y:" << entry.nodeRecord->coords[1]
300  out << ")\n[rx]"
301  << "\nbandwidth = " << entry.rx.bandwidth
302  << ",\ndelay = " << entry.rx.accessDelay
303  << ",\nerrorRate = " << entry.rx.errorRate
304  << ",\ntxMaxQueueTime = " << entry.rx.maxQueueTime
305  << ",\ntxFinished = " << entry.rx.finished;
306  out << "\n[tx]"
307  << "\nbandwidth = " << entry.tx.bandwidth
308  << ",\ndelay = " << entry.tx.accessDelay
309  << ",\nerrorRate = " << entry.tx.errorRate
310  << ",\ntxMaxQueueTime = " << entry.tx.maxQueueTime
311  << ",\ntxFinished = " << entry.tx.finished;
312 
313  return out;
314 }