SimpleNodeEntry.cc

Go to the documentation of this file.
00001 //
00002 // Copyright (C) 2006 Institut fuer Telematik, Universitaet Karlsruhe (TH)
00003 //
00004 // This program is free software; you can redistribute it and/or
00005 // modify it under the terms of the GNU General Public License
00006 // as published by the Free Software Foundation; either version 2
00007 // of the License, or (at your option) any later version.
00008 //
00009 // This program is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 // GNU General Public License for more details.
00013 //
00014 // You should have received a copy of the GNU General Public License
00015 // along with this program; if not, write to the Free Software
00016 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00017 //
00018 
00024 #include <sstream>
00025 #include <cassert>
00026 
00027 #include "SimpleNodeEntry.h"
00028 #include "SimpleUDP.h"
00029 #include "SimpleTCP.h"
00030 #include "SHA1.h"
00031 #include "OverlayKey.h"
00032 #include "BinaryValue.h"
00033 #include "IPAddressResolver.h"
00034 
00035 
00036 uint8_t NodeRecord::dim;
00037 
00038 NodeRecord::NodeRecord()
00039 {
00040     coords = new double[dim];
00041 }
00042 
00043 NodeRecord::~NodeRecord()
00044 {
00045     delete[] coords;
00046     coords = NULL;
00047 }
00048 
00049 NodeRecord::NodeRecord(const NodeRecord& nodeRecord)
00050 {
00051     coords = new double[dim];
00052     for (uint32_t i = 0; i < dim; ++i)
00053         coords[i] = nodeRecord.coords[i];
00054 }
00055 
00056 NodeRecord& NodeRecord::operator=(const NodeRecord& nodeRecord)
00057 {
00058     delete[] coords;
00059     coords = new double[dim];
00060     for (uint32_t i = 0; i < dim; ++i)
00061         coords[i] = nodeRecord.coords[i];
00062 
00063     return *this;
00064 }
00065 
00066 SimpleNodeEntry::SimpleNodeEntry(cModule* node,
00067                                  cChannelType* typeRx,
00068                                  cChannelType* typeTx,
00069                                  uint32_t sendQueueLength,
00070                                  uint32_t fieldSize)
00071 {
00072     assert(NodeRecord::dim == 2);
00073     cModule* udpModule = node->getSubmodule("udp");
00074     UdpIPv4ingate = udpModule->gate("ipIn");
00075     UdpIPv6ingate = udpModule->gate("ipv6In");
00076     cModule* tcpModule = node->getSubmodule("tcp", 0);
00077     if (tcpModule) {
00078         TcpIPv4ingate = tcpModule->gate("ipIn");
00079         TcpIPv6ingate = tcpModule->gate("ipv6In");
00080     }
00081 
00082     nodeRecord = new NodeRecord;
00083     index = -1;
00084 
00085     //use random values as coordinates
00086     nodeRecord->coords[0] = uniform(0, fieldSize) - fieldSize / 2;
00087     nodeRecord->coords[1] = uniform(0, fieldSize) - fieldSize / 2;
00088 
00089     cDatarateChannel* tempRx = dynamic_cast<cDatarateChannel*>(typeRx->create("temp"));
00090     cDatarateChannel* tempTx = dynamic_cast<cDatarateChannel*>(typeTx->create("temp"));
00091 
00092     rx.bandwidth = tempRx->par("datarate");
00093     rx.errorRate = tempRx->par("ber");
00094     rx.accessDelay = tempRx->par("delay");
00095     rx.maxQueueTime = 0;
00096     rx.finished = simTime();
00097 
00098     tx.bandwidth = tempTx->par("datarate");
00099     tx.errorRate = tempTx->par("ber");
00100     tx.accessDelay = tempTx->par("delay");
00101     tx.maxQueueTime = (sendQueueLength * 8.) / tx.bandwidth;
00102     tx.finished = simTime();
00103 
00104     delete tempRx;
00105     delete tempTx;
00106 }
00107 
00108 SimpleNodeEntry::SimpleNodeEntry(cModule* node,
00109                                  cChannelType* typeRx,
00110                                  cChannelType* typeTx,
00111                                  uint32_t sendQueueLength,
00112                                  NodeRecord* nodeRecord, int index)
00113 {
00114     cModule* udpModule = node->getSubmodule("udp");
00115     UdpIPv4ingate = udpModule->gate("ipIn");
00116     UdpIPv6ingate = udpModule->gate("ipv6In");
00117     cModule* tcpModule = node->getSubmodule("tcp", 0);
00118     if (tcpModule) {
00119         TcpIPv4ingate = tcpModule->gate("ipIn");
00120         TcpIPv6ingate = tcpModule->gate("ipv6In");
00121     }
00122 
00123     this->nodeRecord = nodeRecord;
00124     this->index = index;
00125 
00126     cDatarateChannel* tempRx = dynamic_cast<cDatarateChannel*>(typeRx->create("temp"));
00127     cDatarateChannel* tempTx = dynamic_cast<cDatarateChannel*>(typeTx->create("temp"));
00128 
00129     rx.bandwidth = tempRx->par("datarate");
00130     rx.errorRate = tempRx->par("ber");
00131     rx.accessDelay = tempRx->par("delay");
00132     rx.maxQueueTime = 0;
00133     rx.finished = simTime();
00134 
00135     tx.bandwidth = tempTx->par("datarate");
00136     tx.errorRate = tempTx->par("ber");
00137     tx.accessDelay = tempTx->par("delay");
00138     tx.maxQueueTime = (sendQueueLength * 8.) / tx.bandwidth;
00139     tx.finished = simTime();
00140 
00141     delete tempRx;
00142     delete tempTx;
00143 }
00144 
00145 float SimpleNodeEntry::operator-(const SimpleNodeEntry& entry) const
00146 {
00147     double sum_of_squares = 0;
00148     for (uint32_t i = 0; i < nodeRecord->dim; i++) {
00149         sum_of_squares += pow(nodeRecord->coords[i] -
00150                               entry.nodeRecord->coords[i], 2);
00151     }
00152     return sqrt(sum_of_squares);
00153 }
00154 
00155 SimpleNodeEntry::SimpleDelay SimpleNodeEntry::calcDelay(cPacket* msg,
00156                                                         const SimpleNodeEntry& dest,
00157                                                         bool faultyDelay)
00158 {
00159     if ((pow(1 - tx.errorRate, msg->getByteLength() * 8) <= uniform(0, 1)) ||
00160         (pow(1 - dest.rx.errorRate, msg->getByteLength() * 8) <= uniform(0, 1))) {
00161         msg->setBitError(true);
00162     }
00163 
00164     simtime_t now = simTime();
00165     simtime_t bandwidthDelay= ((msg->getByteLength() * 8) / tx.bandwidth);
00166     simtime_t newTxFinished = std::max(tx.finished, now) + bandwidthDelay;
00167 
00168     // send queue
00169     if ((newTxFinished > now + tx.maxQueueTime) && (tx.maxQueueTime != 0)) {
00170         EV << "[SimpleNodeEntry::calcDelay()]\n"
00171            << "    Send queue overrun"
00172            << "\n    newTxFinished = fmax(txFinished, now) + bandwidthDelay"
00173            << "\n    newTxFinished = " << newTxFinished
00174            << "\n    tx.finished = " << tx.finished
00175            << "\n    now = " << now
00176            << "\n    bandwidthDelay = " << bandwidthDelay
00177            << "\n    (newTxFinished > now + txMaxQueueTime) == true"
00178            << "\n    tx.maxQueueTime = " << tx.maxQueueTime
00179            << endl;
00180         return SimpleDelay(0, false);
00181     }
00182 
00183     tx.finished = newTxFinished;
00184 
00185     simtime_t destBandwidthDelay = (msg->getByteLength() * 8) / dest.rx.bandwidth;
00186     simtime_t coordDelay = 0.001 * (*this - dest);
00187 
00188     if (faultyDelay)
00189         coordDelay = getFaultyDelay(coordDelay);
00190 
00191     return SimpleDelay(tx.finished - now
00192                        + tx.accessDelay
00193                        + coordDelay
00194                        + destBandwidthDelay + dest.rx.accessDelay, true);
00195 }
00196 
00197 simtime_t SimpleNodeEntry::getFaultyDelay(simtime_t oldDelay) {
00198 
00199     // hash over string of oldDelay
00200     char delaystring[35];
00201     sprintf(delaystring, "%.30f", SIMTIME_DBL(oldDelay));
00202 
00203     CSHA1 sha1;
00204     uint8_t hashOverDelays[20];
00205     sha1.Reset();
00206     sha1.Update((uint8_t*)delaystring, 32);
00207     sha1.Final();
00208     sha1.GetHash(hashOverDelays);
00209 
00210     // get the hash's first 4 bytes == 32 bits as one unsigned integer
00211     unsigned int decimalhash = 0;
00212     for (int i = 0; i < 4; i++) {
00213         decimalhash += (unsigned int) hashOverDelays[i] * (2 << (8*(3 - i) - 1));
00214     }
00215 
00216     // normalize decimal hash value onto 0..1 (decimal number / 2^32-1)
00217     double fraction = (double) decimalhash / (unsigned int) ((2 << 31) - 1);
00218 
00219     // flip a coin if faulty rtt is larger or smaller
00220     char sign = (decimalhash % 2 == 0) ? 1 : -1;
00221 
00222     // get the error ratio according to the distributions in
00223     // "Network Coordinates in the Wild", Figure 7
00224     double errorRatio = 0;
00225     switch (SimpleUDP::delayFaultTypeMap[SimpleUDP::delayFaultTypeString]) {
00226         case SimpleUDP::delayFaultLiveAll:
00227             // Kumaraswamy, a=2.03, b=14, moved by 0.04 to the right
00228             errorRatio = pow((1.0 - pow(fraction, 1.0/14.0)), 1.0/2.03) + 0.04;
00229             break;
00230 
00231         case SimpleUDP::delayFaultLivePlanetlab:
00232             // Kumaraswamy, a=1.95, b=50, moved by 0.105 to the right
00233             errorRatio = pow((1.0 - pow(fraction, 1.0/50.0)), 1.0/1.95) + 0.105;
00234             break;
00235 
00236         case SimpleUDP::delayFaultSimulation:
00237             // Kumaraswamy, a=1.96, b=23, moved by 0.02 to the right
00238             errorRatio = pow((1.0 - pow(fraction, 1.0/23.0)), 1.0/1.96) + 0.02;
00239             std::cout << "ErrorRatio: " << errorRatio << std::endl;
00240             break;
00241 
00242         default:
00243             break;
00244     }
00245     /*
00246     std::cout << "decimalhash: " << decimalhash << " -- fraction: " << fraction << " -- errorRatio: " << errorRatio << std::endl;
00247     std::cout << SimpleUDP::delayFaultTypeString << " -- " << "old: " << oldDelay << " -- new: " << oldDelay + sign * errorRatio * oldDelay << std::endl;
00248     */
00249 
00250     // If faulty rtt is smaller, set errorRatio to max 0.6
00251     errorRatio = (sign == -1 && errorRatio > 0.6) ? 0.6 : errorRatio;
00252 
00253     return oldDelay + sign * errorRatio * oldDelay;
00254 }
00255 
00256 std::string SimpleNodeEntry::info() const
00257 {
00258     std::ostringstream str;
00259     str << *this;
00260     return str.str();
00261 }
00262 
00263 std::ostream& operator<<(std::ostream& out, const SimpleNodeEntry& entry)
00264 {
00265     out << "(";
00266     for (uint8_t i = 0; i < NodeRecord::dim; i++) {
00267         out << "dim" << i <<": " << entry.nodeRecord->coords[i];
00268         out << ", ";
00269     }
00270     // out << ", y:" << entry.nodeRecord->coords[1]
00271     out << ")\n[rx]"
00272         << "\nbandwidth = " << entry.rx.bandwidth
00273         << ",\ndelay = " << entry.rx.accessDelay
00274         << ",\nerrorRate = " << entry.rx.errorRate
00275         << ",\ntxMaxQueueTime = " << entry.rx.maxQueueTime
00276         << ",\ntxFinished = " << entry.rx.finished;
00277     out << "\n[tx]"
00278         << "\nbandwidth = " << entry.tx.bandwidth
00279         << ",\ndelay = " << entry.tx.accessDelay
00280         << ",\nerrorRate = " << entry.tx.errorRate
00281         << ",\ntxMaxQueueTime = " << entry.tx.maxQueueTime
00282         << ",\ntxFinished = " << entry.tx.finished;
00283 
00284     return out;
00285 }