00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <omnetpp.h>
00020 #include <stdlib.h>
00021 #include <string.h>
00022
00023 #include "IP.h"
00024 #include "IPDatagram.h"
00025 #include "IPControlInfo.h"
00026 #include "ICMPMessage_m.h"
00027 #include "IPv4InterfaceData.h"
00028 #include "ARPPacket_m.h"
00029
00030 Define_Module(IP);
00031
00032
00033 void IP::initialize()
00034 {
00035 QueueBase::initialize();
00036
00037 ift = InterfaceTableAccess().get();
00038 rt = RoutingTableAccess().get();
00039
00040 queueOutGate = gate("queueOut");
00041
00042 defaultTimeToLive = par("timeToLive");
00043 defaultMCTimeToLive = par("multicastTimeToLive");
00044 fragmentTimeoutTime = par("fragmentTimeout");
00045 mapping.parseProtocolMapping(par("protocolMapping"));
00046
00047 curFragmentId = 0;
00048 lastCheckTime = 0;
00049 fragbuf.init(icmpAccess.get());
00050
00051 numMulticast = numLocalDeliver = numDropped = numUnroutable = numForwarded = 0;
00052
00053 WATCH(numMulticast);
00054 WATCH(numLocalDeliver);
00055 WATCH(numDropped);
00056 WATCH(numUnroutable);
00057 WATCH(numForwarded);
00058 }
00059
00060 void IP::updateDisplayString()
00061 {
00062 char buf[80] = "";
00063 if (numForwarded>0) sprintf(buf+strlen(buf), "fwd:%d ", numForwarded);
00064 if (numLocalDeliver>0) sprintf(buf+strlen(buf), "up:%d ", numLocalDeliver);
00065 if (numMulticast>0) sprintf(buf+strlen(buf), "mcast:%d ", numMulticast);
00066 if (numDropped>0) sprintf(buf+strlen(buf), "DROP:%d ", numDropped);
00067 if (numUnroutable>0) sprintf(buf+strlen(buf), "UNROUTABLE:%d ", numUnroutable);
00068 getDisplayString().setTagArg("t",0,buf);
00069 }
00070
00071 void IP::endService(cPacket *msg)
00072 {
00073 if (msg->getArrivalGate()->isName("transportIn"))
00074 {
00075 handleMessageFromHL( msg );
00076 }
00077 else if (dynamic_cast<ARPPacket *>(msg))
00078 {
00079
00080 handleARP((ARPPacket *)msg);
00081 }
00082 else
00083 {
00084 IPDatagram *dgram = check_and_cast<IPDatagram *>(msg);
00085 handlePacketFromNetwork(dgram);
00086 }
00087
00088 if (ev.isGUI())
00089 updateDisplayString();
00090 }
00091
00092 InterfaceEntry *IP::getSourceInterfaceFrom(cPacket *msg)
00093 {
00094 cGate *g = msg->getArrivalGate();
00095 return g ? ift->getInterfaceByNetworkLayerGateIndex(g->getIndex()) : NULL;
00096 }
00097
00098 void IP::handlePacketFromNetwork(IPDatagram *datagram)
00099 {
00100
00101
00102
00103
00104
00105 if (datagram->hasBitError())
00106 {
00107
00108
00109 double relativeHeaderLength = datagram->getHeaderLength() / (double)datagram->getByteLength();
00110 if (dblrand() <= relativeHeaderLength)
00111 {
00112 EV << "bit error found, sending ICMP_PARAMETER_PROBLEM\n";
00113 icmpAccess.get()->sendErrorMessage(datagram, ICMP_PARAMETER_PROBLEM, 0);
00114 return;
00115 }
00116 }
00117
00118
00119 delete datagram->removeControlInfo();
00120
00121
00122 datagram->setTimeToLive(datagram->getTimeToLive()-1);
00123
00124
00125 if (!datagram->getDestAddress().isMulticast())
00126 routePacket(datagram, NULL, false);
00127 else
00128 routeMulticastPacket(datagram, NULL, getSourceInterfaceFrom(datagram));
00129 }
00130
00131 void IP::handleARP(ARPPacket *msg)
00132 {
00133
00134
00135
00136 delete msg->removeControlInfo();
00137
00138
00139 InterfaceEntry *fromIE = getSourceInterfaceFrom(msg);
00140 ASSERT(fromIE);
00141
00142 IPRoutingDecision *routingDecision = new IPRoutingDecision();
00143 routingDecision->setInterfaceId(fromIE->getInterfaceId());
00144 msg->setControlInfo(routingDecision);
00145
00146 send(msg, queueOutGate);
00147 }
00148
00149 void IP::handleReceivedICMP(ICMPMessage *msg)
00150 {
00151 switch (msg->getType())
00152 {
00153 case ICMP_REDIRECT:
00154 case ICMP_DESTINATION_UNREACHABLE:
00155 case ICMP_TIME_EXCEEDED:
00156 case ICMP_PARAMETER_PROBLEM: {
00157
00158 IPDatagram *bogusPacket = check_and_cast<IPDatagram *>(msg->getEncapsulatedMsg());
00159 int protocol = bogusPacket->getTransportProtocol();
00160 int gateindex = mapping.getOutputGateForProtocol(protocol);
00161 send(msg, "transportOut", gateindex);
00162 break;
00163 }
00164 default: {
00165
00166
00167 int gateindex = mapping.getOutputGateForProtocol(IP_PROT_ICMP);
00168 send(msg, "transportOut", gateindex);
00169 }
00170 }
00171 }
00172
00173 void IP::handleMessageFromHL(cPacket *msg)
00174 {
00175
00176 if (ift->getNumInterfaces() == 0)
00177 {
00178 EV << "No interfaces exist, dropping packet\n";
00179 delete msg;
00180 return;
00181 }
00182
00183
00184 InterfaceEntry *destIE;
00185 IPDatagram *datagram = encapsulate(msg, destIE);
00186
00187
00188 if (!datagram->getDestAddress().isMulticast())
00189 routePacket(datagram, destIE, true);
00190 else
00191 routeMulticastPacket(datagram, destIE, NULL);
00192 }
00193
00194 void IP::routePacket(IPDatagram *datagram, InterfaceEntry *destIE, bool fromHL)
00195 {
00196
00197
00198 IPAddress destAddr = datagram->getDestAddress();
00199
00200 EV << "Routing datagram `" << datagram->getName() << "' with dest=" << destAddr << ": ";
00201
00202
00203 if (rt->isLocalAddress(destAddr))
00204 {
00205 EV << "local delivery\n";
00206 if (datagram->getSrcAddress().isUnspecified())
00207 datagram->setSrcAddress(destAddr);
00208 numLocalDeliver++;
00209 reassembleAndDeliver(datagram);
00210 return;
00211 }
00212
00213
00214 if (!fromHL && !rt->isIPForwardingEnabled())
00215 {
00216 EV << "forwarding off, dropping packet\n";
00217 numDropped++;
00218 delete datagram;
00219 return;
00220 }
00221
00222 IPAddress nextHopAddr;
00223
00224
00225 if (destIE)
00226 {
00227 EV << "using manually specified output interface " << destIE->getName() << "\n";
00228
00229 }
00230 else
00231 {
00232
00233 const IPRoute *re = rt->findBestMatchingRoute(destAddr);
00234
00235
00236
00237 if (re==NULL)
00238 {
00239 EV << "unroutable, sending ICMP_DESTINATION_UNREACHABLE\n";
00240 numUnroutable++;
00241 icmpAccess.get()->sendErrorMessage(datagram, ICMP_DESTINATION_UNREACHABLE, 0);
00242 return;
00243 }
00244
00245
00246 destIE = re->getInterface();
00247 nextHopAddr = re->getGateway();
00248 }
00249
00250
00251 if (datagram->getSrcAddress().isUnspecified())
00252 datagram->setSrcAddress(destIE->ipv4Data()->getIPAddress());
00253
00254
00255 EV << "output interface is " << destIE->getName() << ", next-hop address: " << nextHopAddr << "\n";
00256 numForwarded++;
00257
00258
00259
00260
00261 fragmentAndSend(datagram, destIE, nextHopAddr);
00262 }
00263
00264 void IP::routeMulticastPacket(IPDatagram *datagram, InterfaceEntry *destIE, InterfaceEntry *fromIE)
00265 {
00266 IPAddress destAddr = datagram->getDestAddress();
00267 EV << "Routing multicast datagram `" << datagram->getName() << "' with dest=" << destAddr << "\n";
00268
00269 numMulticast++;
00270
00271
00272
00273
00274 InterfaceEntry *shortestPathIE = rt->getInterfaceForDestAddr(datagram->getSrcAddress());
00275 if (fromIE!=NULL && shortestPathIE!=NULL && fromIE!=shortestPathIE)
00276 {
00277
00278 EV << "Packet dropped.\n";
00279 delete datagram;
00280 return;
00281 }
00282
00283
00284 if (fromIE!=NULL)
00285 {
00286
00287 if (rt->isLocalMulticastAddress(destAddr))
00288 {
00289 IPDatagram *datagramCopy = (IPDatagram *) datagram->dup();
00290
00291
00292 datagramCopy->setDestAddress(rt->getRouterId());
00293
00294 reassembleAndDeliver(datagramCopy);
00295 }
00296
00297
00298 if (!rt->isIPForwardingEnabled())
00299 {
00300 delete datagram;
00301 return;
00302 }
00303
00304
00305 if (destAddr.isLinkLocalMulticast())
00306 {
00307 delete datagram;
00308 return;
00309 }
00310
00311 }
00312
00313
00314 if (destIE!=NULL)
00315 {
00316 ASSERT(datagram->getDestAddress().isMulticast());
00317
00318 EV << "multicast packet explicitly routed via output interface " << destIE->getName() << endl;
00319
00320
00321 if (datagram->getSrcAddress().isUnspecified())
00322 datagram->setSrcAddress(destIE->ipv4Data()->getIPAddress());
00323
00324
00325 fragmentAndSend(datagram, destIE, datagram->getDestAddress());
00326
00327 return;
00328 }
00329
00330
00331 MulticastRoutes routes = rt->getMulticastRoutesFor(destAddr);
00332 if (routes.size()==0)
00333 {
00334
00335 delete datagram;
00336 }
00337 else
00338 {
00339
00340 for (unsigned int i=0; i<routes.size(); i++)
00341 {
00342 InterfaceEntry *destIE = routes[i].interf;
00343
00344
00345 if (destIE && destIE!=fromIE)
00346 {
00347 IPDatagram *datagramCopy = (IPDatagram *) datagram->dup();
00348
00349
00350 if (datagramCopy->getSrcAddress().isUnspecified())
00351 datagramCopy->setSrcAddress(destIE->ipv4Data()->getIPAddress());
00352
00353
00354 IPAddress nextHopAddr = routes[i].gateway;
00355 fragmentAndSend(datagramCopy, destIE, nextHopAddr);
00356 }
00357 }
00358
00359
00360 delete datagram;
00361 }
00362 }
00363
00364 void IP::reassembleAndDeliver(IPDatagram *datagram)
00365 {
00366
00367 if (datagram->getFragmentOffset()!=0 || datagram->getMoreFragments())
00368 {
00369 EV << "Datagram fragment: offset=" << datagram->getFragmentOffset()
00370 << ", MORE=" << (datagram->getMoreFragments() ? "true" : "false") << ".\n";
00371
00372
00373 if (simTime() >= lastCheckTime + 10)
00374 {
00375 lastCheckTime = simTime();
00376 fragbuf.purgeStaleFragments(simTime()-fragmentTimeoutTime);
00377 }
00378
00379 datagram = fragbuf.addFragment(datagram, simTime());
00380 if (!datagram)
00381 {
00382 EV << "No complete datagram yet.\n";
00383 return;
00384 }
00385 EV << "This fragment completes the datagram.\n";
00386 }
00387
00388
00389 int protocol = datagram->getTransportProtocol();
00390 cPacket *packet = decapsulateIP(datagram);
00391
00392 if (protocol==IP_PROT_ICMP)
00393 {
00394
00395 handleReceivedICMP(check_and_cast<ICMPMessage *>(packet));
00396 }
00397 else if (protocol==IP_PROT_IP)
00398 {
00399
00400 send(packet, "preRoutingOut");
00401 }
00402 else
00403 {
00404 int gateindex = mapping.getOutputGateForProtocol(protocol);
00405 send(packet, "transportOut", gateindex);
00406 }
00407 }
00408
00409 cPacket *IP::decapsulateIP(IPDatagram *datagram)
00410 {
00411
00412 InterfaceEntry *fromIE = getSourceInterfaceFrom(datagram);
00413 cPacket *packet = datagram->decapsulate();
00414
00415
00416 IPControlInfo *controlInfo = new IPControlInfo();
00417 controlInfo->setProtocol(datagram->getTransportProtocol());
00418 controlInfo->setSrcAddr(datagram->getSrcAddress());
00419 controlInfo->setDestAddr(datagram->getDestAddress());
00420 controlInfo->setDiffServCodePoint(datagram->getDiffServCodePoint());
00421 controlInfo->setInterfaceId(fromIE ? fromIE->getInterfaceId() : -1);
00422
00423
00424 controlInfo->setOrigDatagram(datagram);
00425
00426
00427 packet->setControlInfo(controlInfo);
00428
00429 return packet;
00430 }
00431
00432
00433 void IP::fragmentAndSend(IPDatagram *datagram, InterfaceEntry *ie, IPAddress nextHopAddr)
00434 {
00435 int mtu = ie->getMTU();
00436
00437
00438 if (datagram->getByteLength() <= mtu)
00439 {
00440 sendDatagramToOutput(datagram, ie, nextHopAddr);
00441 return;
00442 }
00443
00444 int headerLength = datagram->getHeaderLength();
00445 int payload = datagram->getByteLength() - headerLength;
00446
00447 int noOfFragments =
00448 int(ceil((float(payload)/mtu) /
00449 (1-float(headerLength)/mtu) ) );
00450
00451
00452 if (datagram->getDontFragment() && noOfFragments>1)
00453 {
00454 EV << "datagram larger than MTU and don't fragment bit set, sending ICMP_DESTINATION_UNREACHABLE\n";
00455 icmpAccess.get()->sendErrorMessage(datagram, ICMP_DESTINATION_UNREACHABLE,
00456 ICMP_FRAGMENTATION_ERROR_CODE);
00457 return;
00458 }
00459
00460
00461 EV << "Breaking datagram into " << noOfFragments << " fragments\n";
00462 std::string fragMsgName = datagram->getName();
00463 fragMsgName += "-frag";
00464
00465
00466 for (int i=0; i<noOfFragments; i++)
00467 {
00468
00469
00470 IPDatagram *fragment = (IPDatagram *) datagram->dup();
00471 fragment->setName(fragMsgName.c_str());
00472
00473
00474
00475 if (i != noOfFragments-1)
00476 {
00477 fragment->setMoreFragments(true);
00478 fragment->setByteLength(mtu);
00479 }
00480 else
00481 {
00482
00483 int bytes = datagram->getByteLength() - (noOfFragments-1) * (mtu - datagram->getHeaderLength());
00484 fragment->setByteLength(bytes);
00485 }
00486 fragment->setFragmentOffset( i*(mtu - datagram->getHeaderLength()) );
00487
00488 sendDatagramToOutput(fragment, ie, nextHopAddr);
00489 }
00490
00491 delete datagram;
00492 }
00493
00494
00495 IPDatagram *IP::encapsulate(cPacket *transportPacket, InterfaceEntry *&destIE)
00496 {
00497 IPControlInfo *controlInfo = check_and_cast<IPControlInfo*>(transportPacket->removeControlInfo());
00498 IPDatagram *datagram = encapsulate(transportPacket, destIE, controlInfo);
00499 delete controlInfo;
00500 return datagram;
00501 }
00502
00503 IPDatagram *IP::encapsulate(cPacket *transportPacket, InterfaceEntry *&destIE, IPControlInfo *controlInfo)
00504 {
00505 IPDatagram *datagram = createIPDatagram(transportPacket->getName());
00506 datagram->setByteLength(IP_HEADER_BYTES);
00507 datagram->encapsulate(transportPacket);
00508
00509
00510 IPAddress dest = controlInfo->getDestAddr();
00511 datagram->setDestAddress(dest);
00512
00513
00514 destIE = ift->getInterfaceById(controlInfo->getInterfaceId());
00515
00516 IPAddress src = controlInfo->getSrcAddr();
00517
00518
00519
00520 if (!src.isUnspecified())
00521 {
00522
00523 if (rt->getInterfaceByAddress(src)==NULL)
00524 opp_error("Wrong source address %s in (%s)%s: no interface with such address",
00525 src.str().c_str(), transportPacket->getClassName(), transportPacket->getFullName());
00526 datagram->setSrcAddress(src);
00527 }
00528
00529
00530 datagram->setDiffServCodePoint(controlInfo->getDiffServCodePoint());
00531
00532 datagram->setIdentification(curFragmentId++);
00533 datagram->setMoreFragments(false);
00534 datagram->setDontFragment (controlInfo->getDontFragment());
00535 datagram->setFragmentOffset(0);
00536
00537 short ttl;
00538 if (controlInfo->getTimeToLive() > 0)
00539 ttl = controlInfo->getTimeToLive();
00540 else if (datagram->getDestAddress().isLinkLocalMulticast())
00541 ttl = 1;
00542 else if (datagram->getDestAddress().isMulticast())
00543 ttl = defaultMCTimeToLive;
00544 else
00545 ttl = defaultTimeToLive;
00546
00547 datagram->setTimeToLive(ttl);
00548 datagram->setTransportProtocol(controlInfo->getProtocol());
00549
00550
00551
00552 return datagram;
00553 }
00554
00555 IPDatagram *IP::createIPDatagram(const char *name)
00556 {
00557 return new IPDatagram(name);
00558 }
00559
00560 void IP::sendDatagramToOutput(IPDatagram *datagram, InterfaceEntry *ie, IPAddress nextHopAddr)
00561 {
00562
00563 if (datagram->getTimeToLive() <= 0)
00564 {
00565
00566 EV << "datagram TTL reached zero, sending ICMP_TIME_EXCEEDED\n";
00567 icmpAccess.get()->sendErrorMessage(datagram, ICMP_TIME_EXCEEDED, 0);
00568 return;
00569 }
00570
00571
00572 IPRoutingDecision *routingDecision = new IPRoutingDecision();
00573 routingDecision->setInterfaceId(ie->getInterfaceId());
00574 routingDecision->setNextHopAddr(nextHopAddr);
00575 datagram->setControlInfo(routingDecision);
00576
00577 send(datagram, queueOutGate);
00578 }
00579
00580