|
INET Framework for OMNeT++/OMNEST
|
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->getEncapsulatedPacket()); 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 }