#include <IP.h>
Inheritance diagram for IP:
|
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 }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|