RINASim  October 2016
Documentation of framework for OMNeT++
IntDCRouting.cc
Go to the documentation of this file.
1 // The MIT License (MIT)
2 //
3 // Copyright (c) 2014-2016 Brno University of Technology, PRISTINE project
4 //
5 // Permission is hereby granted, free of charge, to any person obtaining a copy
6 // of this software and associated documentation files (the "Software"), to deal
7 // in the Software without restriction, including without limitation the rights
8 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 // copies of the Software, and to permit persons to whom the Software is
10 // furnished to do so, subject to the following conditions:
11 //
12 // The above copyright notice and this permission notice shall be included in
13 // all copies or substantial portions of the Software.
14 //
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 // THE SOFTWARE.
22 
23 
24 #include "IntDCRouting.h"
25 
26 namespace NSPSimpleDC {
27 
29  src(DCAddr()), dst(DCAddr()){}
30  linkId::linkId(const DCAddr &_src, const DCAddr &_dst) {
31  if(_src.type < _dst.type) {
32  src =_src;
33  dst =_dst;
34  } else {
35  src =_dst;
36  dst =_src;
37  }
38  }
39 
40  bool linkId::operator<(const linkId & o) const {
41  if(src < o.src) { return true; }
42  if(o.src < src) { return false; }
43  if(dst < o.dst) { return true; }
44 
45  return false;
46  }
47 
48  bool linkId::operator==(const linkId & o) const {
49  return src==o.src && dst==o.dst;
50  }
51 
52  bool linkId::operator!=(const linkId & o) const {
53  return src!=o.src || dst!=o.dst;
54  }
55 
56 
58  link(), status(false), timestamp(-1){}
59 
60  linkInfo::linkInfo(const linkId &_link, const bool &_status, const simtime_t &_timestamp):
61  link(_link), status(_status), timestamp(_timestamp){}
62 
64  LinksUpdate * ret = new LinksUpdate();
65  ret->dstAddr = dst;
66  ret->linksStatus = linksStatus;
67  return ret;
68  }
69 
70 
71  tableNode::tableNode() : d(99) {}
72  tableNode::tableNode(const linkId * n) : d(1) {
73  L.insert(n);
74  }
75 
76  void tableNode::insert (set<const linkId *> Ls) {
77  L.insert(Ls.begin(), Ls.end());
78  }
79 
80  void IntDCRouting::handleMessage(cMessage * msg) {
81  if(msg == clean) {
82  if(linksOk.empty()) {
83  clean = nullptr;
84  delete msg;
85  } else {
86  scheduleAt(simTime() + expiration, clean);
87  }
88  } else if(msg == sched) {
89  LinksUpdate update;
90  for(const auto & linkData : linksOk) {
91  if(linkData.second.link.src == DCAddr()) {
92  cerr << "Invalid link in ok list" << endl;
93  continue;
94  }
95  update.linksStatus.push_back(linkData.second);
96  }
97  for(const auto & linkData : linksKo) {
98  if(linkData.second.link.src == DCAddr()) {
99  cerr << "Invalid link in ko list" << endl;
100  continue;
101  }
102  update.linksStatus.push_back(linkData.second);
103  }
104 
105  if(!update.linksStatus.empty()) {
106  for(const auto & n : activeNeighbours) {
107  sendUpdate(update.toDst(n));
108  }
109  }
110 
111  sched = nullptr;
112  delete msg;
113  } else if(msg == start) {
114  LinksUpdate update;
115  for(const auto & linkData : linksKo) {
116  if(linkData.second.link.src == DCAddr()) {
117  cerr << "Start - Invalid link in ko list" << endl;
118  continue;
119  }
120  update.linksStatus.push_back(linkData.second);
121  }
122 
123  if(!update.linksStatus.empty()) {
124  for(const auto & n : activeNeighbours) {
125  sendUpdate(update.toDst(n));
126  }
127  }
128 
129  start = nullptr;
130  delete msg;
131  } else {
132  cerr << "Unknown message" << endl;
133  delete msg;
134  }
135  }
136 
138 
139  string myAddr = getModuleByPath("^")->par("ipcAddress").stringValue();
140  Im = DCAddr(myAddr);
141 
142  clean = nullptr;
143  start = new cMessage("Start updates");
144  sched = nullptr;
145 
146  pods = par("pods").longValue();
147  torXpod = par("torXpod").longValue();
148  fabricXpod = par("fabricXpod").longValue();
149  spineXfabric = par("spineXfabric").longValue();
150  edgeSets = par("edgeSets").longValue();
151  updateWait = par("updateWait").doubleValue();
152  expiration = par("expiration").doubleValue();
153  double starttime = par("starttime").doubleValue();
154 
155  scheduleAt(simTime() + starttime, start);
156 
157  startMyLinks();
158  }
159 
161  LinksUpdate * u = dynamic_cast<LinksUpdate*>(update);
162  if(u == nullptr) {
163  cerr << "Invalid update message received" << endl;
164  return false;
165  }
166 
167  // cout << "I'm " << Im << ", received update from "<< u->getSource() <<endl;
168 
169  bool changes = false;
170 
171  for(const auto l : u->linksStatus) {
172  auto ml = myLinks.find(l.link);
173  if(ml != myLinks.end()) {
174  if(l.status == false
175  && ml->second.status
176  && ml->second.timestamp < (simTime()-expiration)) {
177  ml->second.timestamp = simTime();
178  changes = true;
179  }
180  continue;
181  }
182 
183  if(l.link.src == DCAddr(-1,0,0)) {
184  cerr << "At " << Im << ", received invalid link info from "<< u->getSource() << endl;
185  continue;
186  }
187 
188  if(l.status) {
189  if(linksKo.find(l.link) != linksKo.end()) {
190  linkInfo & tI = linksKo[l.link];
191  if(tI.timestamp < l.timestamp) {
192  linksOk[l.link] = l;
193  linksKo.erase(l.link);
194  changes = true;
195  }
196  } else if(l.timestamp > simTime() + expiration) {
197  linkInfo & tI = linksOk[l.link];
198  if(tI.timestamp < l.timestamp) {
199  tI.link = l.link;
200  tI.timestamp = l.timestamp;
201  changes = true;
202  }
203  }
204  } else {
205  if(linksOk.find(l.link) != linksOk.end()) {
206  linkInfo & tI = linksOk[l.link];
207  if(tI.timestamp < l.timestamp) {
208  linksKo[l.link] = l;
209  linksOk.erase(l.link);
210  changes = true;
211  }
212  } else {
213  linkInfo & tI = linksKo[l.link];
214  if(tI.timestamp < l.timestamp) {
215  tI.link = l.link;
216  tI.timestamp = l.timestamp;
217  changes = true;
218  }
219  }
220  }
221  }
222 
223  scheduleClean();
224 
225  if(changes) {
226  scheduleUpdate();
227  return true;
228  } else {
229  return false;
230  }
231  }
232 
233  void IntDCRouting::insertNeighbour(const Address &addr, const DCAddr &dst) {
234  Enter_Method_Silent();
235  activeNeighbours.insert(addr);
236  activeNeigh(dst);
237  }
238 
239  void IntDCRouting::removeNeighbour(const Address &addr, const DCAddr &dst) {
240  Enter_Method_Silent();
241  activeNeighbours.erase(addr);
242  inactiveNeigh(dst);
243  }
244 
246  Enter_Method_Silent();
247  if(start == nullptr && sched == nullptr) {
248  sched = new cMessage("Scheduled update");
249  scheduleAt(simTime()+updateWait, sched);
250  }
251  }
253  Enter_Method_Silent();
254  if(clean == nullptr) {
255  clean = new cMessage("Scheduled clean");
256  scheduleAt(simTime()+expiration, clean);
257  }
258  }
259 
260 
261  map<DCAddr, tableNode> * IntDCRouting::computeTable() {
262  map<DCAddr, tableNode> * table = new map<DCAddr, tableNode>();
263  map<DCAddr, tableNode> & t = (*table);
264  for(int p = 0; p < pods; p++) {
265  for(int k = 0; k < torXpod; k++) {
266  t[DCAddr(0, p, k)];
267  }
268  for(int f = 0; f < fabricXpod; f++) {
269  t[DCAddr(1, p, f)];
270  }
271  }
272  for(int f = 0; f < fabricXpod; f++) {
273  for(int s = 0; s < spineXfabric; s++) {
274  t[DCAddr(2, f, s)];
275  }
276  }
277  for(int p = 0; p < edgeSets; p++) {
278  for(int f = 0; f < fabricXpod; f++) {
279  t[DCAddr(3, p, f)];
280  }
281  }
282 
283  queue<DCAddr> next;
284  for(auto & l : myLinks) {
285  if(l.second.status) {
286  if(l.first.dst == Im) {
287  t[l.first.src] = tableNode( &(l.first) );
288  next.push(l.first.src);
289  } else {
290  t[l.first.dst] = tableNode( &(l.first) );
291  next.push(l.first.dst);
292  }
293  }
294  }
295 
296  while(!next.empty()) {
297  auto n = next.front();
298  next.pop();
299  tableNode & tn = t[n];
300  int tD = tn.d + 1;
301  vector<DCAddr> neis = getNeis(n);
302  for(auto &ni : neis) {
303  tableNode & tni = t[ni];
304  if(linksKo.find(linkId(n, ni)) != linksKo.end()) {
305  continue;
306  }
307  if(tni.d > tD) {
308  tni.d = tD;
309  tni.insert(tn.L);
310  next.push(ni);
311  } else if(tni.d == tD) {
312  tni.insert(tn.L);
313  }
314  }
315  }
316 
317  return table;
318  }
319 
320  vector<DCAddr> IntDCRouting::getNeis(DCAddr n) {
321  vector<DCAddr> ret;
322  switch(n.type) {
323  case 0 :
324  for(int f = 0; f < fabricXpod; f++) {
325  ret.push_back( DCAddr(1, n.a, f) );
326  }
327  break;
328  case 1 :
329  for(int t = 0; t < torXpod; t++) {
330  ret.push_back( DCAddr(0, n.a, t) );
331  }
332  for(int s = 0; s < spineXfabric; s++) {
333  ret.push_back( DCAddr(2, n.b, s) );
334  }
335  break;
336  case 2 :
337  for(int p = 0; p < pods; p++) {
338  ret.push_back( DCAddr(1, p, n.a) );
339  }
340  for(int p = 0; p < edgeSets; p++) {
341  ret.push_back( DCAddr(3, p, n.a) );
342  }
343  break;
344  case 3 :
345  break;
346  }
347 
348  return ret;
349  }
350 
351  vector<rtEntry> IntDCRouting::getChanges() {
352  vector<rtEntry> ret;
353  map<DCAddr, tableNode> * t = computeTable();
354  set<DCAddr> no = getNotOptimalDst(t);
355 
356  for(auto it = cache.begin(); it!= cache.end();) {
357  const DCAddr & n = it->first;
358  auto noIt = no.find(n);
359  bool save = false;
360  auto &tn = (*t)[n];
361 
362  if(noIt == no.end()) {
363  save = true;
364  cache.erase(it++);
365  } else if(it->second != tn.L) {
366  save = true;
367  it->second = tn.L;
368  it++;
369  no.erase(noIt);
370  } else {
371  it++;
372  no.erase(noIt);
373  }
374 
375  if(save){
376  rtEntry e;
377  e.dst = n;
378  for(auto & nd : tn.L) {
379  if(nd->src == Im) { e.next.insert(nd->dst); }
380  else { e.next.insert(nd->src); }
381  }
382  ret.push_back(e);
383  }
384  }
385 
386  for(auto & n : no) {
387  auto & tn = (*t)[n];
388  rtEntry e;
389  e.dst = n;
390  cache[n] = tn.L;
391  for(auto & nd : tn.L) {
392  if(nd->src == Im) { e.next.insert(nd->dst); }
393  else { e.next.insert(nd->src); }
394  }
395  ret.push_back(e);
396  }
397  return ret;
398  }
399 
400  vector<rtEntry> IntDCRouting::getAll() {
401  vector<rtEntry> ret;
402  map<DCAddr, tableNode> * t = computeTable();
403  set<DCAddr> no = getNotOptimalDst(t);
404  cache.clear();
405 
406  for(auto n : no) {
407  auto &tn = (*t)[n];
408  rtEntry e;
409  e.dst = n;
410  cache[n] = tn.L;
411  for(auto & nd : tn.L) {
412  if(nd->src == Im) { e.next.insert(nd->dst); }
413  else { e.next.insert(nd->src); }
414  }
415  ret.push_back(e);
416  }
417  return ret;
418  }
419 
420 
422  if(par("printAtEnd").boolValue()) {
423  cout << "-------------" <<endl;
424  cout << "routing at "<< Im <<endl;
425  if(par("printMyLinks").boolValue()) {
426  cout << "-print links status" <<endl;
427  for(auto e : myLinks) {
428  cout << "\t" << e.first.src << " -> " << e.first.dst
429  << " status : " << (e.second.status? "OK" : "KO") << endl;
430  }
431  }
432 
433  if(par("printKoList").boolValue()) {
434  cout << "-print Ko List"<<endl;
435  for(auto e : linksKo) {
436  cout << "\t" << e.first.src << " -> " << e.first.dst << " (@ "<<e.second.timestamp<<")" << endl;
437  }
438  }
439 
440  if(par("printFullTable").boolValue()) {
441  cout << "-print Table"<<endl;
442  map<DCAddr, tableNode> * t = computeTable();
443  for(auto e : *t) {
444  cout << "\t" << e.first;
445  cout << "\t\t--distance : " << e.second.d << endl;
446  for(auto k : e.second.L) {
447  cout << "\t\t" << k->src << " -> " << k->dst << endl;
448  }
449  }
450  if(par("printNotOptimal").boolValue()) {
451  cout << "-print not optimal paths"<<endl;
452  set<DCAddr> no = getNotOptimalDst(t);
453  for(auto n : no) {
454  auto &tn = (*t)[n];
455  cout << "\t"<<n<<endl;
456  cout << "\t\t distance "<< tn.d<<endl;
457  for(auto & nd : tn.L) {
458  if(nd->src == Im) {
459  cout << "\t\t-> "<< nd->dst <<endl;
460  } else {
461  cout << "\t\t-> "<< nd->src <<endl;
462  }
463  }
464  }
465  }
466  } else if(par("printNotOptimal").boolValue()) {
467  map<DCAddr, tableNode> * t = computeTable();
468  cout << "-print not optimal paths"<<endl;
469  set<DCAddr> no = getNotOptimalDst(t);
470  for(auto n : no) {
471  auto &tn = (*t)[n];
472  cout << "\t"<<n<<endl;
473  cout << "\t\t distance "<< tn.d<<endl;
474  for(auto & nd : tn.L) {
475  if(nd->src == Im) {
476  cout << "\t\t-> "<< nd->dst <<endl;
477  } else {
478  cout << "\t\t-> "<< nd->src <<endl;
479  }
480  }
481  }
482  }
483 
484 
485 
486  printAtEnd();
487 
488  cout << "-------------" <<endl;
489  cout << endl;
490  }
491  }
492 }
DCAddr dst
Definition: IntDCRouting.h:88
vector< rtEntry > getChanges()
virtual void inactiveNeigh(const DCAddr &dst)=0
Definition: IntDCRouting.h:87
void insertNeighbour(const Address &addr, const DCAddr &dst)
void removeNeighbour(const Address &addr, const DCAddr &dst)
map< linkId, linkInfo > linksKo
Definition: IntDCRouting.h:112
set< const linkId * > L
Definition: IntDCRouting.h:73
map< linkId, linkInfo > myLinks
Definition: IntDCRouting.h:112
set< DCAddr > next
Definition: IntDCRouting.h:89
map< DCAddr, tableNode > * computeTable()
void insert(set< const linkId * > Ls)
Definition: IntDCRouting.cc:76
virtual set< DCAddr > getNotOptimalDst(map< DCAddr, tableNode > *table)=0
virtual void activeNeigh(const DCAddr &dst)=0
vector< DCAddr > getNeis(DCAddr)
void sendUpdate(IntRoutingUpdate *update)
Definition: IntRouting.cc:62
set< Address > activeNeighbours
Definition: IntDCRouting.h:113
map< linkId, linkInfo > linksOk
Definition: IntDCRouting.h:112
virtual void startMyLinks()=0
map< DCAddr, set< const linkId * > > cache
Definition: IntDCRouting.h:115
Address class holds IPC Process identification.
Definition: Address.h:42
virtual void handleMessage(cMessage *msg)
Definition: IntDCRouting.cc:80
vector< rtEntry > getAll()
bool processUpdate(IntRoutingUpdate *update)
virtual void printAtEnd()=0