-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathRouting.cc
More file actions
298 lines (259 loc) · 10.5 KB
/
Copy pathRouting.cc
File metadata and controls
298 lines (259 loc) · 10.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
// SDN Control Traffic Simulator: simulate control traffic throughput
// and latencies in a variety of topologies
// Copyright (C) 2020 Ananya Gopal, Jesse Chen
// This program is free software: you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
// You should have received a copy of the
// GNU General Public License along with this program.
// If not, see <https://www.gnu.org/licenses/>.
#include "Routing.h"
#include "App.h"
Define_Module(Routing);
/*
* In the Topology, the IDs are dynamic, so we
* first populate the Controller ID.
*/
int Routing::getControllerID() {
cModule *network = cSimulation::getActiveSimulation()->getSystemModule();
for (SubmoduleIterator it(network); !it.end(); ++it) {
cModule * mod = *it;
if (!strcmp(mod->getName(), "controller")) {
return (mod->getId());
}
}
return (0);
}
/*
* We store the Thruput src files as
* leaf_spine_xxxx
* fat_tree_xxxxxx
* tree_xxxxxxxxxx
* bus_star_xxxxxx
*/
std::string Routing::getTopoString (int topo_type) {
std::string ret;
switch (topo_type){
case 0:
ret = "leaf_spine";
break;
case 1:
ret = "fat_tree";
break;
case 2:
ret = "tree";
break;
case 3:
ret = "bus_star";
break;
}
return (ret);
}
/*
* One of the Utility functions to read throughput source files
* This function creates a dynamic string for the thruput file.
*/
std::string Routing::getFileName(int topo_type, int flows, bool from_ctrl) {
std::string file_location = "/home/ananya/Documents/ThruputSrcFiles/10Gbps/Stats/";
std::string dir = from_ctrl ? "cs" : "sc";
std::string ext = ".csv";
std::string file_name = file_location + getTopoString(topo_type) + "_" + std::to_string(flows) + "-" + dir + ext;
return (file_name);
}
/*
* One of the Utility functions to read throughput source files
* This function reads each entry in the thruput src file, once the file name is supplied.
*/
void Routing::calculateDelay(std::string file_name, bool from_ctrl){
std::string thruEntry;
std::ifstream thruputDataFile(file_name);
while (getline (thruputDataFile, thruEntry)) {
// EV << thruEntry << endl; // one entry looks like this: 64,121722.8689183932
int pos = thruEntry.find(",");
int node_id = std::stoi(thruEntry.substr(0, pos));
EV << node_id <<endl;
std::string sub = thruEntry.substr(pos + 1);
double del = std::stod(sub);
/* fromController stores the thruput values observed
* from the direction of the controller
* toController stores the thruput values observed
* packets that traverse towards the controller. */
if (from_ctrl) fromController[node_id] = del;
else toController[node_id] = del;
}
thruputDataFile.close();
return;
}
/*
* For 10Gbps,
* We calculate the baseline thruput by using the baseline csv files.
* We are running two tests -
* ===== One for FLow installation (with normal csv files, and baseline)
* ===== One for Stats collection (with normal csv files, and baseline)
*
* The thruputs and packetlengths will be the same for one test of normal csv and baseline,
* but will change with the number of flows, the direction of the flow and the type of test.
*
*
* For 100Mbps, we use Qrates as QUEUE_RATE_PKTS_S_100Mbps_100FLows_SC/CS
* For 10Gbps, QUEUE_RATE_PKTS_S_10G_100FLows_CS_Stats/SC
* */
long double Routing::calculateQueuingLatencyToController(int address, int flows) {
double qRate = 0.0;
switch (flows) {
case 100:
qRate = (double)QUEUE_RATE_PKTS_S_10G_100FLows_SC_Stats;
break;
case 500:
qRate = (double)QUEUE_RATE_PKTS_S_10G_500FLows_SC_Stats;
break;
}
double thruputVal = (double)toController[address]/ (double)(averagePackLenSC10GbpsStats[flows]*8);
long double delay = (double)1/(double)(qRate - thruputVal);
//long double delay = (double)1/(double)(QUEUE_RATE_PKTS_S);
EV << "\ntoController:" << qRate << ",Thruput:" << thruputVal << ",Delay:" << delay <<endl;
return (delay);
}
/*
* calculateQueuingLatencyFromController(int address, int flows)
* params: address of the node, number of flows.
* For details on the formula, read README
*/
long double Routing::calculateQueuingLatencyFromController(int address, int flows) {
double qRate = 0.0;
switch (flows) {
case 100:
qRate = (double)QUEUE_RATE_PKTS_S_10G_100FLows_CS_Stats;
break;
case 500:
qRate = (double)QUEUE_RATE_PKTS_S_10G_500FLows_CS_Stats;
break;
}
double thruputVal = (double)fromController[address]/(double)(averagePackLenCS10GbpsStats[flows]*8);
EV << "\nQRate:" << ",fromController:" << (double)fromController[address] << endl;
long double delay = (double)1/(double)(qRate - thruputVal);
EV << "\nQRate:FromCtlr:" << qRate << ",Thruput:" << thruputVal << ",Delay:" << delay <<endl;
return (delay);
}
void Routing::initialize()
{
CONTROLLER_ID = getControllerID();
if (!CONTROLLER_ID) {
throw cRuntimeError("Invalid ID for Controller");
}
myAddress = getParentModule()->par("address");
dropSignal = registerSignal("drop");
outputIfSignal = registerSignal("outputIf");
topology_type = par("topo");
cTopology *topo = new cTopology("topo");
// EV << "\n\n " << getNedTypeName() << "--->" << getParentModule()->getComponentType()->getFullName() << "\n";
topo->extractByNedTypeName(cStringTokenizer("Node Controller").asVector());
cTopology::Node *thisNode = topo->getNodeFor(getParentModule());
/* Create the routing table */
for (int i = 0; i < topo->getNumNodes(); i++) {
if (topo->getNode(i) == thisNode)
continue; // skip ourselves
topo->calculateUnweightedSingleShortestPathsTo(topo->getNode(i));
if (thisNode->getNumPaths() == 0) continue;
cGate *parentModuleGate = thisNode->getPath(0)->getLocalGate();
int gateIndex = parentModuleGate->getIndex();
int address = topo->getNode(i)->getModule()->par("address");
rtable[address] = gateIndex;
// EV << " towards address " << address << " gateIndex is " << gateIndex << endl;
}
delete topo;
if (getParentModule()->getId() != CONTROLLER_ID) {
/*
* Queuing delays would differ with the number of flows.
* We get the number of flows from the parameters.
*/
int flows = getParentModule()->par("num_flows");
/*
* First calculate the delay in the direction of
* "from the controller to the switch."
* [Controller] ---> [Spine]---> [Leaf]
* pk ---------------------------->
* We store these delays in fromController.
*/
std::string file_name = getFileName(topology_type, flows, true);
calculateDelay(file_name, true);
/*
* Then calculate the delay "TO the controller from the switch."
* [Controller] ---> [Spine]---> [Leaf]
* <-------------------------------pk
* We store these delays per switch in toController
*/
file_name = getFileName(topology_type, flows, false);
calculateDelay(file_name, false);
/* We then calculate the final Queuing latencies from fromController
* and toController, PER switch, for a given number of "flows". */
queuing_DTC = calculateQueuingLatencyToController(myAddress, flows);
queuing_DFC = calculateQueuingLatencyFromController(myAddress, flows);
} else {
/* For a controller, these delays are 0.*/
queuing_DTC = 0;
queuing_DFC = 0;
}
}
/* This routine is called for EACH message received by the routing module.
*/
void Routing::handleMessage(cMessage *msg)
{
Packet *pk = check_and_cast<Packet *>(msg);
int destAddr = pk->getDestAddr();
int srcAddr = pk->getSrcAddr();
int pk_id = pk->getPacket_id();
long double delay_pack = 0;
EV << "Routing at" <<myAddress << "-" << pk_id << "-"<< pk->getName() << "-"<< myAddress << "="<< destAddr << endl;
EV << "Routing at" <<myAddress << "-" << pk_id << "-"<<"Routing:queuing_DTC:" << queuing_DTC ;
EV << "Routing at" <<myAddress << "-" << pk_id << "-"<< "Routing:queuing_DFC:" << queuing_DFC << endl;
/* This message was intended for us, let us process it.
* We send it to OUR Application module, which is connected to Routing's localOut.
* Application module will read, what kind of a packet it is, and will send
* the appropriate packet response.
*/
if (destAddr == myAddress) {
send(pk, "localOut");
emit(outputIfSignal, -1);
return;
}
/* Route/Forward the message as necessary. */
RoutingTable::iterator it = rtable.find(destAddr);
/* Could not find next hop. */
if (it == rtable.end()) {
emit(dropSignal, (long)pk->getByteLength());
delete pk;
return;
}
/* The code for forwarding is here: */
int outGateIndex = (*it).second;
pk->setHopCount(pk->getHopCount()+1);
emit(outputIfSignal, outGateIndex);
/* Here is where we plug in our delay simulation, before forwarding the packet.*/
if (srcAddr == myAddress) {
/* If the packet was generated by this node, we will only have transmission delay, not the queuing delay. */
delay_pack = 0;
send(pk, "out", outGateIndex);
} else {
/*
* If the packet is forwarded by this node, check which direction it is going to.
* If it is coming from the controller, we plug in delay fromCtlr
* If it is going to the controller, we plug in delay toController.
*/
if (destAddr == CONTROLLER_ADDRS) {
delay_pack = queuing_DTC;
} else {
delay_pack = queuing_DFC;
}
/* We then plug in the transmission delay */
int size = pk->getByteLength();
delay_pack += (double (size)/double(LINE_RATE));
/* Omnet lets us send with a delay by using the sendDelayed function */
sendDelayed(pk, delay_pack, "out", outGateIndex);
}
}