RINASim  October 2016
Documentation of framework for OMNeT++
SimpleFabricForwarding.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 #include "SimpleFabricForwarding.h"
24 #include <sstream>
25 #include "Utils.h"
26 
27 namespace NSPSimpleDC {
28 
29  Register_Class(SimpleFabricForwarding);
30 
31  using namespace std;
32 
33  fFWDEntry::fFWDEntry() : entryType(0), inverseStorage(false) {}
34 
36  upCount = par("upCount").longValue();
37  if(upCount < 0) { upCount = 0; }
38 
39  downCount = par("downCount").longValue();
40  if(downCount < 0) { downCount = 0; }
41 
43  for(int i = 0; i<upCount+downCount; i++) { portsArray[i] = nullptr; }
44  }
45 
46  vector<Port> SimpleFabricForwarding::search(const DCAddr & n_addr) {
47  if(Im == n_addr) { return vector<Port>(); }
48  if(n_addr.type < 0 || n_addr.type > 3) {
49  cerr << "Invalid dst addr ("<<n_addr<< ")" << endl;
50  return vector<Port>();
51  }
52 
53  auto r = table.find(n_addr);
54  if(r != table.end()) {
55  auto & e = r->second;
56  if(e.entryType == 0) { return vector<Port>(); }
57 
58  vector<Port> ret;
59 
60  int i = (e.entryType == 2)? upCount:0;
61  int j = (e.entryType == 1)? downCount : upCount+downCount;
62  for(; i<j; i++) {
63  Port p = portsArray[i];
64  if(p == nullptr) { continue; }
65  if(e.inverseStorage == (e.ports.find(p) == e.ports.end()) ) {
66  ret.push_back(p);
67  }
68  }
69 
70  return ret;
71  }
72 
73  switch(n_addr.type) {
74  case 0:
75  if(n_addr.a == Im.a) {
76  if(n_addr.b < downCount && portsArray[upCount+n_addr.b] != nullptr) {
77  vector<Port> ret;
78  ret.push_back(portsArray[upCount+n_addr.b]);
79  return ret;
80  } else { cout << "!!! Invalid port to " << (upCount+n_addr.b) << " at " << Im << endl; }
81  }
82  return upV;
83  case 1:
84  if(n_addr.a == Im.a) {
85  return downV;
86  } else if(n_addr.b == Im.b) {
87  return upV;
88  }
89  return bothV;
90  case 2:
91  if(n_addr.a == Im.b) {
92  if(n_addr.b < upCount && portsArray[n_addr.b] != nullptr) {
93  vector<Port> ret;
94  ret.push_back(portsArray[n_addr.b]);
95  return ret;
96  } else { cout << "!!! Invalid port to " << (n_addr.b) << " at " << Im << endl; }
97  }
98  return downV;
99  case 3:
100  if(n_addr.b == Im.b) {
101  return upV;
102  }
103  return downV;
104  }
105  return vector<Port>();
106  }
107 
108  bool SimpleFabricForwarding::setNeigh(const DCAddr & n_addr, Port port) {
109  bool invalid = false;
110  switch(n_addr.type){
111  case 0 :
112  if(n_addr.a != Im.a || n_addr.b >= downCount) {
113  invalid = true;
114  } break;
115  case 2 :
116  if(n_addr.a != Im.b || n_addr.b >= upCount) {
117  invalid = true;
118  } break;
119  default:
120  invalid = true;
121  }
122 
123  if(invalid) {
124  cerr << "Invalid neighbour ("<<n_addr<< ") found for Fabric " << Im<<endl;
125  return false;
126  }
127 
128  Port t ;
129  if(n_addr.type == 0){
130  t = portsArray[upCount+n_addr.b];
131  if(t == port) { return true; }
132  portsArray[upCount+n_addr.b] = port;
133  } else {
134  t = portsArray[n_addr.b];
135  if(t == port) { return true; }
136  portsArray[n_addr.b] = port;
137  }
138 
139  upV.clear();
140  downV.clear();
141  bothV.clear();
142  for(int i = 0; i<upCount; i++) {
143  Port pt = portsArray[i];
144  if(pt!= nullptr) {
145  upV.push_back(pt);
146  bothV.push_back(pt);
147  }
148  }
149  for(int i = 0; i<downCount; i++) {
150  Port pt = portsArray[upCount+i];
151  if(pt!= nullptr) {
152  downV.push_back(pt);
153  bothV.push_back(pt);
154  }
155  }
156 
157  for(auto & e : table) {
158  if(e.second.ports.find(t) != e.second.ports.end()) {
159  e.second.ports.erase(t);
160  if(port != nullptr) {
161  e.second.ports.insert(port);
162  }
163  }
164  }
165  refreshCache (t, port);
166 
167  return true;
168  }
169 
170  void SimpleFabricForwarding::setDst(const DCAddr & n_addr, const set<DCAddr> & next) {
171  if(n_addr == Im) { return; }
172 
173  if(n_addr.type < 0 || n_addr.type > 3) {
174  cerr << "Invalid dst addr ("<<n_addr<< ")" << endl;
175  return;
176  }
177 
178  int S = next.size();
179 
180  if(S == 0) {
181  table[n_addr] = fFWDEntry();
182  return;
183  }
184 
185  set<int> upIds, downIds;
186  for(const auto & n : next) {
187  if(n.type == 0) {
188  downIds.insert(n.b);
189  } else if(n.type == 2) {
190  upIds.insert(n.b);
191  }
192  }
193  int upS = upIds.size();
194  int downS = downIds.size();
195 
196  if(upS == 0 && downS == 0) {
197  table[n_addr] = fFWDEntry();
198  return;
199  }
200 
201  bool defaultEntry = false;
202  switch(n_addr.type) {
203  case 0:
204  if(n_addr.a == Im.a
205  && n_addr.b < downCount
206  && portsArray[upCount+n_addr.b] != nullptr) {
207  defaultEntry = true;
208  }else if(downS == 0
209  && upS == upCount) {
210  defaultEntry = true;
211  } break;
212  case 1:
213  if(n_addr.a == Im.a
214  && downS == downCount
215  && upS == 0) {
216  defaultEntry = true;
217  } else if(n_addr.b == Im.b
218  && upS == upCount
219  && downS == 0) {
220  defaultEntry = true;
221  } else if(upS == upCount
222  && downS == downCount) {
223  defaultEntry = true;
224  } break;
225  case 2:
226  if(n_addr.a == Im.b
227  && n_addr.b < upCount
228  && portsArray[n_addr.b] != nullptr) {
229  defaultEntry = true;
230  } else if(downS == downCount
231  && upS == 0) {
232  defaultEntry = true;
233  } break;
234  case 3:
235  if(n_addr.b == Im.b
236  && n_addr.b < upCount
237  && portsArray[n_addr.b] != nullptr) {
238  defaultEntry = true;
239  } else if(downS == downCount
240  && upS == 0) {
241  defaultEntry = true;
242  } break;
243  }
244 
245  if(defaultEntry) {
246  table.erase(n_addr);
247  } else if(upS > 0) {
248  if(downS > 0) {
249  table[n_addr] = getFWDEntryBOTH(upIds, downIds);
250  } else {
251  table[n_addr] = getFWDEntryUP(upIds);
252  }
253  } else {
254  table[n_addr] = getFWDEntryDOWN(downIds);
255  }
256 
257  refreshCache (n_addr);
258  }
259 
261  fFWDEntry ret;
262  ret.entryType = 1;
263  ret.inverseStorage = ((int)pIds.size()*2 > upCount);
264 
265  for(int i = 0; i< upCount; i++) {
266  if(ret.inverseStorage == (pIds.find(i) == pIds.end())) {
267  ret.ports.insert(portsArray[i]);
268  }
269  }
270  return ret;
271  }
272 
274  fFWDEntry ret;
275  ret.entryType = 2;
276  ret.inverseStorage = ((int)pIds.size()*2 > downCount);
277 
278  for(int i = 0; i< downCount; i++) {
279  if(ret.inverseStorage == (pIds.find(i) == pIds.end())) {
280  ret.ports.insert(portsArray[upCount+i]);
281  }
282  }
283  return ret;
284  }
285 
286  fFWDEntry SimpleFabricForwarding::getFWDEntryBOTH(const set<int> & pIdsU, const set<int> & pIdsD) {
287  fFWDEntry ret;
288  ret.entryType = 3;
289  ret.inverseStorage = (int)(pIdsU.size()*2 + pIdsD.size()*2) > (upCount+downCount);
290 
291  for(int i = 0; i< upCount; i++) {
292  if(ret.inverseStorage == (pIdsU.find(i) == pIdsU.end())) {
293  ret.ports.insert(portsArray[i]);
294  }
295  }
296  for(int i = 0; i< downCount; i++) {
297  if(ret.inverseStorage == (pIdsD.find(i) == pIdsD.end())) {
298  ret.ports.insert(portsArray[upCount+i]);
299  }
300  }
301  return ret;
302  }
303 
305  if(par("printAtEnd").boolValue()) {
306  cout << "-----------------------" << endl;
307  cout << "SimpleFabricForwarding at "<< endl;
308  cout << " " << getFullPath() << endl;
309 
310  cout << "I'm Fabric "<< Im << endl;
311  if(upCount > 0) {
312  cout << "\tUp neighbours:" << endl;
313  for(int i = 0; i < upCount; i++) {
314  cout << "\t\t2."<<Im.b<<"."<<i<<" -> Status "<< (portsArray[i]!=nullptr? "ON":"OFF") << endl;
315  }
316  }
317  if(downCount > 0) {
318  cout << "\tDown neighbours:" << endl;
319  for(int i = 0; i < downCount; i++) {
320  cout << "\t\t0."<<Im.a<<"."<<i<<" -> Status "<< (portsArray[upCount+i]!=nullptr? "ON":"OFF") << endl;
321  }
322  }
323  if(table.empty()) {
324  cout << "\tNo entries stored" << endl;
325  } else {
326  cout << "Stored entries " << table.size() << endl;
327  for(auto & e : table) {
328  cout <<"\t\t"<< e.first << " -- ";
329  if(e.second.entryType == 0) {
330  cout << "Unreachable";
331  } else {
332  switch (e.second.entryType) {
333  case 1: cout <<"UP - ";break;
334  case 2: cout <<"DOWN - ";break;
335  case 3: cout <<"BOTH - ";break;
336  }
337  if(e.second.inverseStorage) {
338  cout << "(inverse) ";
339  }
340  cout << e.second.ports.size() << " stored ports:";
341  }
342  cout << endl;
343  for(auto &k : e.second.ports) {
344  cout << "\t\t\t" << k->getFullPath() << endl;
345  }
346  }
347  }
348  }
349 
350  delete portsArray;
351  }
352 
353 }
set< Port > ports
Register_Class(SimpleDCGenerator)
virtual void refreshCache(Port oldP, Port newP)
bool setNeigh(const DCAddr &n_addr, Port port)
bool inverseStorage
fFWDEntry()
fFWDEntry getFWDEntryUP(const set< int > &pIds)
vector< Port > search(const DCAddr &n_addr)
fFWDEntry getFWDEntryDOWN(const set< int > &pIds)
void setDst(const DCAddr &n_addr, const set< DCAddr > &next)
fFWDEntry getFWDEntryBOTH(const set< int > &pIdsU, const set< int > &pIdsD)
char entryType