00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <omnetpp.h>
00021 #include "IPv6.h"
00022 #include "InterfaceTableAccess.h"
00023 #include "RoutingTable6Access.h"
00024 #include "ICMPv6Access.h"
00025 #include "IPv6NeighbourDiscoveryAccess.h"
00026 #include "IPv6ControlInfo.h"
00027 #include "IPv6NDMessage_m.h"
00028 #include "Ieee802Ctrl_m.h"
00029 #include "ICMPv6Message_m.h"
00030
00031
00032 #define FRAGMENT_TIMEOUT 60 // 60 sec, from IPv6 RFC
00033
00034
00035 Define_Module(IPv6);
00036
00037 void IPv6::initialize()
00038 {
00039 QueueBase::initialize();
00040
00041 ift = InterfaceTableAccess().get();
00042 rt = RoutingTable6Access().get();
00043 nd = IPv6NeighbourDiscoveryAccess().get();
00044 icmp = ICMPv6Access().get();
00045
00046 mapping.parseProtocolMapping(par("protocolMapping"));
00047
00048 curFragmentId = 0;
00049 lastCheckTime = 0;
00050 fragbuf.init(icmp);
00051
00052 numMulticast = numLocalDeliver = numDropped = numUnroutable = numForwarded = 0;
00053
00054 WATCH(numMulticast);
00055 WATCH(numLocalDeliver);
00056 WATCH(numDropped);
00057 WATCH(numUnroutable);
00058 WATCH(numForwarded);
00059 }
00060
00061 void IPv6::updateDisplayString()
00062 {
00063 char buf[80] = "";
00064 if (numForwarded>0) sprintf(buf+strlen(buf), "fwd:%d ", numForwarded);
00065 if (numLocalDeliver>0) sprintf(buf+strlen(buf), "up:%d ", numLocalDeliver);
00066 if (numMulticast>0) sprintf(buf+strlen(buf), "mcast:%d ", numMulticast);
00067 if (numDropped>0) sprintf(buf+strlen(buf), "DROP:%d ", numDropped);
00068 if (numUnroutable>0) sprintf(buf+strlen(buf), "UNROUTABLE:%d ", numUnroutable);
00069 getDisplayString().setTagArg("t",0,buf);
00070 }
00071
00072 void IPv6::endService(cPacket *msg)
00073 {
00074 if (msg->getArrivalGate()->isName("transportIn") ||
00075 (msg->getArrivalGate()->isName("ndIn") && dynamic_cast<IPv6NDMessage*>(msg)) ||
00076 (msg->getArrivalGate()->isName("icmpIn") && dynamic_cast<ICMPv6Message*>(msg)))
00077 {
00078
00079 handleMessageFromHL( msg );
00080 }
00081 else
00082 {
00083
00084 IPv6Datagram *dgram = check_and_cast<IPv6Datagram *>(msg);
00085 handleDatagramFromNetwork(dgram);
00086 }
00087
00088 if (ev.isGUI())
00089 updateDisplayString();
00090 }
00091
00092 InterfaceEntry *IPv6::getSourceInterfaceFrom(cPacket *msg)
00093 {
00094 cGate *g = msg->getArrivalGate();
00095 return g ? ift->getInterfaceByNetworkLayerGateIndex(g->getIndex()) : NULL;
00096 }
00097
00098 void IPv6::handleDatagramFromNetwork(IPv6Datagram *datagram)
00099 {
00100
00101 if (datagram->hasBitError())
00102 {
00103 EV << "bit error\n";return;
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115 }
00116
00117
00118 delete datagram->removeControlInfo();
00119
00120
00121 if (!datagram->getDestAddress().isMulticast())
00122 routePacket(datagram, NULL, false);
00123 else
00124 routeMulticastPacket(datagram, NULL, getSourceInterfaceFrom(datagram));
00125 }
00126
00127 void IPv6::handleMessageFromHL(cPacket *msg)
00128 {
00129
00130 if (ift->getNumInterfaces() == 0)
00131 {
00132 EV << "No interfaces exist, dropping packet\n";
00133 delete msg;
00134 return;
00135 }
00136
00137
00138 InterfaceEntry *destIE;
00139 IPv6Datagram *datagram = encapsulate(msg, destIE);
00140
00141
00142 fragmentAndRoute(datagram, destIE);
00143 }
00144
00145 void IPv6::fragmentAndRoute(IPv6Datagram *datagram, InterfaceEntry *destIE)
00146 {
00147
00148
00149
00150
00151
00152
00153
00154 EV << "fragmentation not implemented yet\n";
00155
00156
00157 if (destIE!=NULL)
00158 sendDatagramToOutput(datagram, destIE, MACAddress::BROADCAST_ADDRESS);
00159 else if (!datagram->getDestAddress().isMulticast())
00160 routePacket(datagram, destIE, true);
00161 else
00162 routeMulticastPacket(datagram, destIE, NULL);
00163 }
00164
00165 void IPv6::routePacket(IPv6Datagram *datagram, InterfaceEntry *destIE, bool fromHL)
00166 {
00167
00168 IPv6Address destAddress = datagram->getDestAddress();
00169
00170 EV << "Routing datagram `" << datagram->getName() << "' with dest=" << destAddress << ": ";
00171
00172
00173 if (rt->isLocalAddress(destAddress))
00174 {
00175 EV << "local delivery\n";
00176 if (datagram->getSrcAddress().isUnspecified())
00177 datagram->setSrcAddress(destAddress);
00178 numLocalDeliver++;
00179 isLocalAddress(datagram);
00180 return;
00181 }
00182
00183 if (!fromHL)
00184 {
00185
00186
00187
00188
00189
00190 if (!rt->isRouter() && !(datagram->getArrivalGate()->isName("ndIn")))
00191 {
00192 EV << "forwarding is off, dropping packet\n";
00193 numDropped++;
00194 delete datagram;
00195 return;
00196 }
00197
00198
00199 if (destAddress.isLinkLocal() || destAddress.isLoopback())
00200 {
00201 EV << "dest address is link-local (or weaker) scope, doesn't get forwarded\n";
00202 delete datagram;
00203 return;
00204 }
00205
00206
00207
00208
00209
00210 datagram->setHopLimit(datagram->getHopLimit()-1);
00211 }
00212
00213
00214
00215 int interfaceId;
00216 IPv6Address nextHop = rt->lookupDestCache(destAddress, interfaceId);
00217 if (interfaceId==-1)
00218 {
00219
00220 const IPv6Route *route = rt->doLongestPrefixMatch(destAddress);
00221 if (!route)
00222 {
00223 if (rt->isRouter())
00224 {
00225 EV << "unroutable, sending ICMPv6_DESTINATION_UNREACHABLE\n";
00226 numUnroutable++;
00227 icmp->sendErrorMessage(datagram, ICMPv6_DESTINATION_UNREACHABLE, 0);
00228 }
00229 else
00230 {
00231 EV << "no match in routing table, passing datagram to Neighbour Discovery module for default router selection\n";
00232 send(datagram, "ndOut");
00233 }
00234 return;
00235 }
00236 interfaceId = route->getInterfaceId();
00237 nextHop = route->getNextHop();
00238 if (nextHop.isUnspecified())
00239 nextHop = destAddress;
00240
00241
00242 rt->updateDestCache(destAddress, nextHop, interfaceId);
00243 }
00244
00245 InterfaceEntry *ie = ift->getInterfaceById(interfaceId);
00246 ASSERT(ie!=NULL);
00247 EV << "next hop for " << destAddress << " is " << nextHop << ", interface " << ie->getName() << "\n";
00248 ASSERT(!nextHop.isUnspecified());
00249
00250 MACAddress macAddr = nd->resolveNeighbour(nextHop, interfaceId);
00251 if (macAddr.isUnspecified())
00252 {
00253 EV << "no link-layer address for next hop yet, passing datagram to Neighbour Discovery module\n";
00254 send(datagram, "ndOut");
00255 return;
00256 }
00257 EV << "link-layer address: " << macAddr << "\n";
00258
00259
00260 if (datagram->getSrcAddress().isUnspecified())
00261 {
00262 const IPv6Address& srcAddr = ie->ipv6Data()->getPreferredAddress();
00263 ASSERT(!srcAddr.isUnspecified());
00264 datagram->setSrcAddress(srcAddr);
00265 }
00266
00267
00268 numForwarded++;
00269 sendDatagramToOutput(datagram, ie, macAddr);
00270 }
00271
00272 void IPv6::routeMulticastPacket(IPv6Datagram *datagram, InterfaceEntry *destIE, InterfaceEntry *fromIE)
00273 {
00274 const IPv6Address& destAddr = datagram->getDestAddress();
00275
00276 EV << "destination address " << destAddr << " is multicast, doing multicast routing\n";
00277 numMulticast++;
00278
00279
00280 if (fromIE!=NULL)
00281 {
00282
00283 if (rt->isLocalAddress(destAddr))
00284 {
00285 EV << "local delivery of multicast packet\n";
00286 numLocalDeliver++;
00287 isLocalAddress((IPv6Datagram *)datagram->dup());
00288 }
00289
00290
00291 if (!rt->isRouter())
00292 {
00293 EV << "forwarding is off\n";
00294 delete datagram;
00295 return;
00296 }
00297
00298
00299 if (destAddr.getMulticastScope()<=2)
00300 {
00301 EV << "multicast dest address is link-local (or smaller) scope\n";
00302 delete datagram;
00303 return;
00304 }
00305
00306
00307
00308
00309
00310 datagram->setHopLimit(datagram->getHopLimit()-1);
00311 }
00312
00313
00314 EV << "sending out datagram on every interface (except incoming one)\n";
00315 for (int i=0; i<ift->getNumInterfaces(); i++)
00316 {
00317 InterfaceEntry *ie = ift->getInterface(i);
00318 if (fromIE!=ie)
00319 sendDatagramToOutput((IPv6Datagram *)datagram->dup(), ie, MACAddress::BROADCAST_ADDRESS);
00320 }
00321 delete datagram;
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395 }
00396
00397 void IPv6::isLocalAddress(IPv6Datagram *datagram)
00398 {
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423 int protocol = datagram->getTransportProtocol();
00424 cPacket *packet = decapsulate(datagram);
00425
00426 if (protocol==IP_PROT_IPv6_ICMP && dynamic_cast<IPv6NDMessage*>(packet))
00427 {
00428 EV << "Neigbour Discovery packet: passing it to ND module\n";
00429 send(packet, "ndOut");
00430 }
00431 else if (protocol==IP_PROT_IPv6_ICMP && dynamic_cast<ICMPv6Message*>(packet))
00432 {
00433 EV << "ICMPv6 packet: passing it to ICMPv6 module\n";
00434 send(packet, "icmpOut");
00435 }
00436 else if (protocol==IP_PROT_IP || protocol==IP_PROT_IPv6)
00437 {
00438 EV << "Tunnelled IP datagram\n";
00439
00440 error("tunnelling not yet implemented");
00441 }
00442 else
00443 {
00444 int gateindex = mapping.getOutputGateForProtocol(protocol);
00445 EV << "Protocol " << protocol << ", passing up on gate " << gateindex << "\n";
00446
00447 send(packet, "transportOut", gateindex);
00448 }
00449 }
00450
00451 void IPv6::handleReceivedICMP(ICMPv6Message *msg)
00452 {
00453 switch (msg->getType())
00454 {
00455 case ICMPv6_REDIRECT:
00456 case ICMPv6_DESTINATION_UNREACHABLE:
00457 case ICMPv6_PACKET_TOO_BIG:
00458 case ICMPv6_TIME_EXCEEDED:
00459 case ICMPv6_PARAMETER_PROBLEM: {
00460
00461 IPv6Datagram *bogusPacket = check_and_cast<IPv6Datagram *>(msg->getEncapsulatedMsg());
00462 int protocol = bogusPacket->getTransportProtocol();
00463 int gateindex = mapping.getOutputGateForProtocol(protocol);
00464 send(msg, "transportOut", gateindex);
00465 break;
00466 }
00467 default: {
00468
00469
00470
00471
00472 int gateindex = mapping.getOutputGateForProtocol(IP_PROT_ICMP);
00473 send(msg, "transportOut", gateindex);
00474 }
00475 }
00476 }
00477
00478
00479 cPacket *IPv6::decapsulate(IPv6Datagram *datagram)
00480 {
00481
00482 InterfaceEntry *fromIE = getSourceInterfaceFrom(datagram);
00483 cPacket *packet = datagram->decapsulate();
00484
00485
00486 IPv6ControlInfo *controlInfo = new IPv6ControlInfo();
00487 controlInfo->setProtocol(datagram->getTransportProtocol());
00488 controlInfo->setSrcAddr(datagram->getSrcAddress());
00489 controlInfo->setDestAddr(datagram->getDestAddress());
00490 controlInfo->setHopLimit(datagram->getHopLimit());
00491 controlInfo->setInterfaceId(fromIE ? fromIE->getInterfaceId() : -1);
00492
00493
00494 controlInfo->setOrigDatagram(datagram);
00495
00496
00497 packet->setControlInfo(controlInfo);
00498
00499 return packet;
00500 }
00501
00502 IPv6Datagram *IPv6::encapsulate(cPacket *transportPacket, InterfaceEntry *&destIE)
00503 {
00504 IPv6ControlInfo *controlInfo = check_and_cast<IPv6ControlInfo*>(transportPacket->removeControlInfo());
00505
00506 IPv6Datagram *datagram = new IPv6Datagram(transportPacket->getName());
00507 datagram->setByteLength(datagram->calculateHeaderByteLength());
00508 datagram->encapsulate(transportPacket);
00509
00510
00511 destIE = ift->getInterfaceById(controlInfo->getInterfaceId());
00512
00513
00514 IPv6Address dest = controlInfo->getDestAddr();
00515 datagram->setDestAddress(dest);
00516
00517 IPv6Address src = controlInfo->getSrcAddr();
00518
00519
00520
00521 if (!src.isUnspecified())
00522 {
00523
00524 if (rt->getInterfaceByAddress(src)==NULL)
00525 opp_error("Wrong source address %s in (%s)%s: no interface with such address",
00526 src.str().c_str(), transportPacket->getClassName(), transportPacket->getFullName());
00527 datagram->setSrcAddress(src);
00528 }
00529
00530
00531 datagram->setHopLimit(controlInfo->getHopLimit()>0 ? controlInfo->getHopLimit() : 32);
00532 datagram->setTransportProtocol(controlInfo->getProtocol());
00533 delete controlInfo;
00534
00535
00536
00537 return datagram;
00538 }
00539
00540 void IPv6::sendDatagramToOutput(IPv6Datagram *datagram, InterfaceEntry *ie, const MACAddress& macAddr)
00541 {
00542
00543 if (datagram->getHopLimit() <= 0)
00544 {
00545
00546 EV << "datagram hopLimit reached zero, sending ICMPv6_TIME_EXCEEDED\n";
00547 icmp->sendErrorMessage(datagram, ICMPv6_TIME_EXCEEDED, 0);
00548 return;
00549 }
00550
00551
00552 if (!macAddr.isUnspecified())
00553 {
00554 Ieee802Ctrl *controlInfo = new Ieee802Ctrl();
00555 controlInfo->setDest(macAddr);
00556 datagram->setControlInfo(controlInfo);
00557 }
00558
00559
00560 send(datagram, "queueOut", ie->getNetworkLayerGateIndex());
00561 }
00562
00563