#include <IPv6.h>
Inheritance diagram for IPv6:
cMessage * IPv6::decapsulate | ( | IPv6Datagram * | datagram | ) | [protected, virtual] |
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 }
IPv6Datagram * IPv6::encapsulate | ( | cMessage * | transportPacket, | |
InterfaceEntry *& | destIE | |||
) | [protected] |
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 }
void IPv6::endService | ( | cMessage * | msg | ) | [protected, virtual] |
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 }
void IPv6::fragmentAndRoute | ( | IPv6Datagram * | datagram, | |
InterfaceEntry * | destIE = NULL | |||
) | [protected, virtual] |
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 }
void IPv6::handleDatagramFromNetwork | ( | IPv6Datagram * | datagram | ) | [protected, virtual] |
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 }
void IPv6::handleMessageFromHL | ( | cMessage * | msg | ) | [protected, virtual] |
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 }
void IPv6::handleReceivedICMP | ( | ICMPv6Message * | msg | ) | [protected, virtual] |
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 }
void IPv6::initialize | ( | ) | [protected, virtual] |
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 }
void IPv6::localDeliver | ( | IPv6Datagram * | datagram | ) | [protected, virtual] |
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 }
void IPv6::routeMulticastPacket | ( | IPv6Datagram * | datagram, | |
InterfaceEntry * | destIE, | |||
InterfaceEntry * | fromIE | |||
) | [protected, virtual] |
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 }
void IPv6::routePacket | ( | IPv6Datagram * | datagram, | |
InterfaceEntry * | destIE, | |||
bool | fromHL | |||
) | [protected, virtual] |
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 }
void IPv6::sendDatagramToOutput | ( | IPv6Datagram * | datagram, | |
InterfaceEntry * | ie, | |||
const MACAddress & | macAddr | |||
) | [protected, virtual] |
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 }
InterfaceEntry * IPv6::sourceInterfaceFrom | ( | cMessage * | msg | ) | [protected] |
00094 { 00095 cGate *g = msg->arrivalGate(); 00096 return g ? ift->interfaceByNetworkLayerGateIndex(g->index()) : NULL; 00097 }
void IPv6::updateDisplayString | ( | ) | [protected] |
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 }
long IPv6::curFragmentId [protected] |
IPv6FragBuf IPv6::fragbuf [protected] |
ICMPv6* IPv6::icmp [protected] |
InterfaceTable* IPv6::ift [protected] |
simtime_t IPv6::lastCheckTime [protected] |
ProtocolMapping IPv6::mapping [protected] |
IPv6NeighbourDiscovery* IPv6::nd [protected] |
int IPv6::numDropped [protected] |
int IPv6::numForwarded [protected] |
int IPv6::numLocalDeliver [protected] |
int IPv6::numMulticast [protected] |
int IPv6::numUnroutable [protected] |
RoutingTable6* IPv6::rt [protected] |