#include <IPv6.h>
IPv6 implementation.
Definition at line 36 of file IPv6.h.
cPacket * IPv6::decapsulate | ( | IPv6Datagram * | datagram | ) | [protected, virtual] |
Decapsulate and return encapsulated packet after attaching IPv6ControlInfo.
Definition at line 479 of file IPv6.cc.
Referenced by isLocalAddress().
{ // decapsulate transport packet InterfaceEntry *fromIE = getSourceInterfaceFrom(datagram); cPacket *packet = datagram->decapsulate(); // create and fill in control info IPv6ControlInfo *controlInfo = new IPv6ControlInfo(); controlInfo->setProtocol(datagram->getTransportProtocol()); controlInfo->setSrcAddr(datagram->getSrcAddress()); controlInfo->setDestAddr(datagram->getDestAddress()); controlInfo->setHopLimit(datagram->getHopLimit()); controlInfo->setInterfaceId(fromIE ? fromIE->getInterfaceId() : -1); // original IP datagram might be needed in upper layers to send back ICMP error message controlInfo->setOrigDatagram(datagram); // attach control info packet->setControlInfo(controlInfo); return packet; }
IPv6Datagram * IPv6::encapsulate | ( | cPacket * | transportPacket, | |
InterfaceEntry *& | destIE | |||
) | [protected, virtual] |
Encapsulate packet coming from higher layers into IPv6Datagram
Definition at line 502 of file IPv6.cc.
Referenced by handleMessageFromHL().
{ IPv6ControlInfo *controlInfo = check_and_cast<IPv6ControlInfo*>(transportPacket->removeControlInfo()); IPv6Datagram *datagram = new IPv6Datagram(transportPacket->getName()); datagram->setByteLength(datagram->calculateHeaderByteLength()); datagram->encapsulate(transportPacket); // IPV6_MULTICAST_IF option, but allow interface selection for unicast packets as well destIE = ift->getInterfaceById(controlInfo->getInterfaceId()); // set source and destination address IPv6Address dest = controlInfo->getDestAddr(); datagram->setDestAddress(dest); IPv6Address src = controlInfo->getSrcAddr(); // when source address was given, use it; otherwise it'll get the address // of the outgoing interface after routing if (!src.isUnspecified()) { // if interface parameter does not match existing interface, do not send datagram if (rt->getInterfaceByAddress(src)==NULL) opp_error("Wrong source address %s in (%s)%s: no interface with such address", src.str().c_str(), transportPacket->getClassName(), transportPacket->getFullName()); datagram->setSrcAddress(src); } // set other fields datagram->setHopLimit(controlInfo->getHopLimit()>0 ? controlInfo->getHopLimit() : 32); //FIXME use iface hop limit instead of 32? datagram->setTransportProtocol(controlInfo->getProtocol()); delete controlInfo; // setting IP options is currently not supported return datagram; }
void IPv6::endService | ( | cPacket * | msg | ) | [protected, virtual] |
Processing of IPv6 datagrams. Called when a datagram reaches the front of the queue.
Implements AbstractQueue.
Definition at line 72 of file IPv6.cc.
{ if (msg->getArrivalGate()->isName("transportIn") || (msg->getArrivalGate()->isName("ndIn") && dynamic_cast<IPv6NDMessage*>(msg)) || (msg->getArrivalGate()->isName("icmpIn") && dynamic_cast<ICMPv6Message*>(msg)))//Added this for ICMP msgs from ICMP module-WEI { // packet from upper layers or ND: encapsulate and send out handleMessageFromHL( msg ); } else { // datagram from network or from ND: localDeliver and/or route IPv6Datagram *dgram = check_and_cast<IPv6Datagram *>(msg); handleDatagramFromNetwork(dgram); } if (ev.isGUI()) updateDisplayString(); }
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.
Definition at line 145 of file IPv6.cc.
Referenced by handleMessageFromHL().
{ /* FIXME implement fragmentation here. 1. determine output interface 2. compare packet size with interface MTU 3. if bigger, do fragmentation int mtu = ift->interfaceByPortNo(outputGateIndex)->getMTU(); */ EV << "fragmentation not implemented yet\n"; // route packet if (destIE!=NULL) sendDatagramToOutput(datagram, destIE, MACAddress::BROADCAST_ADDRESS); // FIXME what MAC address to use? else if (!datagram->getDestAddress().isMulticast()) routePacket(datagram, destIE, true); else routeMulticastPacket(datagram, destIE, NULL); }
InterfaceEntry * IPv6::getSourceInterfaceFrom | ( | cPacket * | msg | ) | [protected, virtual] |
Definition at line 92 of file IPv6.cc.
Referenced by decapsulate(), and handleDatagramFromNetwork().
{ cGate *g = msg->getArrivalGate(); return g ? ift->getInterfaceByNetworkLayerGateIndex(g->getIndex()) : NULL; }
void IPv6::handleDatagramFromNetwork | ( | IPv6Datagram * | datagram | ) | [protected, virtual] |
Handle IPv6Datagram messages arriving from lower layer. Decrements TTL, then invokes routePacket().
Definition at line 98 of file IPv6.cc.
Referenced by endService().
{ // check for header biterror if (datagram->hasBitError()) { EV << "bit error\n";return; // revise! /*FIXME revise // probability of bit error in header = size of header / size of total message // (ignore bit error if in payload) double relativeHeaderLength = datagram->getHeaderLength() / (double)datagram->getByteLength(); if (dblrand() <= relativeHeaderLength) { EV << "bit error found, sending ICMP_PARAMETER_PROBLEM\n"; icmp->sendErrorMessage(datagram, ICMP_PARAMETER_PROBLEM, 0); return; } */ } // remove control info delete datagram->removeControlInfo(); // routepacket if (!datagram->getDestAddress().isMulticast()) routePacket(datagram, NULL, false); else routeMulticastPacket(datagram, NULL, getSourceInterfaceFrom(datagram)); }
void IPv6::handleMessageFromHL | ( | cPacket * | msg | ) | [protected, virtual] |
Handle messages (typically packets to be send in IPv6) from transport or ICMP. Invokes encapsulate(), then routePacket().
Definition at line 127 of file IPv6.cc.
Referenced by endService().
{ // if no interface exists, do not send datagram if (ift->getNumInterfaces() == 0) { EV << "No interfaces exist, dropping packet\n"; delete msg; return; } // encapsulate upper-layer packet into IPv6Datagram InterfaceEntry *destIE; // to be filled in by encapsulate() IPv6Datagram *datagram = encapsulate(msg, destIE); // possibly fragment (in IPv6, only the source node does that), then route it fragmentAndRoute(datagram, destIE); }
void IPv6::handleReceivedICMP | ( | ICMPv6Message * | msg | ) | [protected, virtual] |
Handle incoming ICMP messages.
Definition at line 451 of file IPv6.cc.
{ switch (msg->getType()) { case ICMPv6_REDIRECT: // TODO implement redirect handling case ICMPv6_DESTINATION_UNREACHABLE: case ICMPv6_PACKET_TOO_BIG: case ICMPv6_TIME_EXCEEDED: case ICMPv6_PARAMETER_PROBLEM: { // ICMP errors are delivered to the appropriate higher layer protocols IPv6Datagram *bogusPacket = check_and_cast<IPv6Datagram *>(msg->getEncapsulatedMsg()); int protocol = bogusPacket->getTransportProtocol(); int gateindex = mapping.getOutputGateForProtocol(protocol); send(msg, "transportOut", gateindex); break; } default: { // all others are delivered to ICMP: // ICMPv6_ECHO_REQUEST, ICMPv6_ECHO_REPLY, ICMPv6_MLD_QUERY, ICMPv6_MLD_REPORT, // ICMPv6_MLD_DONE, ICMPv6_ROUTER_SOL, ICMPv6_ROUTER_AD, ICMPv6_NEIGHBOUR_SOL, // ICMPv6_NEIGHBOUR_AD, ICMPv6_MLDv2_REPORT int gateindex = mapping.getOutputGateForProtocol(IP_PROT_ICMP); send(msg, "transportOut", gateindex); } } }
void IPv6::initialize | ( | ) | [protected, virtual] |
Initialization
Reimplemented from QueueBase.
Definition at line 37 of file IPv6.cc.
{ QueueBase::initialize(); ift = InterfaceTableAccess().get(); rt = RoutingTable6Access().get(); nd = IPv6NeighbourDiscoveryAccess().get(); icmp = ICMPv6Access().get(); mapping.parseProtocolMapping(par("protocolMapping")); curFragmentId = 0; lastCheckTime = 0; fragbuf.init(icmp); numMulticast = numLocalDeliver = numDropped = numUnroutable = numForwarded = 0; WATCH(numMulticast); WATCH(numLocalDeliver); WATCH(numDropped); WATCH(numUnroutable); WATCH(numForwarded); }
void IPv6::isLocalAddress | ( | IPv6Datagram * | datagram | ) | [protected, virtual] |
Perform reassembly of fragmented datagrams, then send them up to the higher layers using sendToHL().
Definition at line 397 of file IPv6.cc.
Referenced by routeMulticastPacket(), and routePacket().
{ /* FIXME revise and complete defragmentation // Defragmentation. skip defragmentation if datagram is not fragmented if (datagram->getFragmentOffset()!=0 || datagram->getMoreFragments()) { EV << "Datagram fragment: offset=" << datagram->getFragmentOffset() << ", MORE=" << (datagram->getMoreFragments() ? "true" : "false") << ".\n"; // erase timed out fragments in fragmentation buffer; check every 10 seconds max if (simTime() >= lastCheckTime + 10) { lastCheckTime = simTime(); fragbuf.purgeStaleFragments(simTime()-FRAGMENT_TIMEOUT); } datagram = fragbuf.addFragment(datagram, simTime()); if (!datagram) { EV << "No complete datagram yet.\n"; return; } EV << "This fragment completes the datagram.\n"; } */ // decapsulate and send on appropriate output gate int protocol = datagram->getTransportProtocol(); cPacket *packet = decapsulate(datagram); if (protocol==IP_PROT_IPv6_ICMP && dynamic_cast<IPv6NDMessage*>(packet)) { EV << "Neigbour Discovery packet: passing it to ND module\n"; send(packet, "ndOut"); } else if (protocol==IP_PROT_IPv6_ICMP && dynamic_cast<ICMPv6Message*>(packet)) { EV << "ICMPv6 packet: passing it to ICMPv6 module\n"; send(packet, "icmpOut"); }//Added by WEI to forward ICMPv6 msgs to ICMPv6 module. else if (protocol==IP_PROT_IP || protocol==IP_PROT_IPv6) { EV << "Tunnelled IP datagram\n"; // FIXME handle tunnelling error("tunnelling not yet implemented"); } else { int gateindex = mapping.getOutputGateForProtocol(protocol); EV << "Protocol " << protocol << ", passing up on gate " << gateindex << "\n"; //TODO: Indication of forward progress send(packet, "transportOut", gateindex); } }
void IPv6::routeMulticastPacket | ( | IPv6Datagram * | datagram, | |
InterfaceEntry * | destIE, | |||
InterfaceEntry * | fromIE | |||
) | [protected, virtual] |
Forwards packets to all multicast destinations, using fragmentAndSend().
Definition at line 272 of file IPv6.cc.
Referenced by fragmentAndRoute(), and handleDatagramFromNetwork().
{ const IPv6Address& destAddr = datagram->getDestAddress(); EV << "destination address " << destAddr << " is multicast, doing multicast routing\n"; numMulticast++; // if received from the network... if (fromIE!=NULL) { // deliver locally if (rt->isLocalAddress(destAddr)) { EV << "local delivery of multicast packet\n"; numLocalDeliver++; isLocalAddress((IPv6Datagram *)datagram->dup()); } // if datagram arrived from input gate and IP forwarding is off, delete datagram if (!rt->isRouter()) { EV << "forwarding is off\n"; delete datagram; return; } // make sure scope of multicast address is large enough to be forwarded to other links if (destAddr.getMulticastScope()<=2) { EV << "multicast dest address is link-local (or smaller) scope\n"; delete datagram; return; } // hop counter decrement: only if datagram arrived from network, and will be // sent out to the network (hoplimit check will be done just before sending // out datagram) // TBD: in IPv4, arrange TTL check like this datagram->setHopLimit(datagram->getHopLimit()-1); } // for now, we just send it out on every interface except on which it came. FIXME better!!! EV << "sending out datagram on every interface (except incoming one)\n"; for (int i=0; i<ift->getNumInterfaces(); i++) { InterfaceEntry *ie = ift->getInterface(i); if (fromIE!=ie) sendDatagramToOutput((IPv6Datagram *)datagram->dup(), ie, MACAddress::BROADCAST_ADDRESS); } delete datagram; /* FIXME implement handling of multicast According to Gopi: "multicast routing table" should map srcAddr+multicastDestAddr to a set of next hops (interface+nexthopAddr) Where srcAddr is the multicast server, and destAddr sort of narrows it down to a given stream // FIXME multicast-->tunneling link (present in original IPSuite) missing from here // DVMRP: process datagram only if sent locally or arrived on the shortest // route (provided routing table already contains srcAddr); otherwise // discard and continue. int inputGateIndex = datagram->getArrivalGate() ? datagram->getArrivalGate()->getIndex() : -1; int shortestPathInputGateIndex = rt->outputGateIndexNo(datagram->getSrcAddress()); if (inputGateIndex!=-1 && shortestPathInputGateIndex!=-1 && inputGateIndex!=shortestPathInputGateIndex) { // FIXME count dropped EV << "Packet dropped.\n"; delete datagram; return; } // check for local delivery IPv6Address destAddress = datagram->getDestAddress(); if (rt->isLocalMulticastAddress(destAddress)) { IPv6Datagram *datagramCopy = (IPv6Datagram *) datagram->dup(); // FIXME code from the MPLS model: set packet dest address to routerId (???) datagramCopy->setDestAddress(rt->getRouterId()); isLocalAddress(datagramCopy); } // forward datagram only if IP forward is enabled, or sent locally if (inputGateIndex!=-1 && !rt->isRouter()) { delete datagram; return; } MulticastRoutes routes = rt->getMulticastRoutesFor(destAddress); if (routes.size()==0) { // no destination: delete datagram delete datagram; } else { // copy original datagram for multiple destinations for (unsigned int i=0; i<routes.size(); i++) { int outputGateIndex = routes[i].interf->outputGateIndex(); // don't forward to input port if (outputGateIndex>=0 && outputGateIndex!=inputGateIndex) { IPv6Datagram *datagramCopy = (IPv6Datagram *) datagram->dup(); // set datagram source address if not yet set if (datagramCopy->getSrcAddress().isUnspecified()) datagramCopy->setSrcAddress(ift->interfaceByPortNo(outputGateIndex)->ipv6Data()->getIPAddress()); // send IPv6Address nextHopAddr = routes[i].gateway; sendDatagramToOutput(datagramCopy, outputGateIndex, macAddr); } } // only copies sent, delete original datagram delete datagram; } */ }
void IPv6::routePacket | ( | IPv6Datagram * | datagram, | |
InterfaceEntry * | destIE, | |||
bool | fromHL | |||
) | [protected, virtual] |
Performs routing. Based on the routing decision, it dispatches to isLocalAddress() 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.
Definition at line 165 of file IPv6.cc.
Referenced by fragmentAndRoute(), and handleDatagramFromNetwork().
{ // TBD add option handling code here IPv6Address destAddress = datagram->getDestAddress(); EV << "Routing datagram `" << datagram->getName() << "' with dest=" << destAddress << ": "; // local delivery of unicast packets if (rt->isLocalAddress(destAddress)) { EV << "local delivery\n"; if (datagram->getSrcAddress().isUnspecified()) datagram->setSrcAddress(destAddress); // allows two apps on the same host to communicate numLocalDeliver++; isLocalAddress(datagram); return; } if (!fromHL) { // if datagram arrived from input gate and IP forwarding is off, delete datagram //yes but datagrams from the ND module is getting dropped too!-WEI //so we add a 2nd condition // FIXME rewrite code so that condition is cleaner --Andras //if (!rt->isRouter()) if (!rt->isRouter() && !(datagram->getArrivalGate()->isName("ndIn"))) { EV << "forwarding is off, dropping packet\n"; numDropped++; delete datagram; return; } // don't forward link-local addresses or weaker if (destAddress.isLinkLocal() || destAddress.isLoopback()) { EV << "dest address is link-local (or weaker) scope, doesn't get forwarded\n"; delete datagram; return; } // hop counter decrement: only if datagram arrived from network, and will be // sent out to the network (hoplimit check will be done just before sending // out datagram) // TBD: in IPv4, arrange TTL check like this datagram->setHopLimit(datagram->getHopLimit()-1); } // routing // first try destination cache int interfaceId; IPv6Address nextHop = rt->lookupDestCache(destAddress, interfaceId); if (interfaceId==-1) { // address not in destination cache: do longest prefix match in routing table const IPv6Route *route = rt->doLongestPrefixMatch(destAddress); if (!route) { if (rt->isRouter()) { EV << "unroutable, sending ICMPv6_DESTINATION_UNREACHABLE\n"; numUnroutable++; icmp->sendErrorMessage(datagram, ICMPv6_DESTINATION_UNREACHABLE, 0); // FIXME check ICMP 'code' } else // host { EV << "no match in routing table, passing datagram to Neighbour Discovery module for default router selection\n"; send(datagram, "ndOut"); } return; } interfaceId = route->getInterfaceId(); nextHop = route->getNextHop(); if (nextHop.isUnspecified()) nextHop = destAddress; // next hop is the host itself // add result into destination cache rt->updateDestCache(destAddress, nextHop, interfaceId); } InterfaceEntry *ie = ift->getInterfaceById(interfaceId); ASSERT(ie!=NULL); EV << "next hop for " << destAddress << " is " << nextHop << ", interface " << ie->getName() << "\n"; ASSERT(!nextHop.isUnspecified()); MACAddress macAddr = nd->resolveNeighbour(nextHop, interfaceId); if (macAddr.isUnspecified()) { EV << "no link-layer address for next hop yet, passing datagram to Neighbour Discovery module\n"; send(datagram, "ndOut"); return; } EV << "link-layer address: " << macAddr << "\n"; // set datagram source address if not yet set if (datagram->getSrcAddress().isUnspecified()) { const IPv6Address& srcAddr = ie->ipv6Data()->getPreferredAddress(); ASSERT(!srcAddr.isUnspecified()); // FIXME what if we don't have an address yet? datagram->setSrcAddress(srcAddr); } // send out datagram numForwarded++; sendDatagramToOutput(datagram, ie, macAddr); }
void IPv6::sendDatagramToOutput | ( | IPv6Datagram * | datagram, | |
InterfaceEntry * | ie, | |||
const MACAddress & | macAddr | |||
) | [protected, virtual] |
Last hoplimit check, then send datagram on the given interface.
Definition at line 540 of file IPv6.cc.
Referenced by fragmentAndRoute(), routeMulticastPacket(), and routePacket().
{ // hop counter check if (datagram->getHopLimit() <= 0) { // drop datagram, destruction responsibility in ICMP EV << "datagram hopLimit reached zero, sending ICMPv6_TIME_EXCEEDED\n"; icmp->sendErrorMessage(datagram, ICMPv6_TIME_EXCEEDED, 0); // FIXME check icmp 'code' return; } // in link layer uses MAC addresses (basically, not PPP), add control info if (!macAddr.isUnspecified()) { Ieee802Ctrl *controlInfo = new Ieee802Ctrl(); controlInfo->setDest(macAddr); datagram->setControlInfo(controlInfo); } // send datagram to link layer send(datagram, "queueOut", ie->getNetworkLayerGateIndex()); }
void IPv6::updateDisplayString | ( | ) | [protected, virtual] |
Definition at line 61 of file IPv6.cc.
Referenced by endService().
{ char buf[80] = ""; if (numForwarded>0) sprintf(buf+strlen(buf), "fwd:%d ", numForwarded); if (numLocalDeliver>0) sprintf(buf+strlen(buf), "up:%d ", numLocalDeliver); if (numMulticast>0) sprintf(buf+strlen(buf), "mcast:%d ", numMulticast); if (numDropped>0) sprintf(buf+strlen(buf), "DROP:%d ", numDropped); if (numUnroutable>0) sprintf(buf+strlen(buf), "UNROUTABLE:%d ", numUnroutable); getDisplayString().setTagArg("t",0,buf); }
long IPv6::curFragmentId [protected] |
Definition at line 45 of file IPv6.h.
Referenced by initialize().
IPv6FragBuf IPv6::fragbuf [protected] |
Definition at line 46 of file IPv6.h.
Referenced by initialize().
ICMPv6* IPv6::icmp [protected] |
IInterfaceTable* IPv6::ift [protected] |
Definition at line 39 of file IPv6.h.
Referenced by encapsulate(), getSourceInterfaceFrom(), handleMessageFromHL(), initialize(), routeMulticastPacket(), and routePacket().
simtime_t IPv6::lastCheckTime [protected] |
Definition at line 47 of file IPv6.h.
Referenced by initialize().
ProtocolMapping IPv6::mapping [protected] |
Definition at line 48 of file IPv6.h.
Referenced by handleReceivedICMP(), initialize(), and isLocalAddress().
IPv6NeighbourDiscovery* IPv6::nd [protected] |
Definition at line 41 of file IPv6.h.
Referenced by initialize(), and routePacket().
int IPv6::numDropped [protected] |
Definition at line 53 of file IPv6.h.
Referenced by initialize(), routePacket(), and updateDisplayString().
int IPv6::numForwarded [protected] |
Definition at line 55 of file IPv6.h.
Referenced by initialize(), routePacket(), and updateDisplayString().
int IPv6::numLocalDeliver [protected] |
Definition at line 52 of file IPv6.h.
Referenced by initialize(), routeMulticastPacket(), routePacket(), and updateDisplayString().
int IPv6::numMulticast [protected] |
Definition at line 51 of file IPv6.h.
Referenced by initialize(), routeMulticastPacket(), and updateDisplayString().
int IPv6::numUnroutable [protected] |
Definition at line 54 of file IPv6.h.
Referenced by initialize(), routePacket(), and updateDisplayString().
RoutingTable6* IPv6::rt [protected] |
Definition at line 40 of file IPv6.h.
Referenced by encapsulate(), initialize(), routeMulticastPacket(), and routePacket().