OverSim
ReaSEUnderlayConfigurator.cc
Go to the documentation of this file.
1 //
2 // Copyright (C) 2010 Institut fuer Telematik, Karlsruher Institut fuer Technologie (KIT)
3 //
4 // This program is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU General Public License
6 // as published by the Free Software Foundation; either version 2
7 // of the License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 //
18 
25 
26 #include <GlobalNodeList.h>
27 #include <TransportAddress.h>
28 
29 #include <StringConvert.h>
30 
31 #include <ConnectReaSE.h>
32 #include <IRoutingTable.h>
33 #include <IInterfaceTable.h>
34 #include <IPAddressResolver.h>
35 #include <IPv4InterfaceData.h>
36 #include <NotificationBoard.h>
37 
38 
39 #include <ReaSEInfo.h>
40 
42 
44 {
45  //backbone configuration
46  if (stage == MIN_STAGE_UNDERLAY) {
47 
48  }
49  //access net configuration
50  else if (stage == MAX_STAGE_UNDERLAY) {
51  // fetch some parameters
52 
53 
54  // count the overlay clients
56 
57  numCreated = 0;
58  numKilled = 0;
59 
60  // add access node modules to access node vector
61  TerminalConnector = (ConnectReaSE*)getParentModule()->getSubmodule("TerminalConnector");
62  }
63 }
64 
66 {
67  Enter_Method_Silent();
68  // derive overlay node from ned
69  std::string nameStr = "overlayTerminal";
70  if (churnGenerator.size() > 1) {
71  nameStr += "-" + convertToString<int32_t>(type.typeID);
72  }
74  cModuleType* moduleType = cModuleType::get(type.terminalType.c_str());
75  cModule* node = moduleType->create(nameStr.c_str(), accessNet.edge->Router->getParentModule(), //TODO: insert node in submodule
76  numCreated + 1, numCreated);
77 
78  if (type.channelTypesTx.size() > 0) {
79  throw cRuntimeError("ReaSEUnderlayConfigurator::createNode(): Setting "
80  "channel types via the churn generator is not allowed "
81  "with the ReaSEUnderlay. Use **.accessNet.channelTypes instead!");
82  }
83 
84  node->setGateSize("pppg", 1);
85 
86  std::string displayString;
87 
88  if ((type.typeID > 0) && (type.typeID <= NUM_COLORS)) {
89  ((displayString += "i=device/wifilaptop_l,")
90  += colorNames[type.typeID - 1])
91  += ",40;i2=block/circle_s";
92  } else {
93  displayString = "i=device/wifilaptop_l;i2=block/circle_s";
94  }
95 
96  node->finalizeParameters();
97  node->setDisplayString(displayString.c_str());
98 
99  node->buildInside();
100  node->scheduleStart(simTime());
101 
102  // create meta information
103  ReaSEInfo* info = new ReaSEInfo(type.typeID, node->getId(), type.context);
104 
105  accessNet.terminal = node;
106  // add node to a randomly chosen access net
107  info->setNodeID(TerminalConnector->addOverlayNode(&accessNet));
108 
109 
110  // add node to bootstrap oracle
111  globalNodeList->addPeer(IPAddressResolver().addressOf(node), info);
112 
113  // if the node was not created during startup we have to
114  // finish the initialization process manually
115  if (!initialize) {
116  for (int i = MAX_STAGE_UNDERLAY + 1; i < NUM_STAGES_ALL; i++) {
117  node->callInitialize(i);
118  }
119  }
120 
122  numCreated++;
123 
124  churnGenerator[type.typeID]->terminalCount++;
125 
126  TransportAddress *address = new TransportAddress(
127  IPAddressResolver().addressOf(node));
128 
129  // update display
131 
132  return address;
133 }
134 
135 //TODO: getRandomNode()
137 {
138  Enter_Method_Silent();
139 
140  // AccessNet* accessNetModule = NULL;
141  int nodeID;
142  ReaSEInfo* info;
143 
144  // If no address given, get random node
145  if (addr == NULL) {
147 
148  if (addr == NULL) {
149  // all nodes are already prekilled
150  std::cout << "all nodes are already prekilled" << std::endl;
151  return;
152  }
153  }
154 
155  // get node information
156  info = dynamic_cast<ReaSEInfo*>(globalNodeList->getPeerInfo(*addr));
157 
158  if (info != NULL) {
159  //accessNetModule = info->getAccessNetModule();
160  nodeID = info->getNodeID();
161  } else {
162  opp_error("IPv4UnderlayConfigurator: Trying to pre kill node "
163  "with nonexistant TransportAddress!");
164  }
165 
166  uint32_t effectiveType = info->getTypeID();
167 
168  // do not kill node that is already scheduled
169  if (scheduledID.count(nodeID))
170  return;
171  //TODO: get overlay node
172  cModule* node = TerminalConnector->getOverlayNode(nodeID);
173  globalNodeList->removePeer(IPAddressResolver().addressOf(node));
174 
175  //put node into the kill list and schedule a message for final removal of the node
176  killList.push_front(IPAddressResolver().addressOf(node));
177  scheduledID.insert(nodeID);
178 
180  numKilled++;
181 
182  churnGenerator[effectiveType]->terminalCount--;
183 
184  // update display
186 
187  // inform the notification board about the removal
188  NotificationBoard* nb = check_and_cast<NotificationBoard*>(
189  node->getSubmodule("notificationBoard"));
190  nb->fireChangeNotification(NF_OVERLAY_NODE_LEAVE);
191 
192  double random = uniform(0, 1);
193 
194  if (random < gracefulLeaveProbability) {
195  nb->fireChangeNotification(NF_OVERLAY_NODE_GRACEFUL_LEAVE);
196  }
197 
198  cMessage* msg = new cMessage();
199  scheduleAt(simTime() + gracefulLeaveDelay, msg);
200 
201 }
202 
204 {
205  Enter_Method_Silent();
206 
207  // AccessNet* accessNetModule = NULL;
208  int nodeID = -1;
209  ReaSEInfo* info;
210 
211  // If no address given, get random node
212  if (addr == NULL) {
213  info = dynamic_cast<ReaSEInfo*>(globalNodeList->getRandomPeerInfo(type.typeID));
214  } else {
215  // get node information
216  info = dynamic_cast<ReaSEInfo*>(globalNodeList->getPeerInfo(*addr));
217  }
218 
219  if (info != NULL) {
220  //accessNetModule = info->getAccessNetModule();
221  nodeID = info->getNodeID();
222  } else {
223  opp_error("ReaSEUnderlayConfigurator: Trying to pre kill node with nonexistant TransportAddress!");
224  }
225 
226  // do not migrate node that is already scheduled
227  if (scheduledID.count(nodeID))
228  return;
229 
230  cModule* node = TerminalConnector->removeOverlayNode(nodeID);//intuniform(0, accessNetModule->size() - 1));
231 
232  if (node == NULL)
233  opp_error("ReaSEUnderlayConfigurator: Trying to remove node which is not an overlay node in network!");
234 
235  //remove node from bootstrap oracle
236  globalNodeList->killPeer(IPAddressResolver().addressOf(node));
237 
238  node->bubble("I am migrating!");
239  // connect the node to another access net
240  AccessInfo newAccessModule;
241 
242  // create meta information
243  ReaSEInfo* newinfo = new ReaSEInfo(type.typeID, node->getId(), type.context);
244  newAccessModule = TerminalConnector->migrateNode(node->getId());
245  newAccessModule.terminal = node;
246  // add node to a randomly chosen access net
247  info->setNodeID(TerminalConnector->addOverlayNode(&newAccessModule));
248 
249  //add node to bootstrap oracle
250  globalNodeList->addPeer(IPAddressResolver().addressOf(node), newinfo);
251 
252  // inform the notification board about the migration
253  NotificationBoard* nb = check_and_cast<NotificationBoard*>(node->getSubmodule("notificationBoard"));
254  nb->fireChangeNotification(NF_OVERLAY_TRANSPORTADDRESS_CHANGED);
255 }
256 
258 {
259  Enter_Method_Silent();
260 
261  // get next scheduled node from the kill list
262  IPvXAddress addr = killList.back();
263  killList.pop_back();
264 
265  //AccessNet* accessNetModule = NULL;
266  int nodeID = -1;
267 
268  ReaSEInfo* info = dynamic_cast<ReaSEInfo*>(globalNodeList->getPeerInfo(addr));
269  if (info != NULL) {
270  //accessNetModule = info->getAccessNetModule();
271  nodeID = info->getNodeID();
272  } else {
273  opp_error("IPv4UnderlayConfigurator: Trying to kill node with nonexistant TransportAddress!");
274  }
275 
276  scheduledID.erase(nodeID);
277  globalNodeList->killPeer(addr);
278 
279  cModule* node = TerminalConnector->removeOverlayNode(nodeID);
280 
281  if (node == NULL)
282  opp_error("IPv4UnderlayConfigurator: Trying to remove node which is nonexistant in AccessNet!");
283 
284  node->callFinish();
285  node->deleteModule();
286 
287  delete msg;
288 }
289 
291 {
292  char buf[80];
293  sprintf(buf, "%i overlay terminals",
295  getDisplayString().setTagArg("t", 0, buf);
296 }
297 
299 {
300  // statistics
301  recordScalar("Terminals added", numCreated);
302  recordScalar("Terminals removed", numKilled);
303 
304  if (!isInInitPhase()) {
305  struct timeval now, diff;
306  gettimeofday(&now, NULL);
307  timersub(&now, &initFinishedTime, &diff);
308  printf("Simulation time: %li.%06li\n", diff.tv_sec, diff.tv_usec);
309  }
310 }
311 
312