#include <IP.h>
Inheritance diagram for IP:

Public Member Functions | |
| IP () | |
Protected Member Functions | |
| InterfaceEntry * | sourceInterfaceFrom (cMessage *msg) |
| void | updateDisplayString () |
| IPDatagram * | encapsulate (cMessage *transportPacket, InterfaceEntry *&destIE) |
| virtual void | handlePacketFromNetwork (IPDatagram *datagram) |
| virtual void | handleMessageFromHL (cMessage *msg) |
| virtual void | handleARP (ARPPacket *msg) |
| virtual void | handleReceivedICMP (ICMPMessage *msg) |
| virtual void | routePacket (IPDatagram *datagram, InterfaceEntry *destIE, bool fromHL) |
| virtual void | routeMulticastPacket (IPDatagram *datagram, InterfaceEntry *destIE, InterfaceEntry *fromIE) |
| virtual void | localDeliver (IPDatagram *datagram) |
| virtual cMessage * | decapsulateIP (IPDatagram *datagram) |
| virtual void | fragmentAndSend (IPDatagram *datagram, InterfaceEntry *ie, IPAddress nextHopAddr) |
| virtual void | sendDatagramToOutput (IPDatagram *datagram, InterfaceEntry *ie, IPAddress nextHopAddr) |
| virtual void | initialize () |
| virtual void | endService (cMessage *msg) |
Protected Attributes | |
| RoutingTable * | rt |
| InterfaceTable * | ift |
| ICMPAccess | icmpAccess |
| int | defaultTimeToLive |
| int | defaultMCTimeToLive |
| simtime_t | fragmentTimeoutTime |
| long | curFragmentId |
| IPFragBuf | fragbuf |
| simtime_t | lastCheckTime |
| ProtocolMapping | mapping |
| int | numMulticast |
| int | numLocalDeliver |
| int | numDropped |
| int | numUnroutable |
| int | numForwarded |
|
|
00138 {}
|
|
|
Decapsulate and return encapsulated packet after attaching IPControlInfo. 00409 {
00410 // decapsulate transport packet
00411 InterfaceEntry *fromIE = sourceInterfaceFrom(datagram);
00412 cMessage *packet = datagram->decapsulate();
00413
00414 // create and fill in control info
00415 IPControlInfo *controlInfo = new IPControlInfo();
00416 controlInfo->setProtocol(datagram->transportProtocol());
00417 controlInfo->setSrcAddr(datagram->srcAddress());
00418 controlInfo->setDestAddr(datagram->destAddress());
00419 controlInfo->setDiffServCodePoint(datagram->diffServCodePoint());
00420 controlInfo->setInterfaceId(fromIE ? fromIE->interfaceId() : -1);
00421
00422 // original IP datagram might be needed in upper layers to send back ICMP error message
00423 controlInfo->setOrigDatagram(datagram);
00424
00425 // attach control info
00426 packet->setControlInfo(controlInfo);
00427
00428 return packet;
00429 }
|
|
||||||||||||
|
Encapsulate packet coming from higher layers into IPDatagram 00495 {
00496 IPControlInfo *controlInfo = check_and_cast<IPControlInfo*>(transportPacket->removeControlInfo());
00497
00498 IPDatagram *datagram = new IPDatagram(transportPacket->name());
00499 datagram->setByteLength(IP_HEADER_BYTES);
00500 datagram->encapsulate(transportPacket);
00501
00502 // set source and destination address
00503 IPAddress dest = controlInfo->destAddr();
00504 datagram->setDestAddress(dest);
00505
00506 // IP_MULTICAST_IF option, but allow interface selection for unicast packets as well
00507 destIE = ift->interfaceAt(controlInfo->interfaceId());
00508
00509 IPAddress src = controlInfo->srcAddr();
00510
00511 // when source address was given, use it; otherwise it'll get the address
00512 // of the outgoing interface after routing
00513 if (!src.isUnspecified())
00514 {
00515 // if interface parameter does not match existing interface, do not send datagram
00516 if (rt->interfaceByAddress(src)==NULL)
00517 opp_error("Wrong source address %s in (%s)%s: no interface with such address",
00518 src.str().c_str(), transportPacket->className(), transportPacket->fullName());
00519 datagram->setSrcAddress(src);
00520 }
00521
00522 // set other fields
00523 datagram->setDiffServCodePoint(controlInfo->diffServCodePoint());
00524
00525 datagram->setIdentification(curFragmentId++);
00526 datagram->setMoreFragments(false);
00527 datagram->setDontFragment (controlInfo->dontFragment());
00528 datagram->setFragmentOffset(0);
00529
00530 datagram->setTimeToLive(
00531 controlInfo->timeToLive() > 0 ?
00532 controlInfo->timeToLive() :
00533 (datagram->destAddress().isMulticast() ? defaultMCTimeToLive : defaultTimeToLive)
00534 );
00535
00536 datagram->setTransportProtocol(controlInfo->protocol());
00537 delete controlInfo;
00538
00539 // setting IP options is currently not supported
00540
00541 return datagram;
00542 }
|
|
|
Processing of IP datagrams. Called when a datagram reaches the front of the queue. Implements AbstractQueue. 00071 {
00072 if (msg->arrivalGate()->isName("transportIn"))
00073 {
00074 handleMessageFromHL(msg);
00075 }
00076 else if (dynamic_cast<ARPPacket *>(msg))
00077 {
00078 // dispatch ARP packets to ARP
00079 handleARP((ARPPacket *)msg);
00080 }
00081 else
00082 {
00083 IPDatagram *dgram = check_and_cast<IPDatagram *>(msg);
00084 handlePacketFromNetwork(dgram);
00085 }
00086
00087 if (ev.isGUI())
00088 updateDisplayString();
00089 }
|
|
||||||||||||||||
|
Fragment packet if needed, then send it to the selected interface using sendDatagramToOutput(). 00433 {
00434 int mtu = ie->mtu();
00435
00436 // check if datagram does not require fragmentation
00437 if (datagram->byteLength() <= mtu)
00438 {
00439 sendDatagramToOutput(datagram, ie, nextHopAddr);
00440 return;
00441 }
00442
00443 int headerLength = datagram->headerLength();
00444 int payload = datagram->byteLength() - headerLength;
00445
00446 int noOfFragments =
00447 int(ceil((float(payload)/mtu) /
00448 (1-float(headerLength)/mtu) ) ); // FIXME ???
00449
00450 // if "don't fragment" bit is set, throw datagram away and send ICMP error message
00451 if (datagram->dontFragment() && noOfFragments>1)
00452 {
00453 EV << "datagram larger than MTU and don't fragment bit set, sending ICMP_DESTINATION_UNREACHABLE\n";
00454 icmpAccess.get()->sendErrorMessage(datagram, ICMP_DESTINATION_UNREACHABLE,
00455 ICMP_FRAGMENTATION_ERROR_CODE);
00456 return;
00457 }
00458
00459 // create and send fragments
00460 EV << "Breaking datagram into " << noOfFragments << " fragments\n";
00461 std::string fragMsgName = datagram->name();
00462 fragMsgName += "-frag";
00463
00464 // FIXME revise this!
00465 for (int i=0; i<noOfFragments; i++)
00466 {
00467 // FIXME is it ok that full encapsulated packet travels in every datagram fragment?
00468 // should better travel in the last fragment only. Cf. with reassembly code!
00469 IPDatagram *fragment = (IPDatagram *) datagram->dup();
00470 fragment->setName(fragMsgName.c_str());
00471
00472 // total_length equal to mtu, except for last fragment;
00473 // "more fragments" bit is unchanged in the last fragment, otherwise true
00474 if (i != noOfFragments-1)
00475 {
00476 fragment->setMoreFragments(true);
00477 fragment->setByteLength(mtu);
00478 }
00479 else
00480 {
00481 // size of last fragment
00482 int bytes = datagram->byteLength() - (noOfFragments-1) * (mtu - datagram->headerLength());
00483 fragment->setByteLength(bytes);
00484 }
00485 fragment->setFragmentOffset( i*(mtu - datagram->headerLength()) );
00486
00487 sendDatagramToOutput(fragment, ie, nextHopAddr);
00488 }
00489
00490 delete datagram;
00491 }
|
|
|
Handle incoming ARP packets by sending them over "queueOut" to ARP. 00131 {
00132 // FIXME hasBitError() check missing!
00133
00134 // delete old control info
00135 delete msg->removeControlInfo();
00136
00137 // dispatch ARP packets to ARP and let it know the gate index it arrived on
00138 InterfaceEntry *fromIE = sourceInterfaceFrom(msg);
00139 ASSERT(fromIE);
00140
00141 IPRoutingDecision *routingDecision = new IPRoutingDecision();
00142 routingDecision->setInterfaceId(fromIE->interfaceId());
00143 msg->setControlInfo(routingDecision);
00144
00145 send(msg, "queueOut");
00146 }
|
|
|
Handle messages (typically packets to be send in IP) from transport or ICMP. Invokes encapsulate(), then routePacket(). 00173 {
00174 // if no interface exists, do not send datagram
00175 if (ift->numInterfaces() == 0)
00176 {
00177 EV << "No interfaces exist, dropping packet\n";
00178 delete msg;
00179 return;
00180 }
00181
00182 // encapsulate and send
00183 InterfaceEntry *destIE; // will be filled in by encapsulate()
00184 IPDatagram *datagram = encapsulate(msg, destIE);
00185
00186 // route packet
00187 if (!datagram->destAddress().isMulticast())
00188 routePacket(datagram, destIE, true);
00189 else
00190 routeMulticastPacket(datagram, destIE, NULL);
00191 }
|
|
|
Handle IPDatagram messages arriving from lower layer. Decrements TTL, then invokes routePacket(). 00098 {
00099 //
00100 // "Prerouting"
00101 //
00102
00103 // check for header biterror
00104 if (datagram->hasBitError())
00105 {
00106 // probability of bit error in header = size of header / size of total message
00107 // (ignore bit error if in payload)
00108 double relativeHeaderLength = datagram->headerLength() / (double)datagram->byteLength();
00109 if (dblrand() <= relativeHeaderLength)
00110 {
00111 EV << "bit error found, sending ICMP_PARAMETER_PROBLEM\n";
00112 icmpAccess.get()->sendErrorMessage(datagram, ICMP_PARAMETER_PROBLEM, 0);
00113 return;
00114 }
00115 }
00116
00117 // remove control info
00118 delete datagram->removeControlInfo();
00119
00120 // hop counter decrement; FIXME but not if it will be locally delivered
00121 datagram->setTimeToLive(datagram->timeToLive()-1);
00122
00123 // route packet
00124 if (!datagram->destAddress().isMulticast())
00125 routePacket(datagram, NULL, false);
00126 else
00127 routeMulticastPacket(datagram, NULL, sourceInterfaceFrom(datagram));
00128 }
|
|
|
Handle incoming ICMP messages. 00149 {
00150 switch (msg->getType())
00151 {
00152 case ICMP_REDIRECT: // TODO implement redirect handling
00153 case ICMP_DESTINATION_UNREACHABLE:
00154 case ICMP_TIME_EXCEEDED:
00155 case ICMP_PARAMETER_PROBLEM: {
00156 // ICMP errors are delivered to the appropriate higher layer protocol
00157 IPDatagram *bogusPacket = check_and_cast<IPDatagram *>(msg->encapsulatedMsg());
00158 int protocol = bogusPacket->transportProtocol();
00159 int gateindex = mapping.outputGateForProtocol(protocol);
00160 send(msg, "transportOut", gateindex);
00161 break;
00162 }
00163 default: {
00164 // all others are delivered to ICMP: ICMP_ECHO_REQUEST, ICMP_ECHO_REPLY,
00165 // ICMP_TIMESTAMP_REQUEST, ICMP_TIMESTAMP_REPLY, etc.
00166 int gateindex = mapping.outputGateForProtocol(IP_PROT_ICMP);
00167 send(msg, "transportOut", gateindex);
00168 }
00169 }
00170 }
|
|
|
Initialization Reimplemented from QueueBase. 00035 {
00036 QueueBase::initialize();
00037
00038 ift = InterfaceTableAccess().get();
00039 rt = RoutingTableAccess().get();
00040
00041 defaultTimeToLive = par("timeToLive");
00042 defaultMCTimeToLive = par("multicastTimeToLive");
00043 fragmentTimeoutTime = par("fragmentTimeout");
00044 mapping.parseProtocolMapping(par("protocolMapping"));
00045
00046 curFragmentId = 0;
00047 lastCheckTime = 0;
00048 fragbuf.init(icmpAccess.get());
00049
00050 numMulticast = numLocalDeliver = numDropped = numUnroutable = numForwarded = 0;
00051
00052 WATCH(numMulticast);
00053 WATCH(numLocalDeliver);
00054 WATCH(numDropped);
00055 WATCH(numUnroutable);
00056 WATCH(numForwarded);
00057 }
|
|
|
Perform reassembly of fragmented datagrams, then send them up to the higher layers using sendToHL(). 00364 {
00365 // Defragmentation. skip defragmentation if datagram is not fragmented
00366 if (datagram->fragmentOffset()!=0 || datagram->moreFragments())
00367 {
00368 EV << "Datagram fragment: offset=" << datagram->fragmentOffset()
00369 << ", MORE=" << (datagram->moreFragments() ? "true" : "false") << ".\n";
00370
00371 // erase timed out fragments in fragmentation buffer; check every 10 seconds max
00372 if (simTime() >= lastCheckTime + 10)
00373 {
00374 lastCheckTime = simTime();
00375 fragbuf.purgeStaleFragments(simTime()-fragmentTimeoutTime);
00376 }
00377
00378 datagram = fragbuf.addFragment(datagram, simTime());
00379 if (!datagram)
00380 {
00381 EV << "No complete datagram yet.\n";
00382 return;
00383 }
00384 EV << "This fragment completes the datagram.\n";
00385 }
00386
00387 // decapsulate and send on appropriate output gate
00388 int protocol = datagram->transportProtocol();
00389 cMessage *packet = decapsulateIP(datagram);
00390
00391 if (protocol==IP_PROT_ICMP)
00392 {
00393 // incoming ICMP packets are handled specially
00394 handleReceivedICMP(check_and_cast<ICMPMessage *>(packet));
00395 }
00396 else if (protocol==IP_PROT_IP)
00397 {
00398 // tunnelled IP packets are handled separately
00399 send(packet, "preRoutingOut");
00400 }
00401 else
00402 {
00403 int gateindex = mapping.outputGateForProtocol(protocol);
00404 send(packet, "transportOut", gateindex);
00405 }
00406 }
|
|
||||||||||||||||
|
Forwards packets to all multicast destinations, using fragmentAndSend(). 00264 {
00265 IPAddress destAddr = datagram->destAddress();
00266 EV << "Routing multicast datagram `" << datagram->name() << "' with dest=" << destAddr << "\n";
00267
00268 numMulticast++;
00269
00270 // DVMRP: process datagram only if sent locally or arrived on the shortest
00271 // route (provided routing table already contains srcAddr); otherwise
00272 // discard and continue.
00273 InterfaceEntry *shortestPathIE = rt->interfaceForDestAddr(datagram->srcAddress());
00274 if (fromIE!=NULL && shortestPathIE!=NULL && fromIE!=shortestPathIE)
00275 {
00276 // FIXME count dropped
00277 EV << "Packet dropped.\n";
00278 delete datagram;
00279 return;
00280 }
00281
00282 // if received from the network...
00283 if (fromIE!=NULL)
00284 {
00285 // check for local delivery
00286 if (rt->multicastLocalDeliver(destAddr))
00287 {
00288 IPDatagram *datagramCopy = (IPDatagram *) datagram->dup();
00289
00290 // FIXME code from the MPLS model: set packet dest address to routerId (???)
00291 datagramCopy->setDestAddress(rt->routerId());
00292
00293 localDeliver(datagramCopy);
00294 }
00295
00296 // don't forward if IP forwarding is off
00297 if (!rt->ipForward())
00298 {
00299 delete datagram;
00300 return;
00301 }
00302
00303 // don't forward if dest address is link-scope
00304 if (destAddr.isLinkLocalMulticast())
00305 {
00306 delete datagram;
00307 return;
00308 }
00309
00310 }
00311
00312 // routed explicitly via IP_MULTICAST_IF
00313 if (destIE!=NULL)
00314 {
00315 ASSERT(datagram->destAddress().isMulticast());
00316
00317 EV << "multicast packet explicitly routed via output interface " << destIE->name() << endl;
00318
00319 // set datagram source address if not yet set
00320 if (datagram->srcAddress().isUnspecified())
00321 datagram->setSrcAddress(destIE->ipv4()->inetAddress());
00322
00323 // send
00324 fragmentAndSend(datagram, destIE, datagram->destAddress());
00325
00326 return;
00327 }
00328
00329 // now: routing
00330 MulticastRoutes routes = rt->multicastRoutesFor(destAddr);
00331 if (routes.size()==0)
00332 {
00333 // no destination: delete datagram
00334 delete datagram;
00335 }
00336 else
00337 {
00338 // copy original datagram for multiple destinations
00339 for (unsigned int i=0; i<routes.size(); i++)
00340 {
00341 InterfaceEntry *destIE = routes[i].interf;
00342
00343 // don't forward to input port
00344 if (destIE && destIE!=fromIE)
00345 {
00346 IPDatagram *datagramCopy = (IPDatagram *) datagram->dup();
00347
00348 // set datagram source address if not yet set
00349 if (datagramCopy->srcAddress().isUnspecified())
00350 datagramCopy->setSrcAddress(destIE->ipv4()->inetAddress());
00351
00352 // send
00353 IPAddress nextHopAddr = routes[i].gateway;
00354 fragmentAndSend(datagramCopy, destIE, nextHopAddr);
00355 }
00356 }
00357
00358 // only copies sent, delete original datagram
00359 delete datagram;
00360 }
00361 }
|
|
||||||||||||||||
|
Performs routing. Based on the routing decision, it dispatches to localDeliver() for local packets, to fragmentAndSend() for forwarded packets, to handleMulticastPacket() for multicast packets, or drops the packet if it's unroutable or forwarding is off. 00194 {
00195 // TBD add option handling code here
00196
00197 IPAddress destAddr = datagram->destAddress();
00198
00199 EV << "Routing datagram `" << datagram->name() << "' with dest=" << destAddr << ": ";
00200
00201 // check for local delivery
00202 if (rt->localDeliver(destAddr))
00203 {
00204 EV << "local delivery\n";
00205 if (datagram->srcAddress().isUnspecified())
00206 datagram->setSrcAddress(destAddr); // allows two apps on the same host to communicate
00207 numLocalDeliver++;
00208 localDeliver(datagram);
00209 return;
00210 }
00211
00212 // if datagram arrived from input gate and IP_FORWARD is off, delete datagram
00213 if (!fromHL && !rt->ipForward())
00214 {
00215 EV << "forwarding off, dropping packet\n";
00216 numDropped++;
00217 delete datagram;
00218 return;
00219 }
00220
00221 IPAddress nextHopAddr;
00222
00223 // if output port was explicitly requested, use that, otherwise use IP routing
00224 if (destIE)
00225 {
00226 EV << "using manually specified output interface " << destIE->name() << "\n";
00227 // and nextHopAddr remains unspecified
00228 }
00229 else
00230 {
00231 // use IP routing (lookup in routing table)
00232 RoutingEntry *re = rt->findBestMatchingRoute(destAddr);
00233
00234 // error handling: destination address does not exist in routing table:
00235 // notify ICMP, throw packet away and continue
00236 if (re==NULL)
00237 {
00238 EV << "unroutable, sending ICMP_DESTINATION_UNREACHABLE\n";
00239 numUnroutable++;
00240 icmpAccess.get()->sendErrorMessage(datagram, ICMP_DESTINATION_UNREACHABLE, 0);
00241 return;
00242 }
00243
00244 // extract interface and next-hop address from routing table entry
00245 destIE = re->interfacePtr;
00246 nextHopAddr = re->gateway;
00247 }
00248
00249 // set datagram source address if not yet set
00250 if (datagram->srcAddress().isUnspecified())
00251 datagram->setSrcAddress(destIE->ipv4()->inetAddress());
00252
00253 // default: send datagram to fragmentation
00254 EV << "output interface is " << destIE->name() << ", next-hop address: " << nextHopAddr << "\n";
00255 numForwarded++;
00256
00257 //
00258 // fragment and send the packet
00259 //
00260 fragmentAndSend(datagram, destIE, nextHopAddr);
00261 }
|
|
||||||||||||||||
|
Last TTL check, then send datagram on the given interface. 00545 {
00546 // hop counter check
00547 if (datagram->timeToLive() <= 0)
00548 {
00549 // drop datagram, destruction responsibility in ICMP
00550 EV << "datagram TTL reached zero, sending ICMP_TIME_EXCEEDED\n";
00551 icmpAccess.get()->sendErrorMessage(datagram, ICMP_TIME_EXCEEDED, 0);
00552 return;
00553 }
00554
00555 // send out datagram to ARP, with control info attached
00556 IPRoutingDecision *routingDecision = new IPRoutingDecision();
00557 routingDecision->setInterfaceId(ie->interfaceId());
00558 routingDecision->setNextHopAddr(nextHopAddr);
00559 datagram->setControlInfo(routingDecision);
00560
00561 send(datagram, "queueOut");
00562 }
|
|
|
00092 {
00093 cGate *g = msg->arrivalGate();
00094 return g ? ift->interfaceByNetworkLayerGateIndex(g->index()) : NULL;
00095 }
|
|
|
00060 {
00061 char buf[80] = "";
00062 if (numForwarded>0) sprintf(buf+strlen(buf), "fwd:%d ", numForwarded);
00063 if (numLocalDeliver>0) sprintf(buf+strlen(buf), "up:%d ", numLocalDeliver);
00064 if (numMulticast>0) sprintf(buf+strlen(buf), "mcast:%d ", numMulticast);
00065 if (numDropped>0) sprintf(buf+strlen(buf), "DROP:%d ", numDropped);
00066 if (numUnroutable>0) sprintf(buf+strlen(buf), "UNROUTABLE:%d ", numUnroutable);
00067 displayString().setTagArg("t",0,buf);
00068 }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1.4.1