OverSim
AccessNet.cc
Go to the documentation of this file.
1 //
2 // Copyright (C) 2006 Institut fuer Telematik, Universitaet Karlsruhe (TH)
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 
24 #include <vector>
25 #include <iostream>
26 
27 #include <omnetpp.h>
28 
29 #include <IRoutingTable.h>
30 #include <IInterfaceTable.h>
31 #include <RoutingTable6.h>
32 #include <IPAddressResolver.h>
33 #include <IPv4InterfaceData.h>
34 #include <IPv6InterfaceData.h>
35 
36 #include "AccessNet.h"
37 
39 
40 std::ostream& operator<<(std::ostream& os, NodeInfo& n)
41 {
42  os << n.IPAddress;
43  return os;
44 }
45 
46 void AccessNet::initialize(int stage)
47 {
48  if(stage != MIN_STAGE_UNDERLAY + 1)
49  return;
50 
51  router.module = getParentModule();
52  router.interfaceTable = IPAddressResolver().interfaceTableOf(getParentModule());
53  useIPv6 = par("useIPv6Addresses").boolValue();
54  if (useIPv6){
55  router.routingTable6 = IPAddressResolver().routingTable6Of(getParentModule());
57  } else {
58  router.routingTable = IPAddressResolver().routingTableOf(getParentModule());
59  router.IPAddress = IPAddressResolver().addressOf(getParentModule());
60  }
61 
62  channelTypesTx = cStringTokenizer(par("channelTypes"), " ").asVector();
63  channelTypesRx = cStringTokenizer(par("channelTypesRx"), " ").asVector();
64 
65  if (channelTypesRx.size() != channelTypesTx.size()) {
67  }
68 
69  int chanIndex = intuniform(0, channelTypesTx.size()-1);
70 
71  selectChannel(channelTypesRx[chanIndex], channelTypesTx[chanIndex]);
72 
73  // statistics
74  lifetimeVector.setName("Terminal Lifetime");
75 
76  WATCH_VECTOR(overlayTerminal);
77 
78  lastIP = 0;
79 
81 }
82 
83 void AccessNet::handleMessage(cMessage* msg)
84 {
85  error("this module doesn't handle messages, it runs only in initialize()");
86 }
87 
88 IPvXAddress AccessNet::addOverlayNode(cModule* node, bool migrate)
89 {
90  Enter_Method("addOverlayNode()");
91 
92  TerminalInfo terminal;
93  terminal.module = node;
94  terminal.interfaceTable = IPAddressResolver().interfaceTableOf(node);
96  if (useIPv6) {
97  terminal.routingTable6 = IPAddressResolver().routingTable6Of(node);
98  }
99  else {
100  terminal.routingTable = IPAddressResolver().routingTableOf(node);
101  }
102  terminal.PPPInterface = node->getSubmodule("ppp", 0);
103  terminal.createdAt = simTime();
104 
105  // find unassigned ip address:
106  // check list of returned IPs
107  // TODO: check overlays for side effects of reused IP addresses
108 // if (returnedIPs.size() != 0) {
109 // terminal.IPAddress = returnedIPs.back();
110 // returnedIPs.pop_back();
111 // }
112 // else {
113  if (useIPv6) {
114  IPv6Words candidate(router.IPAddress);
115  // we dont need to check for duplicates because of the giant address space and reuse of old IPs
116  candidate.d1 += ++lastIP;
117  terminal.IPAddress = IPvXAddress(IPv6Address(candidate.d0, candidate.d1, candidate.d2, candidate.d3));
118  } else {
119  uint32_t routerAddr = router.IPAddress.get4().getInt();
120 
121  // Start at last given address, check if next address is valid and free.
122  bool ip_test = false;
123  for (uint32 ipOffset = lastIP + 1; ipOffset != lastIP; ipOffset++) {
124  if ( ipOffset == 0x10000) {
125  // Netmask = 255.255.0.0, so roll over if offset = 2**16
126  ipOffset = 0;
127  continue;
128  }
129 
130  uint32_t ip = routerAddr + ipOffset;
131 
132  // Check if IP is valid:
133  // Reject x.y.z.0 or x.y.z.255 or x.y.255.z
134  if ( ((ip & 0xff) == 0) || ((ip & 0xff) == 0xff)
135  || ((ip & 0xff00) == 0xff00) ) {
136  continue;
137  }
138 
139  // Check if IP is free
140  ip_test = true;
141  for (uint32_t i = 0; i < overlayTerminal.size(); i++) {
142  if (overlayTerminal[i].IPAddress == ip) {
143  ip_test = false;
144  break;
145  }
146  }
147 
148  // found valid IP
149  if (ip_test) {
150  terminal.IPAddress = IPvXAddress(ip);
151  lastIP = ipOffset;
152  break;
153  }
154  }
155  if (!ip_test)
156  opp_error ("Error creating node: No available IP in access net!");
157  }
158 // }
159 
160  // update ip display string
161  if (ev.isGUI()) {
162  const char* ip_disp = const_cast<char*>
163  (terminal.IPAddress.str().c_str());
164  terminal.module->getDisplayString().insertTag("t", 0);
165  terminal.module->getDisplayString().setTagArg("t", 0, ip_disp);
166  terminal.module->getDisplayString().setTagArg("t", 1, "l");
167  }
168 
169 
170  //
171  // Create new remote ppp interface module for this terminal
172  //
173 
174  // create ppp interface module
175 
176  int k = 1;
177  while ( router.module->findSubmodule("ppp", k) != -1 )
178  k++;
179 
180  cModuleType* pppInterfaceModuleType = cModuleType::get("inet.linklayer.ppp.PPPInterface");
181  terminal.remotePPPInterface = pppInterfaceModuleType->
182  create("ppp", router.module, 0, k);
183 
184 
185  //
186  // Connect all gates
187  //
188 
189  // connect terminal to access router and vice versa
190  cGate* routerInGate = firstUnusedGate(router.module, "pppg", cGate::INPUT);
191  cGate* routerOutGate = firstUnusedGate(router.module, "pppg", cGate::OUTPUT);
192 
193  cChannelType* channelTypeRx = cChannelType::find( channelTypeRxStr.c_str() );
194  cChannelType* channelTypeTx = cChannelType::find( channelTypeTxStr.c_str() );
195  if (!channelTypeRx || !channelTypeTx)
196  opp_error("Could not find Channel or ChannelRx Type. Most likely "
197  "parameter channelTypes does not match the channels defined "
198  "in channels.ned");
199 
200  terminal.module->gate("pppg$o", 0)->connectTo(routerInGate,
201  channelTypeRx->create(channelTypeRxStr.c_str()));
202  routerOutGate->connectTo(terminal.module->gate("pppg$i", 0),
203  channelTypeTx->create(channelTypeTxStr.c_str()));
204 
205  // connect ppp interface module to router module and vice versa
206  routerInGate->connectTo(terminal.remotePPPInterface->gate("phys$i"));
207  terminal.remotePPPInterface->gate("phys$o")->connectTo(routerOutGate);
208 
209  // connect ppp interface module to network layer module and vice versa
210  cModule* netwModule = router.module->getSubmodule("networkLayer");
211 
212  cGate* netwInGate = firstUnusedGate(netwModule, "ifIn");
213  cGate* netwOutGate = firstUnusedGate(netwModule, "ifOut");
214 
215  netwOutGate->connectTo(terminal.remotePPPInterface->gate("netwIn"));
216  terminal.remotePPPInterface->gate("netwOut")->connectTo(netwInGate);
217 
218  // connect network layer module to ip and arp modules
219  cModule* ipModule;
220  if (useIPv6) {
221  ipModule = router.module->getSubmodule("networkLayer")->getSubmodule("ipv6");
222  }
223  else {
224  ipModule = router.module->getSubmodule("networkLayer")->getSubmodule("ip");
225  }
226 
227  cGate* ipIn = firstUnusedGate(ipModule, "queueIn");
228  netwInGate->connectTo(ipIn);
229 
230  cModule* arpModule = NULL;
231 
232  if(useIPv6) {
233  arpModule = router.module->getSubmodule("networkLayer")->getSubmodule("neighbourDiscovery"); //comment out for speed-hack
234  } else {
235  arpModule = router.module->getSubmodule("networkLayer")->getSubmodule("arp"); //comment out for speed-hack
236  cGate* arpOut = firstUnusedGate(arpModule, "nicOut"); //comment out for speed-hack
237  arpOut->connectTo(netwOutGate); //comment out for speed-hack
238 
239  }
240 
241  //
242  // Start ppp interface modules
243  //
244  terminal.remotePPPInterface->finalizeParameters();
245  terminal.remotePPPInterface->setDisplayString("i=block/ifcard");
246  terminal.remotePPPInterface->buildInside();
247  terminal.remotePPPInterface->scheduleStart(simTime());
248  terminal.remotePPPInterface->callInitialize();
249 
250  if (!migrate) {
251  // we are already in stage 4 and need to call initialize
252  // for all previous stages manually
253  for (int i=0; i < MAX_STAGE_UNDERLAY + 1; i++) {
254  terminal.module->callInitialize(i);
255  }
256  }
257 
258  terminal.remoteInterfaceEntry = router.interfaceTable->getInterface(
259  router.interfaceTable->getNumInterfaces() - 1);
260  terminal.interfaceEntry = terminal.interfaceTable->getInterfaceByName("ppp0");
261 
262 
263  //
264  // Fill in interface table and routing table.
265  //
266 
267  if (useIPv6) {
268  //
269  // Fill in interface table.
270 
271  // router
272  IPv6InterfaceData* interfaceData = new IPv6InterfaceData;
273  interfaceData->setAdvSendAdvertisements(true); // router
274  interfaceData->assignAddress(IPv6Address::formLinkLocalAddress(terminal.remoteInterfaceEntry->getInterfaceToken()), false, 0, 0);
275  terminal.remoteInterfaceEntry->setIPv6Data(interfaceData);
276  terminal.remoteInterfaceEntry->setMACAddress(MACAddress::generateAutoAddress());
277 
278  // terminal
279  terminal.interfaceEntry->ipv6Data()->setAdvSendAdvertisements(false); // host
280  terminal.interfaceEntry->ipv6Data()->assignAddress(terminal.IPAddress.get6(), false, 0, 0);
281  terminal.interfaceEntry->ipv6Data()->assignAddress(IPv6Address::formLinkLocalAddress(terminal.interfaceEntry->getInterfaceToken()), false, 0, 0);
282  terminal.interfaceEntry->setMACAddress(MACAddress::generateAutoAddress());
283 
284  //
285  // Fill in routing table.
286  //
287 
288  // router
289  router.routingTable6->addStaticRoute(terminal.IPAddress.get6(),64, terminal.remoteInterfaceEntry->getInterfaceId(), terminal.interfaceEntry->ipv6Data()->getLinkLocalAddress());
290 
291  // terminal
292  terminal.routingTable6->addDefaultRoute(terminal.remoteInterfaceEntry->ipv6Data()->getLinkLocalAddress(), terminal.interfaceEntry->getInterfaceId(), 0);
293 
294  } else {
295 
296  //
297  // Fill in interface table.
298  //
299 
300  // router
301  IPv4InterfaceData* interfaceData = new IPv4InterfaceData;
302  interfaceData->setIPAddress(router.IPAddress.get4());
303  interfaceData->setNetmask(IPAddress::ALLONES_ADDRESS);
304  terminal.remoteInterfaceEntry->setIPv4Data(interfaceData);
305 
306  // terminal
307  terminal.interfaceEntry->ipv4Data()->setIPAddress(terminal.IPAddress.get4());
308  terminal.interfaceEntry->ipv4Data()->setNetmask(IPAddress::ALLONES_ADDRESS);
309 
310  //
311  // Fill in routing table.
312  //
313 
314  // router
315  IPRoute* re = new IPRoute();
316  re->setHost(terminal.IPAddress.get4());
317  re->setNetmask(IPAddress(IPAddress::ALLONES_ADDRESS));
318  re->setInterface(terminal.remoteInterfaceEntry);
319  re->setType(IPRoute::DIRECT);
320  re->setSource(IPRoute::MANUAL);
321  router.routingTable->addRoute(re);
322  terminal.remoteRoutingEntry = re;
323 
324  // terminal
325  IPRoute* te = new IPRoute();
326  te->setHost(IPAddress::UNSPECIFIED_ADDRESS);
327  te->setNetmask(IPAddress::UNSPECIFIED_ADDRESS);
328  te->setGateway(router.IPAddress.get4());
329  te->setInterface(terminal.interfaceEntry);
330  te->setType(IPRoute::REMOTE);
331  te->setSource(IPRoute::MANUAL);
332  terminal.routingTable->addRoute(te);
333  terminal.routingEntry = te;
334 
335  }
336 
337 
338  // append module to overlay terminal vector
339  overlayTerminal.push_back(terminal);
340  //int ID = terminal.module->getId();
341 
343 
344  return terminal.IPAddress;
345 }
346 
348 {
349  Enter_Method("getRandomNodeId()");
350 
351  return overlayTerminal[intuniform(0, overlayTerminal.size() - 1)].module->getId();
352 }
353 
355 {
356  Enter_Method("removeOverlayNode()");
357 
358  cModule* node = NULL;
359  TerminalInfo terminal;
360  int index;
361 
362  for(unsigned int i=0; i<overlayTerminal.size(); i++) {
363  if(overlayTerminal[i].module->getId() == ID) {
364  terminal = overlayTerminal[i];
365  node = terminal.module;
366  index = i;
367  }
368  }
369 
370  if(node == NULL) return NULL;
371 
372  cModule* ppp = terminal.remotePPPInterface;
373 
374  // disconnect terminal
375  node->gate("pppg$o", 0)->disconnect();
376  node->gate("pppg$i", 0)->getPreviousGate()->disconnect();
377 
378  // disconnect ip and arp modules
379  ppp->gate("netwIn")->getPathStartGate()->disconnect();
380  ppp->gate("netwOut")->getNextGate()->disconnect();
381 
382  // remove associated ppp interface module
383  ppp->callFinish();
384  ppp->deleteModule();
385 
386  // remove associated interface table entry
387  router.interfaceTable->deleteInterface(terminal.remoteInterfaceEntry);
388 
389  // remove routing entries //TODO: IPv6
390  if (!useIPv6) {
391  terminal.routingTable->deleteRoute(terminal.routingEntry);
392  router.routingTable->deleteRoute(terminal.remoteRoutingEntry);
393  } else {
394 #if 0
395  for (int i = 0; i < terminal.routingTable6->getNumRoutes(); i++) {
396  IPv6Route* route = terminal.routingTable6->getRoute(i);
397  if (route->getDestPrefix() == terminal.remoteInterfaceEntry->
398  ipv6Data()->getLinkLocalAddress()) {
399  terminal.routingTable6->purgeDestCacheEntriesToNeighbour(terminal.remoteInterfaceEntry->ipv6Data()->getLinkLocalAddress(), route->getInterfaceId());
400  terminal.routingTable6->removeRoute(route);
401  }
402  }
403 #endif
404 
405  for (int i = 0; i < router.routingTable6->getNumRoutes(); i++) {
406  IPv6Route* route = router.routingTable6->getRoute(i);
407  if (route->getDestPrefix() == terminal.IPAddress.get6()) {
408  router.routingTable6->purgeDestCacheEntriesToNeighbour(terminal.interfaceEntry->ipv6Data()->getLinkLocalAddress(), route->getInterfaceId());
409  router.routingTable6->removeRoute(route);
410  break;
411  }
412  }
413  }
414 
415  // statistics
416  lifetimeVector.record(simTime() - overlayTerminal[index].createdAt);
417 
418  // remove terminal from overlay terminal vector
419  overlayTerminal.erase(overlayTerminal.begin() + index);
420 
422 
423  return node;
424 }
425 
427 {
428  Enter_Method("getOverlayNode()");
429 
430  cModule* node = NULL;
431 
432  for(unsigned int i=0; i<overlayTerminal.size(); i++) {
433  if(overlayTerminal[i].module->getId() == ID)
434  node = overlayTerminal[i].module;
435  }
436  return node;
437 }
438 
440 {
441  if (ev.isGUI()) {
442  char buf[80];
443  if ( overlayTerminal.size() == 1 ) {
444  sprintf(buf, "1 terminal connected");
445  } else {
446  sprintf(buf, "%zi terminals connected", overlayTerminal.size());
447  }
448  getDisplayString().setTagArg("t", 0, buf);
449  getDisplayString().setTagArg("t", 2, "blue");
450  }
451 }
452 
453 cGate* firstUnusedGate(cModule* owner, const char* name, cGate::Type type)
454 {
455  int index;
456  for (index = 0; index < owner->gateSize(name); index++) {
457  cGate *gate = type == cGate::NONE ? owner->gate(name, index) : owner->gateHalf(name, type, index);
458  if (!gate->isConnectedOutside()) {
459  return gate;
460  }
461  }
462 
463  owner->setGateSize(name, index + 2);
464  return type == cGate::NONE ? owner->gate(name, index + 1) : owner->gateHalf(name, type, index + 1);
465 }
466 
467 IPvXAddress AccessNet::getAssignedPrefix(IInterfaceTable* ift)
468 {
469  //FIXME: support multiple prefixes
470  for (int i = 0; i< ift->getNumInterfaces(); i++) {
471  if (!ift->getInterface(i)->isLoopback()) {
472  if (ift->getInterface(i)->ipv6Data()->getNumAdvPrefixes() == 1)
473  return ift->getInterface(i)->ipv6Data()->getAdvPrefix(0).prefix;
474  else
475  opp_error("Prefix is not unique.");
476  }
477  }
478  return IPvXAddress();
479 }