INET Framework for OMNeT++/OMNEST
inet::Ipv6Tunneling Class Reference

Management of IP tunnels. More...

#include <Ipv6Tunneling.h>

Inheritance diagram for inet::Ipv6Tunneling:
inet::LifecycleUnsupported inet::ILifecycle

Classes

struct  equalTunnel
 
struct  Tunnel
 

Public Types

enum  TunnelType {
  INVALID = 0, SPLIT, NON_SPLIT, NORMAL,
  T2RH, HA_OPT, MOBILITY
}
 

Public Member Functions

 Ipv6Tunneling ()
 
virtual void initialize (int stage) override
 Initialize tunnel manager. More...
 
virtual int numInitStages () const override
 
virtual void handleMessage (cMessage *msg) override
 Receive messages from Ipv6 module and encapsulate/decapsulate them. More...
 
int createTunnel (TunnelType tunnelType, const Ipv6Address &src, const Ipv6Address &dest, const Ipv6Address &destTrigger=Ipv6Address::UNSPECIFIED_ADDRESS)
 Creates a tunnel with given entry and exit point, which will be used for datagrams destined for destTrigger. More...
 
bool destroyTunnel (const Ipv6Address &src, const Ipv6Address &dest, const Ipv6Address &destTrigger)
 Creates a pseudo-tunnel for use with either Type 2 Routing Header or Home Address Option with given entry and exit point, which will be used for datagrams destined for destTrigger. More...
 
void destroyTunnels (const Ipv6Address &entry)
 Remove all tunnels with provided entry point. More...
 
void destroyTunnel (const Ipv6Address &entry, const Ipv6Address &exit)
 Remove the tunnel with the provided entry and exit point. More...
 
void destroyTunnelForExitAndTrigger (const Ipv6Address &exit, const Ipv6Address &trigger)
 Remove the tunnel with the provided exit point and trigger. More...
 
void destroyTunnelForEntryAndTrigger (const Ipv6Address &entry, const Ipv6Address &trigger)
 Remove the tunnel with the provided entry point and trigger. More...
 
void destroyTunnelFromTrigger (const Ipv6Address &trigger)
 Remove the tunnel with the provided destination trigger. More...
 
int getVIfIndexForDest (const Ipv6Address &destAddress)
 Returns the virtual interface identifier for the tunnel which has the provided destination as destination trigger. More...
 
virtual int getVIfIndexForDest (const Ipv6Address &destAddress, TunnelType tunnelType)
 This method is equivalent for getVIfIndexForDest() except that it only searches for either "normal" or mobility tunnels. More...
 
bool isTunnelExit (const Ipv6Address &exit)
 This method is equivalent for getVIfIndexForDest() except that it only searches for pseudo tunnels (T2RH, etc.). More...
 
- Public Member Functions inherited from inet::LifecycleUnsupported
virtual bool handleOperationStage (LifecycleOperation *operation, IDoneCallback *doneCallback) override
 Perform one stage of a lifecycle operation. More...
 
- Public Member Functions inherited from inet::ILifecycle
virtual ~ILifecycle ()
 

Protected Types

typedef std::map< int, struct TunnelTunnels
 
typedef Tunnels::const_iterator TI
 

Protected Member Functions

int findTunnel (const Ipv6Address &src, const Ipv6Address &dest, const Ipv6Address &destTrigger) const
 Returns the type of the tunnels: non-split, split, T2RH, ... More...
 
void encapsulateDatagram (Packet *packet)
 Encapsulate a datagram with tunnel headers. More...
 
void decapsulateDatagram (Packet *packet)
 Strip tunnel headers from datagram. More...
 

Protected Attributes

ModuleRefByPar< IInterfaceTableift
 
ModuleRefByPar< Ipv6RoutingTablert
 
Tunnels tunnels
 
int vIfIndexTop = 0
 
int noOfNonSplitTunnels = 0
 

Private Member Functions

int lookupTunnels (const Ipv6Address &dest)
 Search through all tunnels and locate one entry which is anything but a non-split tunnel and has a destination trigger for the provided address. More...
 
int doPrefixMatch (const Ipv6Address &dest)
 Search through all tunnels and locate one entry which is a non-split tunnel (later on this could be exteded to searching for a tunnel that has a prefix matching the provided address). More...
 
void resetVIfIndex ()
 Reset the vIfIndex to its starting value if no tunnels exist anymore. More...
 

Friends

std::ostream & operator<< (std::ostream &os, const Ipv6Tunneling::Tunnel &tun)
 

Detailed Description

Management of IP tunnels.

Member Typedef Documentation

◆ TI

typedef Tunnels::const_iterator inet::Ipv6Tunneling::TI
protected

◆ Tunnels

typedef std::map<int, struct Tunnel> inet::Ipv6Tunneling::Tunnels
protected

Member Enumeration Documentation

◆ TunnelType

Enumerator
INVALID 
SPLIT 
NON_SPLIT 
NORMAL 
T2RH 
HA_OPT 
MOBILITY 
40  {
41  INVALID = 0,
42  SPLIT,
43  NON_SPLIT,
44  NORMAL, // either split or non-split
45  T2RH,
46  HA_OPT,
47  MOBILITY // either T2RH or HA_OPT
48  };

Constructor & Destructor Documentation

◆ Ipv6Tunneling()

inet::Ipv6Tunneling::Ipv6Tunneling ( )
52 {
53 }

Member Function Documentation

◆ createTunnel()

int inet::Ipv6Tunneling::createTunnel ( TunnelType  tunnelType,
const Ipv6Address src,
const Ipv6Address dest,
const Ipv6Address destTrigger = Ipv6Address::UNSPECIFIED_ADDRESS 
)

Creates a tunnel with given entry and exit point, which will be used for datagrams destined for destTrigger.

Type of tunnel (normal tunnel, mobility related pseudo-tunnel) is determined by first parameter. Returns virtual interface index.

100 {
101  ASSERT(entry != Ipv6Address::UNSPECIFIED_ADDRESS);
102  ASSERT(exit != Ipv6Address::UNSPECIFIED_ADDRESS);
103 
104  // Test for entry and exit point node pointing to same node i.e. localDeliver
105  // addresses to prevent loopback encapsulation 4.1.2
106  if ((tunnelType == NORMAL || tunnelType == SPLIT || tunnelType == NON_SPLIT) // check does not work for T2RH or HoA_Opt. Why?
107  && rt->isLocalAddress(entry) && rt->isLocalAddress(exit))
108  {
109  EV_INFO << "Cannot create tunnel with local endpoints (prevents loopback tunneling)" << endl;
110  return 0;
111  }
112 
113  int search = findTunnel(entry, exit, destTrigger);
114  if (search != 0) {
115  EV_INFO << "Tunnel with entry = " << entry << ", exit = " << exit << " and trigger = "
116  << destTrigger << " already exists!" << endl;
117  return search;
118  }
119 
120  if (vIfIndexTop <= (ift->getBiggestInterfaceId()))
121  throw cRuntimeError("Error: Not more than %d tunnels supported!", INT_MAX - ift->getBiggestInterfaceId());
122 
123  if ((destTrigger == Ipv6Address::UNSPECIFIED_ADDRESS) && (noOfNonSplitTunnels == 1))
124  throw cRuntimeError("Error: Not more than 1 non-split tunnel supported!");
125 
126  // 6.1-6.2
127  ASSERT(entry.isUnicast());
128  tunnels[vIfIndexTop] = Tunnel(entry, exit, destTrigger);
129 
130  if (tunnelType == NORMAL || tunnelType == SPLIT || tunnelType == NON_SPLIT) {
131  if (destTrigger == Ipv6Address::UNSPECIFIED_ADDRESS) {
132  // this is a "full" tunnel over which everything gets routed
133  tunnels[vIfIndexTop].tunnelType = NON_SPLIT;
135  }
136 
137  // default values: 5.
138  // 6.4
139  tunnels[vIfIndexTop].trafficClass = 0;
140 
141  // 6.5
142  tunnels[vIfIndexTop].flowLabel = 0;
143 
144  // 6.3
145  // The tunnel hop limit default value for hosts is the Ipv6 Neighbor
146  // Discovery advertised hop limit [ND-Spec].
147  if (rt->isRouter())
149  else
150  tunnels[vIfIndexTop].hopLimit = 255;
151 
152  // 6.7
153  // TODO perform path MTU on link (interface resolved via exit address)
154  tunnels[vIfIndexTop].tunnelMTU = IPv6_MIN_MTU - 40;
155 
156  EV_INFO << "Tunneling: Created tunnel with entry=" << entry << ", exit=" << exit
157  << " and trigger=" << destTrigger << endl;
158  }
159  else if (tunnelType == T2RH || tunnelType == HA_OPT) {
160  tunnels[vIfIndexTop].tunnelType = tunnelType;
161 
162  if (tunnelType == T2RH)
163  EV_INFO << "Tunneling: Created RH2 path with entry=" << entry << ", exit=" << exit
164  << " and trigger=" << destTrigger << endl;
165  else
166  EV_INFO << "Tunneling: Created HA option path with entry=" << entry << ", exit=" << exit
167  << " and trigger=" << destTrigger << endl;
168  }
169  else {
170  throw cRuntimeError("tunnel type %d not supported for createTunnel()", tunnelType);
171  }
172 
173  if (hasGUI())
174  bubble("Created Tunnel");
175 
176  return vIfIndexTop--; // decrement vIfIndex for use with next createTunnel() call
177 }

Referenced by inet::Ipv6RoutingTable::configureTunnelFromXml().

◆ decapsulateDatagram()

void inet::Ipv6Tunneling::decapsulateDatagram ( Packet packet)
protected

Strip tunnel headers from datagram.

464 {
465  auto ipv6Header = packet->peekAtFront<Ipv6Header>();
466  // decapsulation is performed in Ipv6 module
467  Ipv6Address srcAddr = packet->getTag<L3AddressInd>()->getSrcAddress().toIpv6();
468 
469 #ifdef INET_WITH_xMIPv6
470  // we only decapsulate packets for which we have a tunnel
471  // where the exit point is equal to the packets source
472  // 11.9.07 - CB
473  if (rt->isHomeAgent() && !isTunnelExit(srcAddr)) {
474  /*RFC 3775, 10.4.5
475  Otherwise, when a home agent decapsulates a tunneled packet from
476  the mobile node, the home agent MUST verify that the Source
477  Address in the tunnel IP header is the mobile node's primary
478  care-of address. Otherwise, any node in the Internet could send
479  traffic through the home agent and escape ingress filtering
480  limitations. This simple check forces the attacker to know the
481  current location of the real mobile node and be able to defeat
482  ingress filtering. This check is not necessary if the reverse-
483  tunneled packet is protected by ESP in tunnel mode.*/
484  EV_INFO << "Dropping packet: source address of tunnel IP header different from tunnel exit points!" << endl;
485  delete packet;
486  return;
487  }
488 #endif // ifdef INET_WITH_xMIPv6
489 
490  // FIX: we leave the interface Id to it's previous value to make sure
491  // that later processing knowns from which interface the datagram came from
492  // (important if several interfaces are available)
493 // controlInfo->setInterfaceId(-1);
494 
495  send(packet, "linkLayerOut");
496 
497 #ifdef INET_WITH_xMIPv6
498  // Alain Tigyo, 21.03.2008
499  // The following code is used for triggering RO to a CN
500  NetworkInterface *ie = ift->getInterfaceById(packet->getTag<InterfaceInd>()->getInterfaceId());
501  if (rt->isMobileNode() && (srcAddr == ie->getProtocolData<Ipv6InterfaceData>()->getHomeAgentAddress())
502  && (ipv6Header->getProtocolId() != IP_PROT_IPv6EXT_MOB))
503  {
504  EV_INFO << "Checking Route Optimization for: " << ipv6Header->getSrcAddress() << endl;
505  xMIPv6 *mipv6 = findModuleFromPar<xMIPv6>(par("xmipv6Module"), this);
506  if (mipv6)
507  mipv6->triggerRouteOptimization(ipv6Header->getSrcAddress(), ie->getProtocolData<Ipv6InterfaceData>()->getMNHomeAddress(), ie);
508  }
509 #endif // ifdef INET_WITH_xMIPv6
510 }

Referenced by handleMessage().

◆ destroyTunnel() [1/2]

void inet::Ipv6Tunneling::destroyTunnel ( const Ipv6Address entry,
const Ipv6Address exit 
)

Remove the tunnel with the provided entry and exit point.

225 {
226  for (auto it = tunnels.begin(); it != tunnels.end();) {
227  if (it->second.entry == entry && it->second.exit == exit) {
228  destroyTunnel(it->second.entry, it->second.exit, it->second.destTrigger);
229  break;
230  }
231  else
232  ++it;
233  }
234 
235  // reset the index if we do not have a single tunnel anymore
236  resetVIfIndex();
237 }

◆ destroyTunnel() [2/2]

bool inet::Ipv6Tunneling::destroyTunnel ( const Ipv6Address src,
const Ipv6Address dest,
const Ipv6Address destTrigger 
)

Creates a pseudo-tunnel for use with either Type 2 Routing Header or Home Address Option with given entry and exit point, which will be used for datagrams destined for destTrigger.

Returns virtual interface index. Remove tunnel and the associated entries from destination cache

195 {
196  EV_INFO << "Destroy tunnel entry =" << src << ", exit = " << dest
197  << ", destTrigger = " << destTrigger << "\n";
198 
199  // search for tunnel with given entry and exit point as well as trigger
200  int vIfIndex = findTunnel(src, dest, destTrigger);
201 
202  if (vIfIndex == 0) {
203  EV_WARN << "Tunnel not found\n";
204  return false;
205  }
206 
207  // if we delete a non-split tunnel, then we can
208  // also decrement the appropriate counter
209  if (tunnels[vIfIndex].tunnelType == NON_SPLIT)
211 
212  // TODO store vIfIndex for later reuse when creating a new tunnel
213  tunnels.erase(vIfIndex);
214 
215  // reset the index if we do not have a single tunnel anymore
216  resetVIfIndex();
217 
218  if (hasGUI())
219  bubble("Destroyed Tunnel");
220 
221  return true;
222 }

Referenced by destroyTunnel(), destroyTunnelForEntryAndTrigger(), destroyTunnelForExitAndTrigger(), destroyTunnelFromTrigger(), and destroyTunnels().

◆ destroyTunnelForEntryAndTrigger()

void inet::Ipv6Tunneling::destroyTunnelForEntryAndTrigger ( const Ipv6Address entry,
const Ipv6Address trigger 
)

Remove the tunnel with the provided entry point and trigger.

255 {
256  for (auto it = tunnels.begin(); it != tunnels.end();) {
257  if (it->second.entry == entry && it->second.destTrigger == trigger) {
258  destroyTunnel(it->second.entry, it->second.exit, it->second.destTrigger);
259  break;
260  }
261  else
262  ++it;
263  }
264 
265  // reset the index if we do not have a single tunnel anymore
266  resetVIfIndex();
267 }

◆ destroyTunnelForExitAndTrigger()

void inet::Ipv6Tunneling::destroyTunnelForExitAndTrigger ( const Ipv6Address exit,
const Ipv6Address trigger 
)

Remove the tunnel with the provided exit point and trigger.

240 {
241  for (auto it = tunnels.begin(); it != tunnels.end();) {
242  if (it->second.exit == exit && it->second.destTrigger == trigger) {
243  destroyTunnel(it->second.entry, it->second.exit, it->second.destTrigger);
244  break;
245  }
246  else
247  ++it;
248  }
249 
250  // reset the index if we do not have a single tunnel anymore
251  resetVIfIndex();
252 }

◆ destroyTunnelFromTrigger()

void inet::Ipv6Tunneling::destroyTunnelFromTrigger ( const Ipv6Address trigger)

Remove the tunnel with the provided destination trigger.

287 {
288  for (auto& elem : tunnels) {
289  if (elem.second.destTrigger == trigger) {
290  destroyTunnel(elem.second.entry, elem.second.exit, elem.second.destTrigger);
291 
292  // reset the index if we do not have a single tunnel anymore
293  resetVIfIndex();
294 
295  return; // there can not be more than one tunnel for a trigger
296  }
297  }
298 }

◆ destroyTunnels()

void inet::Ipv6Tunneling::destroyTunnels ( const Ipv6Address entry)

Remove all tunnels with provided entry point.

270 {
271  for (auto it = tunnels.begin(); it != tunnels.end();) {
272  if (it->second.entry == entry) {
273  auto oldIt = it;
274  ++it;
275 
276  destroyTunnel(oldIt->second.entry, oldIt->second.exit, oldIt->second.destTrigger);
277  }
278  else
279  ++it;
280  }
281 
282  // reset the index if we do not have a single tunnel anymore
283  resetVIfIndex();
284 }

◆ doPrefixMatch()

int inet::Ipv6Tunneling::doPrefixMatch ( const Ipv6Address dest)
private

Search through all tunnels and locate one entry which is a non-split tunnel (later on this could be exteded to searching for a tunnel that has a prefix matching the provided address).

530 {
531  int outInterfaceId = -1;
532 
533  // we'll just stop at the first match, because it is assumed that not
534  // more than a single non-split tunnel is possible
535  for (auto& elem : tunnels) {
536  if (elem.second.tunnelType == NON_SPLIT) {
537  outInterfaceId = elem.first;
538  break;
539  }
540  }
541 
542  return outInterfaceId;
543 }

Referenced by encapsulateDatagram(), and getVIfIndexForDest().

◆ encapsulateDatagram()

void inet::Ipv6Tunneling::encapsulateDatagram ( Packet packet)
protected

Encapsulate a datagram with tunnel headers.

Attaches a Type 2 Routing Header in the control info if the datagram is routed over an appropriate RH2 pseudo tunnel.

350 {
351  auto ipv6Header = packet->peekAtFront<Ipv6Header>();
352  int vIfIndex = -1;
353 
354  if (ipv6Header->getProtocolId() == IP_PROT_IPv6EXT_MOB) {
355  // only look at non-split tunnel
356  // (HoTI is only sent over HA tunnel)
357  vIfIndex = doPrefixMatch(ipv6Header->getDestAddress());
358  }
359 
360  if ((ipv6Header->getProtocolId() != IP_PROT_IPv6EXT_MOB) || (vIfIndex == -1)) {
361  // look up all tunnels for dgram's destination
362  vIfIndex = getVIfIndexForDest(ipv6Header->getDestAddress());
363 // EV << "looked up again!" << endl;
364  }
365 
366  if (vIfIndex == -1)
367  throw cRuntimeError("encapsulateDatagram(): tunnel not existent");
368 
369  // TODO copy information from old ctrlInfo into new one (Traffic Class, Flow label, etc.)
370  delete packet->removeControlInfo();
371 
372 #ifdef INET_WITH_xMIPv6
373  if ((tunnels[vIfIndex].tunnelType == T2RH) || (tunnels[vIfIndex].tunnelType == HA_OPT)) {
374  // pseudo-tunnel for Type 2 Routing Header
375  // or Home Address Option
376 
377  Ipv6Address src = ipv6Header->getSrcAddress();
378  Ipv6Address dest = ipv6Header->getDestAddress();
379  Ipv6Address rh2; // dest
380 
381  if (src.isUnspecified()) {
382  // if we do not have a valid source address, we'll have to ask
383  // the routing table for the correct interface.
384  int interfaceId;
385  (void)(rt->lookupDestCache(dest, interfaceId));
386  }
387 
388  if (tunnels[vIfIndex].tunnelType == T2RH) { // update 15.01.08 - CB
389  // this is the CN -> MN path
390  src = tunnels[vIfIndex].entry; // CN address
391  dest = tunnels[vIfIndex].exit; // CoA
392  rh2 = tunnels[vIfIndex].destTrigger; // HoA
393  }
394  else {
395  // path MN -> CN
396  src = tunnels[vIfIndex].entry; // CoA
397  dest = tunnels[vIfIndex].destTrigger; // CN address
398  rh2 = tunnels[vIfIndex].exit; // HoA
399  }
400 
401  // get rid of the encapsulation of the Ipv6 module
402  packet->popAtFront<Ipv6Header>();
403  packet->addTagIfAbsent<PacketProtocolTag>()->setProtocol(ipv6Header->getProtocol());
404 
405  if (tunnels[vIfIndex].tunnelType == T2RH) {
406  // construct Type 2 Routing Header (RFC 3775 - 6.4.1)
407  /*For a type 2 routing header, the Hdr Ext Len MUST be 2. The Segments
408  Left value describes the number of route segments remaining; i.e.,
409  number of explicitly listed intermediate nodes still to be visited
410  before reaching the final destination. Segments Left MUST be 1.*/
411  Ipv6RoutingHeader *t2RH = new Ipv6RoutingHeader();
412  t2RH->setRoutingType(2);
413  t2RH->setSegmentsLeft(1);
414  t2RH->setAddressArraySize(1);
415  t2RH->setByteLength(B(8 + 1 * 16));
416  // old src becomes address of T2RH
417  t2RH->setAddress(0, rh2);
418 
419  // append T2RH to routing headers
420  packet->addTagIfAbsent<Ipv6ExtHeaderReq>()->appendExtensionHeader(t2RH);
421 
422  EV_INFO << "Added Type 2 Routing Header." << endl;
423  }
424  else { // HA_OPT
425  /*The Home Address option is carried by the Destination Option
426  extension header (Next Header value = 60). It is used in a packet
427  sent by a mobile node while away from home, to inform the recipient
428  of the mobile node's home address.*/
429  HomeAddressOption *haOpt = new HomeAddressOption();
430  haOpt->setHomeAddress(rh2);
431 
432  // append HA option to routing headers
433  packet->addTagIfAbsent<Ipv6ExtHeaderReq>()->appendExtensionHeader(haOpt);
434 
435  EV_INFO << "Added Home Address Option header." << endl;
436  }
437 
438  auto addresses = packet->addTagIfAbsent<L3AddressReq>();
439  // new src is tunnel entry (either CoA or CN)
440  addresses->setSrcAddress(src);
441  // copy old dest addr
442  addresses->setDestAddress(dest);
443 
444  send(packet, "upperLayerOut");
445  }
446  else {
447 #endif // INET_WITH_xMIPv6
448  // normal tunnel - just modify controlInfo and send
449  // datagram back to Ipv6 module for encapsulation
450 
451  packet->addTagIfAbsent<PacketProtocolTag>()->setProtocol(&Protocol::ipv6);
452  auto addresses = packet->addTagIfAbsent<L3AddressReq>();
453  addresses->setSrcAddress(tunnels[vIfIndex].entry);
454  addresses->setDestAddress(tunnels[vIfIndex].exit);
455 
456  send(packet, "upperLayerOut");
457 #ifdef INET_WITH_xMIPv6
458 }
459 
460 #endif // ifdef INET_WITH_xMIPv6
461 }

Referenced by handleMessage().

◆ findTunnel()

int inet::Ipv6Tunneling::findTunnel ( const Ipv6Address src,
const Ipv6Address dest,
const Ipv6Address destTrigger 
) const
protected

Returns the type of the tunnels: non-split, split, T2RH, ...

Returns the vIfIndex of tunnel if found, 0 otherwise.

181 {
182  TI it = std::find_if(tunnels.begin(), tunnels.end(),
183  std::bind(equalTunnel(),
184  std::make_pair((int)0, Tunnel(src, dest, destTrigger)),
185  std::placeholders::_1));
186 
187  if (it != tunnels.end())
188  return it->first;
189 
190  return 0;
191 }

Referenced by createTunnel(), and destroyTunnel().

◆ getVIfIndexForDest() [1/2]

int inet::Ipv6Tunneling::getVIfIndexForDest ( const Ipv6Address destAddress)

Returns the virtual interface identifier for the tunnel which has the provided destination as destination trigger.

This is done by first looking at the split tunnels; if no split tunnels are found, a prefix matching on the non-split tunnels is then performed. In case both searches do not return a search hit, a value of -1 is returned.

301 {
302 // Enter_Method("Looking up Tunnels (%s)", destAddress.str().c_str());
303  EV_INFO << "Looking up tunnels...";
304 
305  // first we look for tunnels with destAddress as trigger
306  int vIfIndex = lookupTunnels(destAddress);
307 
308  if (vIfIndex == -1) {
309  // then the only chance left for finding a suitable tunnel
310  // is to find a non-split tunnel
311  vIfIndex = doPrefixMatch(destAddress);
312  }
313 
314  EV_DETAIL << "found vIf=" << vIfIndex << endl;
315 
316  return vIfIndex;
317 }

Referenced by encapsulateDatagram().

◆ getVIfIndexForDest() [2/2]

int inet::Ipv6Tunneling::getVIfIndexForDest ( const Ipv6Address destAddress,
TunnelType  tunnelType 
)
virtual

This method is equivalent for getVIfIndexForDest() except that it only searches for either "normal" or mobility tunnels.

320 {
321  int outInterfaceId = -1;
322 
323  for (auto& elem : tunnels) {
324  if (tunnelType == NORMAL || tunnelType == NON_SPLIT || tunnelType == SPLIT) {
325  // we search here for tunnels which have a destination trigger and
326  // check whether the trigger is equal to the destination
327  // only "normal" tunnels, both split and non-split, are possible entry points
328  if ((elem.second.tunnelType == NON_SPLIT) ||
329  (elem.second.tunnelType == SPLIT && elem.second.destTrigger == destAddress))
330  {
331  outInterfaceId = elem.first;
332  break;
333  }
334  }
335  else if (tunnelType == MOBILITY || tunnelType == HA_OPT || tunnelType == T2RH) {
336  if (elem.second.tunnelType != NON_SPLIT &&
337  elem.second.tunnelType != SPLIT &&
338  elem.second.destTrigger == destAddress)
339  {
340  outInterfaceId = elem.first;
341  break;
342  }
343  }
344  }
345 
346  return outInterfaceId;
347 }

◆ handleMessage()

void inet::Ipv6Tunneling::handleMessage ( cMessage *  msg)
overridevirtual

Receive messages from Ipv6 module and encapsulate/decapsulate them.

78 {
79  Packet *packet = check_and_cast<Packet *>(msg);
80 
81  if (packet->getArrivalGate()->isName("upperLayerIn")) {
82  // decapsulate
83  decapsulateDatagram(packet);
84  }
85  else if (packet->getArrivalGate()->isName("linkLayerIn")) {
86  // encapsulate
87  encapsulateDatagram(packet);
88  }
89  else
90  throw cRuntimeError("Ipv6Tunneling: Unknown gate: %s!", packet->getArrivalGate()->getFullName());
91 }

◆ initialize()

void inet::Ipv6Tunneling::initialize ( int  stage)
overridevirtual

Initialize tunnel manager.

56 {
57  cSimpleModule::initialize(stage);
58 
59  if (stage == INITSTAGE_LOCAL) {
60  ift.reference(this, "interfaceTableModule", true);
61  rt.reference(this, "routingTableModule", true);
62 
63  vIfIndexTop = INT_MAX; // virtual interface number set to maximum int value
64  noOfNonSplitTunnels = 0; // current number of non-split tunnels on this host
65 
66  WATCH_MAP(tunnels);
67  }
68  else if (stage == INITSTAGE_NETWORK_LAYER) {
69  cModule *node = findContainingNode(this);
70  NodeStatus *nodeStatus = node ? check_and_cast_nullable<NodeStatus *>(node->getSubmodule("status")) : nullptr;
71  bool isOperational = (!nodeStatus) || nodeStatus->getState() == NodeStatus::UP;
72  if (!isOperational)
73  throw cRuntimeError("This module doesn't support starting in node DOWN state");
74  }
75 }

◆ isTunnelExit()

bool inet::Ipv6Tunneling::isTunnelExit ( const Ipv6Address exit)

This method is equivalent for getVIfIndexForDest() except that it only searches for pseudo tunnels (T2RH, etc.).

Check if there exists a tunnel with exit equal to the provided address.

546 {
547  for (auto& elem : tunnels) {
548  // mobility "tunnels" are not relevant for decapsulation
549  // 17.10.07 - same for Home Address Option
550  if (elem.second.tunnelType != T2RH && elem.second.tunnelType != HA_OPT
551  && elem.second.exit == exit)
552  {
553  return true;
554  }
555  }
556 
557  return false;
558 }

Referenced by decapsulateDatagram().

◆ lookupTunnels()

int inet::Ipv6Tunneling::lookupTunnels ( const Ipv6Address dest)
private

Search through all tunnels and locate one entry which is anything but a non-split tunnel and has a destination trigger for the provided address.

513 {
514  int outInterfaceId = -1;
515 
516  // we search here for tunnels which have a destination trigger and
517  // check whether the trigger is equal to the destination
518  // only split tunnels or mobility paths are possible entry points
519  for (auto& elem : tunnels) {
520  if ((elem.second.tunnelType != NON_SPLIT) && (elem.second.destTrigger == dest)) {
521  outInterfaceId = elem.first;
522  break;
523  }
524  }
525 
526  return outInterfaceId;
527 }

Referenced by getVIfIndexForDest().

◆ numInitStages()

virtual int inet::Ipv6Tunneling::numInitStages ( ) const
inlineoverridevirtual
130 { return NUM_INIT_STAGES; }

◆ resetVIfIndex()

void inet::Ipv6Tunneling::resetVIfIndex ( )
inlineprivate

Reset the vIfIndex to its starting value if no tunnels exist anymore.

253 { if (tunnels.size() == 0) vIfIndexTop = INT_MAX; };

Referenced by destroyTunnel(), destroyTunnelForEntryAndTrigger(), destroyTunnelForExitAndTrigger(), destroyTunnelFromTrigger(), and destroyTunnels().

Friends And Related Function Documentation

◆ operator<<

std::ostream& operator<< ( std::ostream &  os,
const Ipv6Tunneling::Tunnel tun 
)
friend
573 {
574  os << "tunnel entry = " << tun.entry << ", exit = " << tun.exit << ", tunnelMTU = "
575  << tun.tunnelMTU << ", dest = " << tun.destTrigger << ", type: ";
576 
577  switch (tun.tunnelType) {
579  os << "split tunnel";
580  break;
581 
583  os << "non-split tunnel";
584  break;
585 
586  case Ipv6Tunneling::T2RH:
587  os << "T2RH path";
588  break;
589 
591  os << "Home Address Option path";
592  break;
593 
594  default:
595  throw cRuntimeError("Not a valid type for an existing tunnel!");
596  break;
597  }
598 
599  os << endl;
600 
601  return os;
602 }

Member Data Documentation

◆ ift

ModuleRefByPar<IInterfaceTable> inet::Ipv6Tunneling::ift
protected

◆ noOfNonSplitTunnels

int inet::Ipv6Tunneling::noOfNonSplitTunnels = 0
protected

◆ rt

◆ tunnels

◆ vIfIndexTop

int inet::Ipv6Tunneling::vIfIndexTop = 0
protected

Referenced by createTunnel(), and initialize().


The documentation for this class was generated from the following files:
inet::findContainingNode
cModule * findContainingNode(const cModule *from)
Find the node containing the given module.
Definition: ModuleAccess.cc:31
inet::Ipv6Tunneling::doPrefixMatch
int doPrefixMatch(const Ipv6Address &dest)
Search through all tunnels and locate one entry which is a non-split tunnel (later on this could be e...
Definition: Ipv6Tunneling.cc:529
inet::Ipv6Tunneling::destroyTunnel
bool destroyTunnel(const Ipv6Address &src, const Ipv6Address &dest, const Ipv6Address &destTrigger)
Creates a pseudo-tunnel for use with either Type 2 Routing Header or Home Address Option with given e...
Definition: Ipv6Tunneling.cc:193
inet::Ipv6Tunneling::lookupTunnels
int lookupTunnels(const Ipv6Address &dest)
Search through all tunnels and locate one entry which is anything but a non-split tunnel and has a de...
Definition: Ipv6Tunneling.cc:512
inet::Protocol::ipv6
static const Protocol ipv6
Definition: Protocol.h:94
inet::Ipv6Tunneling::MOBILITY
@ MOBILITY
Definition: Ipv6Tunneling.h:47
inet::INITSTAGE_NETWORK_LAYER
INET_API InitStage INITSTAGE_NETWORK_LAYER
Initialization of network layer protocols.
L3AddressInd
removed DscpReq Ipv4ControlInfo Ipv6ControlInfo up L3AddressInd L3AddressInd
Definition: IUdp-gates.txt:20
inet::Ipv6Tunneling::SPLIT
@ SPLIT
Definition: Ipv6Tunneling.h:42
inet::Ipv6Tunneling::T2RH
@ T2RH
Definition: Ipv6Tunneling.h:45
inet::Ipv6Tunneling::noOfNonSplitTunnels
int noOfNonSplitTunnels
Definition: Ipv6Tunneling.h:120
inet::Ipv6Tunneling::isTunnelExit
bool isTunnelExit(const Ipv6Address &exit)
This method is equivalent for getVIfIndexForDest() except that it only searches for pseudo tunnels (T...
Definition: Ipv6Tunneling.cc:545
PacketProtocolTag
removed DscpReq Ipv4ControlInfo Ipv6ControlInfo up L3AddressInd DispatchProtocolReq L4PortInd Ipv4ControlInfo Ipv6ControlInfo down PacketProtocolTag
Definition: IUdp-gates.txt:25
inet::Ipv6Tunneling::ift
ModuleRefByPar< IInterfaceTable > ift
Definition: Ipv6Tunneling.h:51
inet::Ipv6Tunneling::HA_OPT
@ HA_OPT
Definition: Ipv6Tunneling.h:46
inet::Ipv6Tunneling::INVALID
@ INVALID
Definition: Ipv6Tunneling.h:41
inet::units::units::B
intscale< b, 1, 8 > B
Definition: Units.h:1168
inet::Ipv6Address::UNSPECIFIED_ADDRESS
static const Ipv6Address UNSPECIFIED_ADDRESS
The unspecified address.
Definition: Ipv6Address.h:54
inet::Ipv6Tunneling::tunnels
Tunnels tunnels
Definition: Ipv6Tunneling.h:114
inet::INITSTAGE_LOCAL
INET_API InitStage INITSTAGE_LOCAL
Initialization of local state that don't use or affect other modules includes:
inet::Ipv6Tunneling::decapsulateDatagram
void decapsulateDatagram(Packet *packet)
Strip tunnel headers from datagram.
Definition: Ipv6Tunneling.cc:463
NUM_INIT_STAGES
#define NUM_INIT_STAGES
Definition: InitStageRegistry.h:73
inet::Ipv6Tunneling::getVIfIndexForDest
int getVIfIndexForDest(const Ipv6Address &destAddress)
Returns the virtual interface identifier for the tunnel which has the provided destination as destina...
Definition: Ipv6Tunneling.cc:300
inet::Ipv6Tunneling::vIfIndexTop
int vIfIndexTop
Definition: Ipv6Tunneling.h:117
inet::Ipv6Tunneling::resetVIfIndex
void resetVIfIndex()
Reset the vIfIndex to its starting value if no tunnels exist anymore.
Definition: Ipv6Tunneling.h:253
inet::NodeStatus::UP
@ UP
Definition: NodeStatus.h:28
inet::Ipv6Tunneling::findTunnel
int findTunnel(const Ipv6Address &src, const Ipv6Address &dest, const Ipv6Address &destTrigger) const
Returns the type of the tunnels: non-split, split, T2RH, ...
Definition: Ipv6Tunneling.cc:179
IPv6_MIN_MTU
#define IPv6_MIN_MTU
Definition: Ipv6InterfaceData.h:31
inet::Ipv6Tunneling::NORMAL
@ NORMAL
Definition: Ipv6Tunneling.h:44
inet::Ipv6Tunneling::encapsulateDatagram
void encapsulateDatagram(Packet *packet)
Encapsulate a datagram with tunnel headers.
Definition: Ipv6Tunneling.cc:349
IPv6__INET_DEFAULT_ROUTER_HOPLIMIT
#define IPv6__INET_DEFAULT_ROUTER_HOPLIMIT
Definition: Ipv6InterfaceData.h:37
inet::IP_PROT_IPv6EXT_MOB
@ IP_PROT_IPv6EXT_MOB
Definition: IpProtocolId_m.h:117
inet::Ipv6Tunneling::TI
Tunnels::const_iterator TI
Definition: Ipv6Tunneling.h:102
inet::Ipv6Tunneling::rt
ModuleRefByPar< Ipv6RoutingTable > rt
Definition: Ipv6Tunneling.h:52
inet::Ipv6Tunneling::NON_SPLIT
@ NON_SPLIT
Definition: Ipv6Tunneling.h:43