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

|
|
00125 {}
|
|
|
Decapsulate and return encapsulated packet after attaching IPv6ControlInfo. 00480 {
00481 // decapsulate transport packet
00482 InterfaceEntry *fromIE = sourceInterfaceFrom(datagram);
00483 cMessage *packet = datagram->decapsulate();
00484
00485 // create and fill in control info
00486 IPv6ControlInfo *controlInfo = new IPv6ControlInfo();
00487 controlInfo->setProtocol(datagram->transportProtocol());
00488 controlInfo->setSrcAddr(datagram->srcAddress());
00489 controlInfo->setDestAddr(datagram->destAddress());
00490 controlInfo->setHopLimit(datagram->hopLimit());
00491 controlInfo->setInterfaceId(fromIE ? fromIE->interfaceId() : -1);
00492
00493 // original IP datagram might be needed in upper layers to send back ICMP error message
00494 controlInfo->setOrigDatagram(datagram);
00495
00496 // attach control info
00497 packet->setControlInfo(controlInfo);
00498
00499 return packet;
00500 }
|
|
||||||||||||
|
Encapsulate packet coming from higher layers into IPv6Datagram 00503 {
00504 IPv6ControlInfo *controlInfo = check_and_cast<IPv6ControlInfo*>(transportPacket->removeControlInfo());
00505
00506 IPv6Datagram *datagram = new IPv6Datagram(transportPacket->name());
00507 datagram->setByteLength(datagram->calculateHeaderByteLength());
00508 datagram->encapsulate(transportPacket);
00509
00510 // IPV6_MULTICAST_IF option, but allow interface selection for unicast packets as well
00511 destIE = ift->interfaceAt(controlInfo->interfaceId());
00512
00513 // set source and destination address
00514 IPv6Address dest = controlInfo->destAddr();
00515 datagram->setDestAddress(dest);
00516
00517 IPv6Address src = controlInfo->srcAddr();
00518
00519 // when source address was given, use it; otherwise it'll get the address
00520 // of the outgoing interface after routing
00521 if (!src.isUnspecified())
00522 {
00523 // if interface parameter does not match existing interface, do not send datagram
00524 if (rt->interfaceByAddress(src)==NULL)
00525 opp_error("Wrong source address %s in (%s)%s: no interface with such address",
00526 src.str().c_str(), transportPacket->className(), transportPacket->fullName());
00527 datagram->setSrcAddress(src);
00528 }
00529
00530 // set other fields
00531 datagram->setHopLimit(controlInfo->hopLimit()>0 ? controlInfo->hopLimit() : 32); //FIXME use iface hop limit instead of 32?
00532 datagram->setTransportProtocol(controlInfo->protocol());
00533 delete controlInfo;
00534
00535 // setting IP options is currently not supported
00536
00537 return datagram;
00538 }
|
|
|
Processing of IPv6 datagrams. Called when a datagram reaches the front of the queue. Implements AbstractQueue. 00074 {
00075 if (msg->arrivalGate()->isName("transportIn") ||
00076 (msg->arrivalGate()->isName("ndIn") && dynamic_cast<IPv6NDMessage*>(msg)) ||
00077 (msg->arrivalGate()->isName("icmpIn") && dynamic_cast<ICMPv6Message*>(msg)))//Added this for ICMP msgs from ICMP module-WEI
00078 {
00079 // packet from upper layers or ND: encapsulate and send out
00080 handleMessageFromHL(msg);
00081 }
00082 else
00083 {
00084 // datagram from network or from ND: localDeliver and/or route
00085 IPv6Datagram *dgram = check_and_cast<IPv6Datagram *>(msg);
00086 handleDatagramFromNetwork(dgram);
00087 }
00088
00089 if (ev.isGUI())
00090 updateDisplayString();
00091 }
|
|
||||||||||||
|
Fragment packet if needed, then send it. The optional output gate index is only used if higher layer protocol explicitly requests the datagram to be sent out on a specific interface, bypassing the routing table. 00147 {
00148 /*
00149 FIXME implement fragmentation here.
00150 1. determine output interface
00151 2. compare packet size with interface MTU
00152 3. if bigger, do fragmentation
00153 int mtu = ift->interfaceByPortNo(outputGateIndex)->mtu();
00154 */
00155 EV << "fragmentation not implemented yet\n";
00156
00157 // route packet
00158 if (destIE!=NULL)
00159 sendDatagramToOutput(datagram, destIE, MACAddress::BROADCAST_ADDRESS); // FIXME what MAC address to use?
00160 else if (!datagram->destAddress().isMulticast())
00161 routePacket(datagram, destIE, true);
00162 else
00163 routeMulticastPacket(datagram, destIE, NULL);
00164 }
|
|
|
Handle IPv6Datagram messages arriving from lower layer. Decrements TTL, then invokes routePacket(). 00100 {
00101 // check for header biterror
00102 if (datagram->hasBitError())
00103 {
00104 EV << "bit error\n";return; // revise!
00105 /*FIXME revise
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 icmp->sendErrorMessage(datagram, ICMP_PARAMETER_PROBLEM, 0);
00113 return;
00114 }
00115 */
00116 }
00117
00118 // remove control info
00119 delete datagram->removeControlInfo();
00120
00121 // routepacket
00122 if (!datagram->destAddress().isMulticast())
00123 routePacket(datagram, NULL, false);
00124 else
00125 routeMulticastPacket(datagram, NULL, sourceInterfaceFrom(datagram));
00126 }
|
|
|
Handle messages (typically packets to be send in IPv6) from transport or ICMP. Invokes encapsulate(), then routePacket(). 00129 {
00130 // if no interface exists, do not send datagram
00131 if (ift->numInterfaces() == 0)
00132 {
00133 EV << "No interfaces exist, dropping packet\n";
00134 delete msg;
00135 return;
00136 }
00137
00138 // encapsulate upper-layer packet into IPv6Datagram
00139 InterfaceEntry *destIE; // to be filled in by encapsulate()
00140 IPv6Datagram *datagram = encapsulate(msg, destIE);
00141
00142 // possibly fragment (in IPv6, only the source node does that), then route it
00143 fragmentAndRoute(datagram, destIE);
00144 }
|
|
|
Handle incoming ICMP messages. 00452 {
00453 switch (msg->type())
00454 {
00455 case ICMPv6_REDIRECT: // TODO implement redirect handling
00456 case ICMPv6_DESTINATION_UNREACHABLE:
00457 case ICMPv6_PACKET_TOO_BIG:
00458 case ICMPv6_TIME_EXCEEDED:
00459 case ICMPv6_PARAMETER_PROBLEM: {
00460 // ICMP errors are delivered to the appropriate higher layer protocols
00461 IPv6Datagram *bogusPacket = check_and_cast<IPv6Datagram *>(msg->encapsulatedMsg());
00462 int protocol = bogusPacket->transportProtocol();
00463 int gateindex = mapping.outputGateForProtocol(protocol);
00464 send(msg, "transportOut", gateindex);
00465 break;
00466 }
00467 default: {
00468 // all others are delivered to ICMP:
00469 // ICMPv6_ECHO_REQUEST, ICMPv6_ECHO_REPLY, ICMPv6_MLD_QUERY, ICMPv6_MLD_REPORT,
00470 // ICMPv6_MLD_DONE, ICMPv6_ROUTER_SOL, ICMPv6_ROUTER_AD, ICMPv6_NEIGHBOUR_SOL,
00471 // ICMPv6_NEIGHBOUR_AD, ICMPv6_MLDv2_REPORT
00472 int gateindex = mapping.outputGateForProtocol(IP_PROT_ICMP);
00473 send(msg, "transportOut", gateindex);
00474 }
00475 }
00476 }
|
|
|
Initialization Reimplemented from QueueBase. 00039 {
00040 QueueBase::initialize();
00041
00042 ift = InterfaceTableAccess().get();
00043 rt = RoutingTable6Access().get();
00044 nd = IPv6NeighbourDiscoveryAccess().get();
00045 icmp = ICMPv6Access().get();
00046
00047 mapping.parseProtocolMapping(par("protocolMapping"));
00048
00049 curFragmentId = 0;
00050 lastCheckTime = 0;
00051 fragbuf.init(icmp);
00052
00053 numMulticast = numLocalDeliver = numDropped = numUnroutable = numForwarded = 0;
00054
00055 WATCH(numMulticast);
00056 WATCH(numLocalDeliver);
00057 WATCH(numDropped);
00058 WATCH(numUnroutable);
00059 WATCH(numForwarded);
00060 }
|
|
|
Perform reassembly of fragmented datagrams, then send them up to the higher layers using sendToHL(). 00398 {
00399 /* FIXME revise and complete defragmentation
00400 // Defragmentation. skip defragmentation if datagram is not fragmented
00401 if (datagram->fragmentOffset()!=0 || datagram->moreFragments())
00402 {
00403 EV << "Datagram fragment: offset=" << datagram->fragmentOffset()
00404 << ", MORE=" << (datagram->moreFragments() ? "true" : "false") << ".\n";
00405
00406 // erase timed out fragments in fragmentation buffer; check every 10 seconds max
00407 if (simTime() >= lastCheckTime + 10)
00408 {
00409 lastCheckTime = simTime();
00410 fragbuf.purgeStaleFragments(simTime()-FRAGMENT_TIMEOUT);
00411 }
00412
00413 datagram = fragbuf.addFragment(datagram, simTime());
00414 if (!datagram)
00415 {
00416 EV << "No complete datagram yet.\n";
00417 return;
00418 }
00419 EV << "This fragment completes the datagram.\n";
00420 }
00421 */
00422 // decapsulate and send on appropriate output gate
00423 int protocol = datagram->transportProtocol();
00424 cMessage *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 }//Added by WEI to forward ICMPv6 msgs to ICMPv6 module.
00436 else if (protocol==IP_PROT_IP || protocol==IP_PROT_IPv6)
00437 {
00438 EV << "Tunnelled IP datagram\n";
00439 // FIXME handle tunnelling
00440 error("tunnelling not yet implemented");
00441 }
00442 else
00443 {
00444 int gateindex = mapping.outputGateForProtocol(protocol);
00445 EV << "Protocol " << protocol << ", passing up on gate " << gateindex << "\n";
00446 //TODO: Indication of forward progress
00447 send(packet, "transportOut", gateindex);
00448 }
00449 }
|
|
||||||||||||||||
|
Forwards packets to all multicast destinations, using fragmentAndSend(). 00273 {
00274 const IPv6Address& destAddr = datagram->destAddress();
00275
00276 EV << "destination address " << destAddr << " is multicast, doing multicast routing\n";
00277 numMulticast++;
00278
00279 // if received from the network...
00280 if (fromIE!=NULL)
00281 {
00282 // deliver locally
00283 if (rt->localDeliver(destAddr))
00284 {
00285 EV << "local delivery of multicast packet\n";
00286 numLocalDeliver++;
00287 localDeliver((IPv6Datagram *)datagram->dup());
00288 }
00289
00290 // if datagram arrived from input gate and IP forwarding is off, delete datagram
00291 if (!rt->isRouter())
00292 {
00293 EV << "forwarding is off\n";
00294 delete datagram;
00295 return;
00296 }
00297
00298 // make sure scope of multicast address is large enough to be forwarded to other links
00299 if (destAddr.multicastScope()<=2)
00300 {
00301 EV << "multicast dest address is link-local (or smaller) scope\n";
00302 delete datagram;
00303 return;
00304 }
00305
00306 // hop counter decrement: only if datagram arrived from network, and will be
00307 // sent out to the network (hoplimit check will be done just before sending
00308 // out datagram)
00309 // TBD: in IPv4, arrange TTL check like this
00310 datagram->setHopLimit(datagram->hopLimit()-1);
00311 }
00312
00313 // for now, we just send it out on every interface except on which it came. FIXME better!!!
00314 EV << "sending out datagram on every interface (except incoming one)\n";
00315 for (int i=0; i<ift->numInterfaces(); i++)
00316 {
00317 InterfaceEntry *ie = ift->interfaceAt(i);
00318 if (fromIE!=ie)
00319 sendDatagramToOutput((IPv6Datagram *)datagram->dup(), ie, MACAddress::BROADCAST_ADDRESS);
00320 }
00321 delete datagram;
00322
00323 /* FIXME implement handling of multicast
00324
00325 According to Gopi: "multicast routing table" should map
00326 srcAddr+multicastDestAddr to a set of next hops (interface+nexthopAddr)
00327 Where srcAddr is the multicast server, and destAddr sort of narrows it down to a given stream
00328
00329 // FIXME multicast-->tunneling link (present in original IPSuite) missing from here
00330
00331 // DVMRP: process datagram only if sent locally or arrived on the shortest
00332 // route (provided routing table already contains srcAddr); otherwise
00333 // discard and continue.
00334 int inputGateIndex = datagram->arrivalGate() ? datagram->arrivalGate()->index() : -1;
00335 int shortestPathInputGateIndex = rt->outputGateIndexNo(datagram->srcAddress());
00336 if (inputGateIndex!=-1 && shortestPathInputGateIndex!=-1 && inputGateIndex!=shortestPathInputGateIndex)
00337 {
00338 // FIXME count dropped
00339 EV << "Packet dropped.\n";
00340 delete datagram;
00341 return;
00342 }
00343
00344 // check for local delivery
00345 IPv6Address destAddress = datagram->destAddress();
00346 if (rt->multicastLocalDeliver(destAddress))
00347 {
00348 IPv6Datagram *datagramCopy = (IPv6Datagram *) datagram->dup();
00349
00350 // FIXME code from the MPLS model: set packet dest address to routerId (???)
00351 datagramCopy->setDestAddress(rt->routerId());
00352
00353 localDeliver(datagramCopy);
00354 }
00355
00356 // forward datagram only if IP forward is enabled, or sent locally
00357 if (inputGateIndex!=-1 && !rt->isRouter())
00358 {
00359 delete datagram;
00360 return;
00361 }
00362
00363 MulticastRoutes routes = rt->multicastRoutesFor(destAddress);
00364 if (routes.size()==0)
00365 {
00366 // no destination: delete datagram
00367 delete datagram;
00368 }
00369 else
00370 {
00371 // copy original datagram for multiple destinations
00372 for (unsigned int i=0; i<routes.size(); i++)
00373 {
00374 int outputGateIndex = routes[i].interf->outputGateIndex();
00375
00376 // don't forward to input port
00377 if (outputGateIndex>=0 && outputGateIndex!=inputGateIndex)
00378 {
00379 IPv6Datagram *datagramCopy = (IPv6Datagram *) datagram->dup();
00380
00381 // set datagram source address if not yet set
00382 if (datagramCopy->srcAddress().isUnspecified())
00383 datagramCopy->setSrcAddress(ift->interfaceByPortNo(outputGateIndex)->ipv6()->inetAddress());
00384
00385 // send
00386 IPv6Address nextHopAddr = routes[i].gateway;
00387 sendDatagramToOutput(datagramCopy, outputGateIndex, macAddr);
00388 }
00389 }
00390
00391 // only copies sent, delete original datagram
00392 delete datagram;
00393 }
00394 */
00395 }
|
|
||||||||||||||||
|
Performs routing. Based on the routing decision, it dispatches to localDeliver() for local packets, to fragmentAndSend() for forwarded packets, to routeMulticastPacket() for multicast packets, or drops the packet if it's unroutable or forwarding is off. 00167 {
00168 // TBD add option handling code here
00169 IPv6Address destAddress = datagram->destAddress();
00170
00171 EV << "Routing datagram `" << datagram->name() << "' with dest=" << destAddress << ": ";
00172
00173 // local delivery of unicast packets
00174 if (rt->localDeliver(destAddress))
00175 {
00176 EV << "local delivery\n";
00177 if (datagram->srcAddress().isUnspecified())
00178 datagram->setSrcAddress(destAddress); // allows two apps on the same host to communicate
00179 numLocalDeliver++;
00180 localDeliver(datagram);
00181 return;
00182 }
00183
00184 if (!fromHL)
00185 {
00186 // if datagram arrived from input gate and IP forwarding is off, delete datagram
00187 //yes but datagrams from the ND module is getting dropped too!-WEI
00188 //so we add a 2nd condition
00189 // FIXME rewrite code so that condition is cleaner --Andras
00190 //if (!rt->isRouter())
00191 if (!rt->isRouter() && !(datagram->arrivalGate()->isName("ndIn")))
00192 {
00193 EV << "forwarding is off, dropping packet\n";
00194 numDropped++;
00195 delete datagram;
00196 return;
00197 }
00198
00199 // don't forward link-local addresses or weaker
00200 if (destAddress.isLinkLocal() || destAddress.isLoopback())
00201 {
00202 EV << "dest address is link-local (or weaker) scope, doesn't get forwarded\n";
00203 delete datagram;
00204 return;
00205 }
00206
00207 // hop counter decrement: only if datagram arrived from network, and will be
00208 // sent out to the network (hoplimit check will be done just before sending
00209 // out datagram)
00210 // TBD: in IPv4, arrange TTL check like this
00211 datagram->setHopLimit(datagram->hopLimit()-1);
00212 }
00213
00214 // routing
00215 // first try destination cache
00216 int interfaceId;
00217 IPv6Address nextHop = rt->lookupDestCache(destAddress, interfaceId);
00218 if (interfaceId==-1)
00219 {
00220 // address not in destination cache: do longest prefix match in routing table
00221 const IPv6Route *route = rt->doLongestPrefixMatch(destAddress);
00222 if (!route)
00223 {
00224 if (rt->isRouter())
00225 {
00226 EV << "unroutable, sending ICMPv6_DESTINATION_UNREACHABLE\n";
00227 numUnroutable++;
00228 icmp->sendErrorMessage(datagram, ICMPv6_DESTINATION_UNREACHABLE, 0); // FIXME check ICMP 'code'
00229 }
00230 else // host
00231 {
00232 EV << "no match in routing table, passing datagram to Neighbour Discovery module for default router selection\n";
00233 send(datagram, "ndOut");
00234 }
00235 return;
00236 }
00237 interfaceId = route->interfaceID();
00238 nextHop = route->nextHop();
00239 if (nextHop.isUnspecified())
00240 nextHop = destAddress; // next hop is the host itself
00241
00242 // add result into destination cache
00243 rt->updateDestCache(destAddress, nextHop, interfaceId);
00244 }
00245
00246 InterfaceEntry *ie = ift->interfaceAt(interfaceId);
00247 EV << "next hop for " << destAddress << " is " << nextHop << ", interface " << ie->name() << "\n";
00248 ASSERT(!nextHop.isUnspecified() && ie!=NULL);
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 // set datagram source address if not yet set
00260 if (datagram->srcAddress().isUnspecified())
00261 {
00262 const IPv6Address& srcAddr = ie->ipv6()->preferredAddress();
00263 ASSERT(!srcAddr.isUnspecified()); // FIXME what if we don't have an address yet?
00264 datagram->setSrcAddress(srcAddr);
00265 }
00266
00267 // send out datagram
00268 numForwarded++;
00269 sendDatagramToOutput(datagram, ie, macAddr);
00270 }
|
|
||||||||||||||||
|
Last hoplimit check, then send datagram on the given interface. 00541 {
00542 // hop counter check
00543 if (datagram->hopLimit() <= 0)
00544 {
00545 // drop datagram, destruction responsibility in ICMP
00546 EV << "datagram hopLimit reached zero, sending ICMPv6_TIME_EXCEEDED\n";
00547 icmp->sendErrorMessage(datagram, ICMPv6_TIME_EXCEEDED, 0); // FIXME check icmp 'code'
00548 return;
00549 }
00550
00551 // in link layer uses MAC addresses (basically, not PPP), add control info
00552 if (!macAddr.isUnspecified())
00553 {
00554 Ieee802Ctrl *controlInfo = new Ieee802Ctrl();
00555 controlInfo->setDest(macAddr);
00556 datagram->setControlInfo(controlInfo);
00557 }
00558
00559 // send datagram to link layer
00560 send(datagram, "queueOut", ie->networkLayerGateIndex());
00561 }
|
|
|
00094 {
00095 cGate *g = msg->arrivalGate();
00096 return g ? ift->interfaceByNetworkLayerGateIndex(g->index()) : NULL;
00097 }
|
|
|
00063 {
00064 char buf[80] = "";
00065 if (numForwarded>0) sprintf(buf+strlen(buf), "fwd:%d ", numForwarded);
00066 if (numLocalDeliver>0) sprintf(buf+strlen(buf), "up:%d ", numLocalDeliver);
00067 if (numMulticast>0) sprintf(buf+strlen(buf), "mcast:%d ", numMulticast);
00068 if (numDropped>0) sprintf(buf+strlen(buf), "DROP:%d ", numDropped);
00069 if (numUnroutable>0) sprintf(buf+strlen(buf), "UNROUTABLE:%d ", numUnroutable);
00070 displayString().setTagArg("t",0,buf);
00071 }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1.4.1