#include <IP.h>
Public Member Functions | |
IP () | |
Protected Member Functions | |
virtual InterfaceEntry * | getSourceInterfaceFrom (cPacket *msg) |
virtual void | updateDisplayString () |
virtual IPDatagram * | encapsulate (cPacket *transportPacket, InterfaceEntry *&destIE) |
virtual IPDatagram * | encapsulate (cPacket *transportPacket, InterfaceEntry *&destIE, IPControlInfo *controlInfo) |
virtual IPDatagram * | createIPDatagram (const char *name) |
virtual void | handlePacketFromNetwork (IPDatagram *datagram) |
virtual void | handleMessageFromHL (cPacket *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 | reassembleAndDeliver (IPDatagram *datagram) |
virtual cPacket * | 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 (cPacket *msg) |
Protected Attributes | |
IRoutingTable * | rt |
IInterfaceTable * | ift |
ICMPAccess | icmpAccess |
cGate * | queueOutGate |
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 |
Implements the IP protocol.
Definition at line 42 of file IP.h.
IPDatagram * IP::createIPDatagram | ( | const char * | name | ) | [protected, virtual] |
Creates a blank IP datagram. Override when subclassing IPDatagram is needed
Definition at line 555 of file IP.cc.
Referenced by encapsulate().
{ return new IPDatagram(name); }
cPacket * IP::decapsulateIP | ( | IPDatagram * | datagram | ) | [protected, virtual] |
Decapsulate and return encapsulated packet after attaching IPControlInfo.
Definition at line 409 of file IP.cc.
Referenced by reassembleAndDeliver().
{ // decapsulate transport packet InterfaceEntry *fromIE = getSourceInterfaceFrom(datagram); cPacket *packet = datagram->decapsulate(); // create and fill in control info IPControlInfo *controlInfo = new IPControlInfo(); controlInfo->setProtocol(datagram->getTransportProtocol()); controlInfo->setSrcAddr(datagram->getSrcAddress()); controlInfo->setDestAddr(datagram->getDestAddress()); controlInfo->setDiffServCodePoint(datagram->getDiffServCodePoint()); 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; }
IPDatagram * IP::encapsulate | ( | cPacket * | transportPacket, | |
InterfaceEntry *& | destIE | |||
) | [protected, virtual] |
Encapsulate packet coming from higher layers into IPDatagram, using the control info attached to the packet.
Definition at line 495 of file IP.cc.
Referenced by handleMessageFromHL().
{ IPControlInfo *controlInfo = check_and_cast<IPControlInfo*>(transportPacket->removeControlInfo()); IPDatagram *datagram = encapsulate(transportPacket, destIE, controlInfo); delete controlInfo; return datagram; }
IPDatagram * IP::encapsulate | ( | cPacket * | transportPacket, | |
InterfaceEntry *& | destIE, | |||
IPControlInfo * | controlInfo | |||
) | [protected, virtual] |
Encapsulate packet coming from higher layers into IPDatagram, using the given control info. Override if you subclassed controlInfo and/or want to add options etc to the datagram.
Definition at line 503 of file IP.cc.
{ IPDatagram *datagram = createIPDatagram(transportPacket->getName()); datagram->setByteLength(IP_HEADER_BYTES); datagram->encapsulate(transportPacket); // set source and destination address IPAddress dest = controlInfo->getDestAddr(); datagram->setDestAddress(dest); // IP_MULTICAST_IF option, but allow interface selection for unicast packets as well destIE = ift->getInterfaceById(controlInfo->getInterfaceId()); IPAddress 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->setDiffServCodePoint(controlInfo->getDiffServCodePoint()); datagram->setIdentification(curFragmentId++); datagram->setMoreFragments(false); datagram->setDontFragment (controlInfo->getDontFragment()); datagram->setFragmentOffset(0); short ttl; if (controlInfo->getTimeToLive() > 0) ttl = controlInfo->getTimeToLive(); else if (datagram->getDestAddress().isLinkLocalMulticast()) ttl = 1; else if (datagram->getDestAddress().isMulticast()) ttl = defaultMCTimeToLive; else ttl = defaultTimeToLive; datagram->setTimeToLive(ttl); datagram->setTransportProtocol(controlInfo->getProtocol()); // setting IP options is currently not supported return datagram; }
void IP::endService | ( | cPacket * | msg | ) | [protected, virtual] |
Processing of IP datagrams. Called when a datagram reaches the front of the queue.
Implements AbstractQueue.
Definition at line 71 of file IP.cc.
{ if (msg->getArrivalGate()->isName("transportIn")) { handleMessageFromHL( msg ); } else if (dynamic_cast<ARPPacket *>(msg)) { // dispatch ARP packets to ARP handleARP((ARPPacket *)msg); } else { IPDatagram *dgram = check_and_cast<IPDatagram *>(msg); handlePacketFromNetwork(dgram); } if (ev.isGUI()) updateDisplayString(); }
void IP::fragmentAndSend | ( | IPDatagram * | datagram, | |
InterfaceEntry * | ie, | |||
IPAddress | nextHopAddr | |||
) | [protected, virtual] |
Fragment packet if needed, then send it to the selected interface using sendDatagramToOutput().
Definition at line 433 of file IP.cc.
Referenced by routeMulticastPacket(), and routePacket().
{ int mtu = ie->getMTU(); // check if datagram does not require fragmentation if (datagram->getByteLength() <= mtu) { sendDatagramToOutput(datagram, ie, nextHopAddr); return; } int headerLength = datagram->getHeaderLength(); int payload = datagram->getByteLength() - headerLength; int noOfFragments = int(ceil((float(payload)/mtu) / (1-float(headerLength)/mtu) ) ); // FIXME ??? // if "don't fragment" bit is set, throw datagram away and send ICMP error message if (datagram->getDontFragment() && noOfFragments>1) { EV << "datagram larger than MTU and don't fragment bit set, sending ICMP_DESTINATION_UNREACHABLE\n"; icmpAccess.get()->sendErrorMessage(datagram, ICMP_DESTINATION_UNREACHABLE, ICMP_FRAGMENTATION_ERROR_CODE); return; } // create and send fragments EV << "Breaking datagram into " << noOfFragments << " fragments\n"; std::string fragMsgName = datagram->getName(); fragMsgName += "-frag"; // FIXME revise this! for (int i=0; i<noOfFragments; i++) { // FIXME is it ok that full encapsulated packet travels in every datagram fragment? // should better travel in the last fragment only. Cf. with reassembly code! IPDatagram *fragment = (IPDatagram *) datagram->dup(); fragment->setName(fragMsgName.c_str()); // total_length equal to mtu, except for last fragment; // "more fragments" bit is unchanged in the last fragment, otherwise true if (i != noOfFragments-1) { fragment->setMoreFragments(true); fragment->setByteLength(mtu); } else { // size of last fragment int bytes = datagram->getByteLength() - (noOfFragments-1) * (mtu - datagram->getHeaderLength()); fragment->setByteLength(bytes); } fragment->setFragmentOffset( i*(mtu - datagram->getHeaderLength()) ); sendDatagramToOutput(fragment, ie, nextHopAddr); } delete datagram; }
InterfaceEntry * IP::getSourceInterfaceFrom | ( | cPacket * | msg | ) | [protected, virtual] |
Definition at line 92 of file IP.cc.
Referenced by decapsulateIP(), handleARP(), and handlePacketFromNetwork().
{ cGate *g = msg->getArrivalGate(); return g ? ift->getInterfaceByNetworkLayerGateIndex(g->getIndex()) : NULL; }
void IP::handleARP | ( | ARPPacket * | msg | ) | [protected, virtual] |
Handle incoming ARP packets by sending them over "queueOut" to ARP.
Definition at line 131 of file IP.cc.
Referenced by endService().
{ // FIXME hasBitError() check missing! // delete old control info delete msg->removeControlInfo(); // dispatch ARP packets to ARP and let it know the gate index it arrived on InterfaceEntry *fromIE = getSourceInterfaceFrom(msg); ASSERT(fromIE); IPRoutingDecision *routingDecision = new IPRoutingDecision(); routingDecision->setInterfaceId(fromIE->getInterfaceId()); msg->setControlInfo(routingDecision); send(msg, queueOutGate); }
void IP::handleMessageFromHL | ( | cPacket * | msg | ) | [protected, virtual] |
Handle messages (typically packets to be send in IP) from transport or ICMP. Invokes encapsulate(), then routePacket().
Definition at line 173 of file IP.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 and send InterfaceEntry *destIE; // will be filled in by encapsulate() IPDatagram *datagram = encapsulate(msg, destIE); // route packet if (!datagram->getDestAddress().isMulticast()) routePacket(datagram, destIE, true); else routeMulticastPacket(datagram, destIE, NULL); }
void IP::handlePacketFromNetwork | ( | IPDatagram * | datagram | ) | [protected, virtual] |
Handle IPDatagram messages arriving from lower layer. Decrements TTL, then invokes routePacket().
Definition at line 98 of file IP.cc.
Referenced by endService().
{ // // "Prerouting" // // check for header biterror if (datagram->hasBitError()) { // 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"; icmpAccess.get()->sendErrorMessage(datagram, ICMP_PARAMETER_PROBLEM, 0); return; } } // remove control info delete datagram->removeControlInfo(); // hop counter decrement; FIXME but not if it will be locally delivered datagram->setTimeToLive(datagram->getTimeToLive()-1); // route packet if (!datagram->getDestAddress().isMulticast()) routePacket(datagram, NULL, false); else routeMulticastPacket(datagram, NULL, getSourceInterfaceFrom(datagram)); }
void IP::handleReceivedICMP | ( | ICMPMessage * | msg | ) | [protected, virtual] |
Handle incoming ICMP messages.
Definition at line 149 of file IP.cc.
Referenced by reassembleAndDeliver().
{ switch (msg->getType()) { case ICMP_REDIRECT: // TODO implement redirect handling case ICMP_DESTINATION_UNREACHABLE: case ICMP_TIME_EXCEEDED: case ICMP_PARAMETER_PROBLEM: { // ICMP errors are delivered to the appropriate higher layer protocol IPDatagram *bogusPacket = check_and_cast<IPDatagram *>(msg->getEncapsulatedMsg()); int protocol = bogusPacket->getTransportProtocol(); int gateindex = mapping.getOutputGateForProtocol(protocol); send(msg, "transportOut", gateindex); break; } default: { // all others are delivered to ICMP: ICMP_ECHO_REQUEST, ICMP_ECHO_REPLY, // ICMP_TIMESTAMP_REQUEST, ICMP_TIMESTAMP_REPLY, etc. int gateindex = mapping.getOutputGateForProtocol(IP_PROT_ICMP); send(msg, "transportOut", gateindex); } } }
void IP::initialize | ( | ) | [protected, virtual] |
Initialization
Reimplemented from QueueBase.
Definition at line 33 of file IP.cc.
{ QueueBase::initialize(); ift = InterfaceTableAccess().get(); rt = RoutingTableAccess().get(); queueOutGate = gate("queueOut"); defaultTimeToLive = par("timeToLive"); defaultMCTimeToLive = par("multicastTimeToLive"); fragmentTimeoutTime = par("fragmentTimeout"); mapping.parseProtocolMapping(par("protocolMapping")); curFragmentId = 0; lastCheckTime = 0; fragbuf.init(icmpAccess.get()); numMulticast = numLocalDeliver = numDropped = numUnroutable = numForwarded = 0; WATCH(numMulticast); WATCH(numLocalDeliver); WATCH(numDropped); WATCH(numUnroutable); WATCH(numForwarded); }
void IP::reassembleAndDeliver | ( | IPDatagram * | datagram | ) | [protected, virtual] |
Perform reassembly of fragmented datagrams, then send them up to the higher layers using sendToHL().
Definition at line 364 of file IP.cc.
Referenced by routeMulticastPacket(), and routePacket().
{ // reassemble the packet (if 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()-fragmentTimeoutTime); } 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 = decapsulateIP(datagram); if (protocol==IP_PROT_ICMP) { // incoming ICMP packets are handled specially handleReceivedICMP(check_and_cast<ICMPMessage *>(packet)); } else if (protocol==IP_PROT_IP) { // tunnelled IP packets are handled separately send(packet, "preRoutingOut"); } else { int gateindex = mapping.getOutputGateForProtocol(protocol); send(packet, "transportOut", gateindex); } }
void IP::routeMulticastPacket | ( | IPDatagram * | datagram, | |
InterfaceEntry * | destIE, | |||
InterfaceEntry * | fromIE | |||
) | [protected, virtual] |
Forwards packets to all multicast destinations, using fragmentAndSend().
Definition at line 264 of file IP.cc.
Referenced by handleMessageFromHL(), and handlePacketFromNetwork().
{ IPAddress destAddr = datagram->getDestAddress(); EV << "Routing multicast datagram `" << datagram->getName() << "' with dest=" << destAddr << "\n"; numMulticast++; // DVMRP: process datagram only if sent locally or arrived on the shortest // route (provided routing table already contains srcAddr); otherwise // discard and continue. InterfaceEntry *shortestPathIE = rt->getInterfaceForDestAddr(datagram->getSrcAddress()); if (fromIE!=NULL && shortestPathIE!=NULL && fromIE!=shortestPathIE) { // FIXME count dropped EV << "Packet dropped.\n"; delete datagram; return; } // if received from the network... if (fromIE!=NULL) { // check for local delivery if (rt->isLocalMulticastAddress(destAddr)) { IPDatagram *datagramCopy = (IPDatagram *) datagram->dup(); // FIXME code from the MPLS model: set packet dest address to routerId (???) datagramCopy->setDestAddress(rt->getRouterId()); reassembleAndDeliver(datagramCopy); } // don't forward if IP forwarding is off if (!rt->isIPForwardingEnabled()) { delete datagram; return; } // don't forward if dest address is link-scope if (destAddr.isLinkLocalMulticast()) { delete datagram; return; } } // routed explicitly via IP_MULTICAST_IF if (destIE!=NULL) { ASSERT(datagram->getDestAddress().isMulticast()); EV << "multicast packet explicitly routed via output interface " << destIE->getName() << endl; // set datagram source address if not yet set if (datagram->getSrcAddress().isUnspecified()) datagram->setSrcAddress(destIE->ipv4Data()->getIPAddress()); // send fragmentAndSend(datagram, destIE, datagram->getDestAddress()); return; } // now: routing MulticastRoutes routes = rt->getMulticastRoutesFor(destAddr); 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++) { InterfaceEntry *destIE = routes[i].interf; // don't forward to input port if (destIE && destIE!=fromIE) { IPDatagram *datagramCopy = (IPDatagram *) datagram->dup(); // set datagram source address if not yet set if (datagramCopy->getSrcAddress().isUnspecified()) datagramCopy->setSrcAddress(destIE->ipv4Data()->getIPAddress()); // send IPAddress nextHopAddr = routes[i].gateway; fragmentAndSend(datagramCopy, destIE, nextHopAddr); } } // only copies sent, delete original datagram delete datagram; } }
void IP::routePacket | ( | IPDatagram * | datagram, | |
InterfaceEntry * | destIE, | |||
bool | fromHL | |||
) | [protected, virtual] |
Performs routing. Based on the routing decision, it dispatches to reassembleAndDeliver() 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.
Definition at line 194 of file IP.cc.
Referenced by handleMessageFromHL(), and handlePacketFromNetwork().
{ // TBD add option handling code here IPAddress destAddr = datagram->getDestAddress(); EV << "Routing datagram `" << datagram->getName() << "' with dest=" << destAddr << ": "; // check for local delivery if (rt->isLocalAddress(destAddr)) { EV << "local delivery\n"; if (datagram->getSrcAddress().isUnspecified()) datagram->setSrcAddress(destAddr); // allows two apps on the same host to communicate numLocalDeliver++; reassembleAndDeliver(datagram); return; } // if datagram arrived from input gate and IP_FORWARD is off, delete datagram if (!fromHL && !rt->isIPForwardingEnabled()) { EV << "forwarding off, dropping packet\n"; numDropped++; delete datagram; return; } IPAddress nextHopAddr; // if output port was explicitly requested, use that, otherwise use IP routing if (destIE) { EV << "using manually specified output interface " << destIE->getName() << "\n"; // and nextHopAddr remains unspecified } else { // use IP routing (lookup in routing table) const IPRoute *re = rt->findBestMatchingRoute(destAddr); // error handling: destination address does not exist in routing table: // notify ICMP, throw packet away and continue if (re==NULL) { EV << "unroutable, sending ICMP_DESTINATION_UNREACHABLE\n"; numUnroutable++; icmpAccess.get()->sendErrorMessage(datagram, ICMP_DESTINATION_UNREACHABLE, 0); return; } // extract interface and next-hop address from routing table entry destIE = re->getInterface(); nextHopAddr = re->getGateway(); } // set datagram source address if not yet set if (datagram->getSrcAddress().isUnspecified()) datagram->setSrcAddress(destIE->ipv4Data()->getIPAddress()); // default: send datagram to fragmentation EV << "output interface is " << destIE->getName() << ", next-hop address: " << nextHopAddr << "\n"; numForwarded++; // // fragment and send the packet // fragmentAndSend(datagram, destIE, nextHopAddr); }
void IP::sendDatagramToOutput | ( | IPDatagram * | datagram, | |
InterfaceEntry * | ie, | |||
IPAddress | nextHopAddr | |||
) | [protected, virtual] |
Last TTL check, then send datagram on the given interface.
Definition at line 560 of file IP.cc.
Referenced by fragmentAndSend().
{ // hop counter check if (datagram->getTimeToLive() <= 0) { // drop datagram, destruction responsibility in ICMP EV << "datagram TTL reached zero, sending ICMP_TIME_EXCEEDED\n"; icmpAccess.get()->sendErrorMessage(datagram, ICMP_TIME_EXCEEDED, 0); return; } // send out datagram to ARP, with control info attached IPRoutingDecision *routingDecision = new IPRoutingDecision(); routingDecision->setInterfaceId(ie->getInterfaceId()); routingDecision->setNextHopAddr(nextHopAddr); datagram->setControlInfo(routingDecision); send(datagram, queueOutGate); }
void IP::updateDisplayString | ( | ) | [protected, virtual] |
Definition at line 60 of file IP.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 IP::curFragmentId [protected] |
Definition at line 56 of file IP.h.
Referenced by encapsulate(), and initialize().
int IP::defaultMCTimeToLive [protected] |
Definition at line 52 of file IP.h.
Referenced by encapsulate(), and initialize().
int IP::defaultTimeToLive [protected] |
Definition at line 51 of file IP.h.
Referenced by encapsulate(), and initialize().
IPFragBuf IP::fragbuf [protected] |
Definition at line 57 of file IP.h.
Referenced by initialize(), and reassembleAndDeliver().
simtime_t IP::fragmentTimeoutTime [protected] |
Definition at line 53 of file IP.h.
Referenced by initialize(), and reassembleAndDeliver().
ICMPAccess IP::icmpAccess [protected] |
Definition at line 47 of file IP.h.
Referenced by fragmentAndSend(), handlePacketFromNetwork(), initialize(), routePacket(), and sendDatagramToOutput().
IInterfaceTable* IP::ift [protected] |
Definition at line 46 of file IP.h.
Referenced by encapsulate(), getSourceInterfaceFrom(), handleMessageFromHL(), and initialize().
simtime_t IP::lastCheckTime [protected] |
Definition at line 58 of file IP.h.
Referenced by initialize(), and reassembleAndDeliver().
ProtocolMapping IP::mapping [protected] |
Definition at line 59 of file IP.h.
Referenced by handleReceivedICMP(), initialize(), and reassembleAndDeliver().
int IP::numDropped [protected] |
Definition at line 64 of file IP.h.
Referenced by initialize(), routePacket(), and updateDisplayString().
int IP::numForwarded [protected] |
Definition at line 66 of file IP.h.
Referenced by initialize(), routePacket(), and updateDisplayString().
int IP::numLocalDeliver [protected] |
Definition at line 63 of file IP.h.
Referenced by initialize(), routePacket(), and updateDisplayString().
int IP::numMulticast [protected] |
Definition at line 62 of file IP.h.
Referenced by initialize(), routeMulticastPacket(), and updateDisplayString().
int IP::numUnroutable [protected] |
Definition at line 65 of file IP.h.
Referenced by initialize(), routePacket(), and updateDisplayString().
cGate* IP::queueOutGate [protected] |
Definition at line 48 of file IP.h.
Referenced by handleARP(), initialize(), and sendDatagramToOutput().
IRoutingTable* IP::rt [protected] |
Definition at line 45 of file IP.h.
Referenced by encapsulate(), initialize(), routeMulticastPacket(), and routePacket().