MPLS.cc

Go to the documentation of this file.
00001 //
00002 // (C) 2005 Vojtech Janota
00003 // (C) 2003 Xuan Thang Nguyen
00004 //
00005 // This library is free software, you can redistribute it
00006 // and/or modify
00007 // it under  the terms of the GNU Lesser General Public License
00008 // as published by the Free Software Foundation;
00009 // either version 2 of the License, or any later version.
00010 // The library is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00013 // See the GNU Lesser General Public License for more details.
00014 //
00015 
00016 #include <omnetpp.h>
00017 #include <string.h>
00018 
00019 #include "MPLS.h"
00020 #include "Utils.h"
00021 
00022 #include "InterfaceTableAccess.h"
00023 #include "RoutingTableAccess.h"
00024 #include "LIBTableAccess.h"
00025 #include "IClassifier.h"
00026 
00027 
00028 // FIXME temporary fix
00029 #include "LDP.h"
00030 #include "TCPSegment.h"
00031 #define ICMP_TRAFFIC    6
00032 
00033 
00034 Define_Module(MPLS);
00035 
00036 void MPLS::initialize(int stage)
00037 {
00038     if (stage!=3) // interfaceTable must be initialized
00039         return;
00040 
00041     lt = LIBTableAccess().get();
00042     ift = InterfaceTableAccess().get();
00043 
00044     pct = check_and_cast<IClassifier*>(getParentModule()->getSubmodule(par("classifier")));
00045 
00046     /*
00047      * we now send plain IPDatagrams instead of packets with label=-1
00048      * and we thus do not need this extra configuration
00049      *
00050     labelIf.resize(ift->getNumInterfaces());
00051     cStringTokenizer tokenizer(par("peers"));
00052     const char *token;
00053     while ((token = tokenizer.nextToken())!=NULL)
00054     {
00055         ASSERT(ift->getInterfaceByName(token));
00056         int n = ift->getInterfaceByName(token)->outputPort();
00057         ASSERT(n >= 0 && n < labelIf.size());
00058         labelIf[n] = true;
00059     }
00060     */
00061 }
00062 
00063 void MPLS::handleMessage(cMessage * msg)
00064 {
00065     if (!strcmp(msg->getArrivalGate()->getName(), "ifIn"))
00066     {
00067         EV << "Processing message from L2: " << msg << endl;
00068         processPacketFromL2(msg);
00069     }
00070     else if (!strcmp(msg->getArrivalGate()->getName(), "netwIn"))
00071     {
00072         EV << "Processing message from L3: " << msg << endl;
00073         processPacketFromL3(msg);
00074     }
00075     else
00076     {
00077         error("unexpected message: %s", msg->getName());
00078     }
00079 }
00080 
00081 void MPLS::sendToL2(cMessage *msg, int gateIndex)
00082 {
00083     send(msg, "ifOut", gateIndex);
00084 }
00085 
00086 void MPLS::processPacketFromL3(cMessage * msg)
00087 {
00088     IPDatagram *ipdatagram = check_and_cast<IPDatagram *>(msg);
00089     //int gateIndex = msg->getArrivalGate()->getIndex();
00090 
00091     // XXX temporary solution, until TCPSocket and IP are extended to support nam tracing
00092     if (ipdatagram->getTransportProtocol() == IP_PROT_TCP)
00093     {
00094         TCPSegment *seg = check_and_cast<TCPSegment*>(ipdatagram->getEncapsulatedMsg());
00095         if (seg->getDestPort() == LDP_PORT || seg->getSrcPort() == LDP_PORT)
00096         {
00097             ASSERT(!ipdatagram->hasPar("color"));
00098             ipdatagram->addPar("color") = LDP_TRAFFIC;
00099         }
00100     }
00101     else if (ipdatagram->getTransportProtocol() == IP_PROT_ICMP)
00102     {
00103         // ASSERT(!ipdatagram->hasPar("color")); XXX this did not hold sometimes...
00104         if (!ipdatagram->hasPar("color"))
00105             ipdatagram->addPar("color") = ICMP_TRAFFIC;
00106     }
00107     // XXX end of temporary area
00108 
00109     labelAndForwardIPDatagram(ipdatagram);
00110 }
00111 
00112 bool MPLS::tryLabelAndForwardIPDatagram(IPDatagram *ipdatagram)
00113 {
00114     LabelOpVector outLabel;
00115     std::string outInterface;
00116     int color;
00117 
00118     if (!pct->lookupLabel(ipdatagram, outLabel, outInterface, color))
00119     {
00120         EV << "no mapping exists for this packet" << endl;
00121         return false;
00122     }
00123 
00124     ASSERT(outLabel.size() > 0);
00125 
00126     int outgoingPort = ift->getInterfaceByName(outInterface.c_str())->getNetworkLayerGateIndex();
00127 
00128     MPLSPacket *mplsPacket = new MPLSPacket(ipdatagram->getName());
00129     mplsPacket->encapsulate(ipdatagram);
00130     doStackOps(mplsPacket, outLabel);
00131 
00132     EV << "forwarding packet to " << outInterface << endl;
00133 
00134     mplsPacket->addPar("color") = color;
00135 
00136     if (!mplsPacket->hasLabel())
00137     {
00138         // yes, this may happen - if we'are both ingress and egress
00139         ipdatagram = check_and_cast<IPDatagram*>(mplsPacket->decapsulate()); // XXX FIXME superfluous encaps/decaps
00140         delete mplsPacket;
00141         sendToL2(ipdatagram, outgoingPort);
00142     }
00143     else
00144         sendToL2(mplsPacket, outgoingPort);
00145 
00146     return true;
00147 }
00148 
00149 void MPLS::labelAndForwardIPDatagram(IPDatagram *ipdatagram)
00150 {
00151     if (tryLabelAndForwardIPDatagram(ipdatagram))
00152         return;
00153 
00154     // handling our outgoing IP traffic that didn't match any FEC/LSP
00155     // do not use labelAndForwardIPDatagram for packets arriving to ingress!
00156 
00157     EV << "FEC not resolved, doing regular L3 routing" << endl;
00158 
00159     int gateIndex = ipdatagram->getArrivalGate()->getIndex();
00160 
00161     sendToL2(ipdatagram, gateIndex);
00162 }
00163 
00164 void MPLS::doStackOps(MPLSPacket *mplsPacket, const LabelOpVector& outLabel)
00165 {
00166     unsigned int n = outLabel.size();
00167 
00168     EV << "doStackOps: " << outLabel << endl;
00169 
00170     ASSERT(n >= 0);
00171 
00172     for (unsigned int i = 0; i <  n; i++)
00173     {
00174         switch (outLabel[i].optcode)
00175         {
00176             case PUSH_OPER:
00177                 mplsPacket->pushLabel(outLabel[i].label);
00178                 break;
00179 
00180             case SWAP_OPER:
00181                 ASSERT(mplsPacket->hasLabel());
00182                 mplsPacket->swapLabel(outLabel[i].label);
00183                 break;
00184 
00185             case POP_OPER:
00186                 ASSERT(mplsPacket->hasLabel());
00187                 mplsPacket->popLabel();
00188                 break;
00189 
00190             default:
00191                 error("Unknown MPLS OptCode %d", outLabel[i].optcode);
00192         }
00193     }
00194 }
00195 
00196 void MPLS::processPacketFromL2(cMessage *msg)
00197 {
00198     IPDatagram *ipdatagram = dynamic_cast<IPDatagram *>(msg);
00199     MPLSPacket *mplsPacket = dynamic_cast<MPLSPacket *>(msg);
00200 
00201     if (mplsPacket)
00202     {
00203         processMPLSPacketFromL2(mplsPacket);
00204     }
00205     else if (ipdatagram)
00206     {
00207         // IP datagram arrives at Ingress router. We'll try to classify it
00208         // and add an MPLS header
00209 
00210         if (!tryLabelAndForwardIPDatagram(ipdatagram))
00211         {
00212             int gateIndex = ipdatagram->getArrivalGate()->getIndex();
00213             send(ipdatagram, "netwOut", gateIndex);
00214         }
00215     }
00216     else
00217     {
00218         error("Unknown message received");
00219     }
00220 }
00221 
00222 void MPLS::processMPLSPacketFromL2(MPLSPacket *mplsPacket)
00223 {
00224     int gateIndex = mplsPacket->getArrivalGate()->getIndex();
00225     InterfaceEntry *ie = ift->getInterfaceByNetworkLayerGateIndex(gateIndex);
00226     std::string senderInterface = ie->getName();
00227     ASSERT(mplsPacket->hasLabel());
00228     int oldLabel = mplsPacket->getTopLabel();
00229 
00230     EV << "Received " << mplsPacket << " from L2, label=" << oldLabel << " inInterface=" << senderInterface << endl;
00231 
00232     if (oldLabel==-1)
00233     {
00234         // This is a IP native packet (RSVP/TED traffic)
00235         // Decapsulate the message and pass up to L3
00236         EV << ": decapsulating and sending up\n";
00237 
00238         IPDatagram *ipdatagram = check_and_cast<IPDatagram *>(mplsPacket->decapsulate());
00239         delete mplsPacket;
00240         send(ipdatagram, "netwOut", gateIndex);
00241         return;
00242     }
00243 
00244     LabelOpVector outLabel;
00245     std::string outInterface;
00246     int color;
00247 
00248     bool found = lt->resolveLabel(senderInterface, oldLabel, outLabel, outInterface, color);
00249     if (!found)
00250     {
00251         EV << "discarding packet, incoming label not resolved" << endl;
00252 
00253         delete mplsPacket;
00254         return;
00255     }
00256 
00257     int outgoingPort = ift->getInterfaceByName(outInterface.c_str())->getNetworkLayerGateIndex();
00258 
00259     doStackOps(mplsPacket, outLabel);
00260 
00261     if (mplsPacket->hasLabel())
00262     {
00263         // forward labeled packet
00264 
00265         EV << "forwarding packet to " << outInterface << endl;
00266 
00267         if (mplsPacket->hasPar("color"))
00268         {
00269             mplsPacket->par("color") = color;
00270         }
00271         else
00272         {
00273             mplsPacket->addPar("color") = color;
00274         }
00275 
00276         //ASSERT(labelIf[outgoingPort]);
00277 
00278         sendToL2(mplsPacket, outgoingPort);
00279     }
00280     else
00281     {
00282         // last label popped, decapsulate and send out IP datagram
00283 
00284         EV << "decapsulating IP datagram" << endl;
00285 
00286         IPDatagram *nativeIP = check_and_cast<IPDatagram *>(mplsPacket->decapsulate());
00287         delete mplsPacket;
00288 
00289         if (outgoingPort != -1)
00290         {
00291             sendToL2(nativeIP, outgoingPort);
00292         }
00293         else
00294         {
00295             send(nativeIP, "netwOut", gateIndex);
00296         }
00297     }
00298 }