00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00023 #include "I3BaseApp.h"
00024 #include "I3.h"
00025
00026 #define TRIGGER_TIMER 1234
00027
00028 #define STRETCH_HELLO 12345
00029 #define STRETCH_HELLOACK 12346
00030 #define STRETCH_I3MSG 12347
00031 #define STRETCH_IPMSG 12348
00032
00033 #define USE_NO_SAMPLING 0
00034 #define USE_QUERY_FLAG 1
00035 #define USE_CLOSEST_ID 2
00036 #define USE_SAMPLING (USE_QUERY_FLAG | USE_CLOSEST_ID)
00037
00038 using namespace std;
00039
00040 enum Stats {
00041 STAT_IP,
00042 STAT_I3,
00043 STAT_RATIO,
00044 NUM_STATS
00045 };
00046
00047 static cStdDev stats[NUM_STATS];
00048 static bool statsDumped = false;
00049
00050 struct NodeIdentity {
00051 I3Identifier id;
00052 I3IPAddress address;
00053 };
00054
00055 struct LatencyInfo {
00056 simtime_t i3Time;
00057 simtime_t ipTime;
00058 };
00059
00060 struct MsgContent {
00061 I3Identifier sourceId;
00062 I3IPAddress sourceIp;
00063 simtime_t creationTime;
00064 };
00065
00066 class I3LatencyStretch : public I3BaseApp {
00067 int samplingType;
00068 I3Identifier generalId;
00069 I3Identifier myId;
00070 NodeIdentity partner;
00071 bool foundPartner;
00072 cStdDev myStats[NUM_STATS];
00073
00074 std::map<I3IPAddress, LatencyInfo> latencies;
00075
00076
00077 void initializeApp(int stage);
00078 void initializeI3();
00079 void handleTimerEvent(cMessage *msg);
00080 void handleUDPMessage(cMessage* msg);
00081 void deliver(I3Trigger &trigger, I3IdentifierStack &stack, cPacket *msg);
00082 void finish();
00083 };
00084
00085 Define_Module(I3LatencyStretch);
00086
00087
00088 void I3LatencyStretch::initializeApp(int stage) {
00089 statsDumped = false;
00090 I3BaseApp::initializeApp(stage);
00091 }
00092
00093 void I3LatencyStretch::finish() {
00094 recordScalar("Number of samples", myStats[STAT_RATIO].getCount());
00095
00096 recordScalar("IP Min ", myStats[STAT_IP].getMin());
00097 recordScalar("IP Max ", myStats[STAT_IP].getMax());
00098 recordScalar("IP Mean ", myStats[STAT_IP].getMean());
00099 recordScalar("IP Stdev", myStats[STAT_IP].getStddev());
00100
00101 recordScalar("I3 Min ", myStats[STAT_I3].getMin());
00102 recordScalar("I3 Max ", myStats[STAT_I3].getMax());
00103 recordScalar("I3 Mean ", myStats[STAT_I3].getMean());
00104 recordScalar("I3 Stdev", myStats[STAT_I3].getStddev());
00105
00106 recordScalar("Ratio Min ", myStats[STAT_RATIO].getMin());
00107 recordScalar("Ratio Max ", myStats[STAT_RATIO].getMax());
00108 recordScalar("Ratio Mean ", myStats[STAT_RATIO].getMean());
00109 recordScalar("Ratio Stdev", myStats[STAT_RATIO].getStddev());
00110
00111 if (!statsDumped) {
00112 statsDumped = true;
00113 recordScalar("General Number of samples", stats[STAT_RATIO].getCount());
00114
00115 recordScalar("General IP Min ", stats[STAT_IP].getMin());
00116 recordScalar("General IP Max ", stats[STAT_IP].getMax());
00117 recordScalar("General IP Mean ", stats[STAT_IP].getMean());
00118 recordScalar("General IP Stdev", stats[STAT_IP].getStddev());
00119 stats[STAT_IP].clearResult();
00120
00121 recordScalar("General I3 Min ", stats[STAT_I3].getMin());
00122 recordScalar("General I3 Max ", stats[STAT_I3].getMax());
00123 recordScalar("General I3 Mean ", stats[STAT_I3].getMean());
00124 recordScalar("General I3 Stdev", stats[STAT_I3].getStddev());
00125 stats[STAT_I3].clearResult();
00126
00127 recordScalar("General Ratio Min ", stats[STAT_RATIO].getMin());
00128 recordScalar("General Ratio Max ", stats[STAT_RATIO].getMax());
00129 recordScalar("General Ratio Mean ", stats[STAT_RATIO].getMean());
00130 recordScalar("General Ratio Stdev", stats[STAT_RATIO].getStddev());
00131 stats[STAT_RATIO].clearResult();
00132 }
00133 }
00134
00135 void I3LatencyStretch::initializeI3() {
00136 foundPartner = false;
00137 samplingType = par("useSampling");
00138
00139 generalId.createFromHash("LatencyStretch");
00140 generalId.setName("LatencyStretch");
00141 generalId.createRandomSuffix();
00142 insertTrigger(generalId);
00143
00144 if (samplingType & USE_CLOSEST_ID) {
00145 myId = retrieveClosestIdentifier();
00146 } else {
00147 myId.createRandomKey();
00148 }
00149 insertTrigger(myId);
00150
00151 cMessage *msg = new cMessage();
00152 msg->setKind(TRIGGER_TIMER);
00153 scheduleAt(simTime() + 5, msg);
00154 }
00155
00156 void I3LatencyStretch::handleUDPMessage(cMessage *msg) {
00157 if (msg->getContextPointer() != 0) {
00158 MsgContent *mc = (MsgContent*)msg->getContextPointer();
00159
00160 if (!latencies.count(mc->sourceIp)) opp_error("Unknown Id!");
00161
00162 LatencyInfo &info = latencies[mc->sourceIp];
00163
00164 info.ipTime = simTime() - mc->creationTime;
00165 delete mc;
00166 delete msg;
00167 } else {
00168 I3BaseApp::handleUDPMessage(msg);
00169 }
00170 }
00171
00172 void I3LatencyStretch::deliver(I3Trigger &trigger, I3IdentifierStack &stack, cPacket *msg)
00173 {
00174 if (msg->getKind() == STRETCH_HELLO) {
00175 NodeIdentity *nid = (NodeIdentity*)msg->getContextPointer();
00176 I3Identifier otherId = nid->id;
00177
00178 latencies[nid->address] = LatencyInfo();
00179 latencies[nid->address].i3Time = 0;
00180 latencies[nid->address].ipTime = 0;
00181
00182 msg->setKind(STRETCH_HELLOACK);
00183 nid->id = myId;
00184 nid->address = I3IPAddress(nodeIPAddress, par("clientPort"));
00185 msg->setContextPointer(nid);
00186 sendPacket(otherId, msg, samplingType & USE_QUERY_FLAG);
00187
00188 } else if (msg->getKind() == STRETCH_HELLOACK) {
00189
00190 NodeIdentity *nid = (NodeIdentity*)msg->getContextPointer();
00191 partner = *nid;
00192 foundPartner = true;
00193 delete nid;
00194 delete msg;
00195
00196 } else if (msg->getKind() == STRETCH_I3MSG) {
00197
00198 MsgContent *mc = (MsgContent*)msg->getContextPointer();
00199
00200 if (!latencies.count(mc->sourceIp)) opp_error("Unknown Id!");
00201
00202 LatencyInfo &info = latencies[ mc->sourceIp ];
00203
00204 info.i3Time = simTime() - mc->creationTime;
00205
00206 if (info.ipTime != 0) {
00207 if (simTime() > 100) {
00208 stats[STAT_IP].collect(info.ipTime);
00209 stats[STAT_I3].collect(info.i3Time );
00210 stats[STAT_RATIO].collect(info.i3Time / info.ipTime);
00211
00212 myStats[STAT_IP].collect(info.ipTime);
00213 myStats[STAT_I3].collect(info.i3Time );
00214 myStats[STAT_RATIO].collect(info.i3Time / info.ipTime);
00215 }
00216 info.i3Time = 0;
00217 info.ipTime = 0;
00218 }
00219
00220
00221 delete mc;
00222 delete msg;
00223 }
00224 }
00225
00226 void I3LatencyStretch::handleTimerEvent(cMessage *msg) {
00227 if (msg->getKind() == TRIGGER_TIMER) {
00228 if (!foundPartner) {
00229 I3Identifier otherId;
00230
00231 otherId.createFromHash("LatencyStretch");
00232 otherId.createRandomSuffix();
00233
00234 cPacket *hmsg = new cPacket();
00235 NodeIdentity *nid = new NodeIdentity();
00236
00237 nid->id = myId;
00238 nid->address = I3IPAddress(nodeIPAddress, par("clientPort"));
00239
00240 hmsg->setKind(STRETCH_HELLO);
00241 hmsg->setContextPointer(nid);
00242 sendPacket(otherId, hmsg, samplingType & USE_QUERY_FLAG);
00243
00244 } else {
00245 int length = (intrand(512) + 32) * 8;
00246
00247 MsgContent *mc1 = new MsgContent();
00248 mc1->creationTime = simTime();
00249 mc1->sourceId = myId;
00250 mc1->sourceIp = I3IPAddress(nodeIPAddress, par("clientPort"));
00251
00252 cPacket *i3msg = new cPacket();
00253 i3msg->setKind(STRETCH_I3MSG);
00254 i3msg->setContextPointer(mc1);
00255 i3msg->setBitLength(length);
00256
00257 MsgContent *mc2 = new MsgContent(*mc1);
00258 cPacket *ipmsg = new cPacket();
00259 ipmsg->setKind(STRETCH_IPMSG);
00260 ipmsg->setContextPointer(mc2);
00261 ipmsg->setBitLength(length);
00262
00263 sendPacket(partner.id, i3msg, samplingType & USE_QUERY_FLAG);
00264 sendThroughUDP(ipmsg, partner.address);
00265
00266 }
00267
00268 scheduleAt(simTime() + truncnormal(15, 5), msg);
00269
00270 }
00271 }