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