|
INET Framework for OMNeT++/OMNEST
|
00001 // 00002 // Copyright (C) 2005-2010 Irene Ruengeler 00003 // Copyright (C) 2009-2010 Thomas Dreibholz 00004 // 00005 // This program is free software; you can redistribute it and/or 00006 // modify it under the terms of the GNU General Public License 00007 // as published by the Free Software Foundation; either version 2 00008 // of the License, or (at your option) any later version. 00009 // 00010 // This program 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. See the 00013 // GNU General Public License for more details. 00014 // 00015 // You should have received a copy of the GNU General Public License 00016 // along with this program; if not, see <http://www.gnu.org/licenses/>. 00017 // 00018 00019 00020 #include "SCTP.h" 00021 #include "SCTPAssociation.h" 00022 #include "SCTPCommand_m.h" 00023 #include "IPControlInfo.h" 00024 #include "IPv6ControlInfo.h" 00025 #include "IPDatagram.h" 00026 00027 00028 Define_Module(SCTP); 00029 00030 00031 bool SCTP::testing; 00032 bool SCTP::logverbose; 00033 00034 int32 SCTP::nextConnId = 0; 00035 00036 00037 void SCTP::printInfoConnMap() 00038 { 00039 SCTPAssociation* assoc; 00040 SockPair key; 00041 sctpEV3<<"Number of Assocs: "<<sizeConnMap<<"\n"; 00042 if (sizeConnMap>0) 00043 { 00044 for (SctpConnMap::iterator i = sctpConnMap.begin(); i!=sctpConnMap.end(); ++i) 00045 { 00046 assoc = i->second; 00047 key = i->first; 00048 00049 sctpEV3<<"assocId: "<<assoc->assocId<<" assoc: "<<assoc<<" src: "<<IPvXAddress(key.localAddr)<<" dst: "<<IPvXAddress(key.remoteAddr)<<" lPort: "<<key.localPort<<" rPort: "<<key.remotePort<<"\n"; 00050 00051 } 00052 00053 sctpEV3<<"\n"; 00054 } 00055 00056 } 00057 00058 void SCTP::printVTagMap() 00059 { 00060 int32 assocId; 00061 VTagPair key; 00062 sctpEV3<<"Number of Assocs: "<<sctpVTagMap.size()<<"\n"; 00063 if (sctpVTagMap.size()>0) 00064 { 00065 for (SctpVTagMap::iterator i = sctpVTagMap.begin(); i!=sctpVTagMap.end(); ++i) 00066 { 00067 assocId = i->first; 00068 key = i->second; 00069 00070 sctpEV3<<"assocId: "<<assocId<<" peerVTag: "<<key.peerVTag<< 00071 " localVTag: "<<key.localVTag<< 00072 " localPort: "<<key.localPort<<" rPort: "<<key.remotePort<<"\n"; 00073 } 00074 00075 sctpEV3<<"\n"; 00076 } 00077 } 00078 00079 void SCTP::bindPortForUDP() 00080 { 00081 EV << "Binding to UDP port " << 9899 << endl; 00082 00083 cMessage *msg = new cMessage("UDP_C_BIND", UDP_C_BIND); 00084 UDPControlInfo *ctrl = new UDPControlInfo(); 00085 ctrl->setSrcPort(9899); 00086 ctrl->setSockId(UDPSocket::generateSocketId()); 00087 msg->setControlInfo(ctrl); 00088 send(msg, "to_ip"); 00089 } 00090 00091 void SCTP::initialize() 00092 { 00093 nextEphemeralPort = (uint16)(intrand(10000) + 30000); 00094 00095 //sctpEV3<<"SCTPMain initialize\n"; 00096 00097 cModule *netw = simulation.getSystemModule(); 00098 00099 testing = netw->hasPar("testing") && netw->par("testing").boolValue(); 00100 if(testing) { 00101 } 00102 if (netw->hasPar("testTimeout")) 00103 { 00104 testTimeout = (simtime_t)netw->par("testTimeout"); 00105 } 00106 numPacketsReceived = 0; 00107 numPacketsDropped = 0; 00108 sizeConnMap = 0; 00109 if ((bool)par("udpEncapsEnabled")) 00110 bindPortForUDP(); 00111 } 00112 00113 00114 SCTP::~SCTP() 00115 { 00116 sctpEV3<<"delete SCTPMain\n"; 00117 if (!(sctpAppConnMap.empty())) 00118 { 00119 sctpEV3<<"clear appConnMap ptr="<<&sctpAppConnMap<<"\n"; 00120 sctpAppConnMap.clear(); 00121 } 00122 if (!(assocStatMap.empty())) 00123 { 00124 sctpEV3<<"clear assocStatMap ptr="<<&assocStatMap<<"\n"; 00125 assocStatMap.clear(); 00126 } 00127 if (!(sctpVTagMap.empty())) 00128 { 00129 sctpVTagMap.clear(); 00130 } 00131 sctpEV3<<"after clearing maps\n"; 00132 } 00133 00134 00135 void SCTP::handleMessage(cMessage *msg) 00136 { 00137 IPvXAddress destAddr; 00138 IPvXAddress srcAddr; 00139 IPControlInfo *controlInfo =NULL; 00140 IPv6ControlInfo *controlInfoV6 =NULL; 00141 bool findListen = false; 00142 bool bitError = false; 00143 00144 sctpEV3<<"\n\nSCTPMain handleMessage at "<<getFullPath()<<"\n"; 00145 00146 if (msg->isSelfMessage()) 00147 { 00148 00149 sctpEV3<<"selfMessage\n"; 00150 00151 SCTPAssociation *assoc = (SCTPAssociation *) msg->getContextPointer(); 00152 bool ret = assoc->processTimer(msg); 00153 00154 if (!ret) 00155 removeAssociation(assoc); 00156 } 00157 else if (msg->arrivedOn("from_ip") || msg->arrivedOn("from_ipv6")) 00158 { 00159 sctpEV3<<"Message from IP\n"; 00160 printInfoConnMap(); 00161 if (!dynamic_cast<SCTPMessage *>(msg)) 00162 { 00163 sctpEV3<<"no sctp message, delete it\n"; 00164 delete msg; 00165 return; 00166 } 00167 SCTPMessage *sctpmsg = check_and_cast<SCTPMessage *>(msg); 00168 00169 numPacketsReceived++; 00170 00171 if ((sctpmsg->hasBitError() || !(sctpmsg->getChecksumOk()))) { 00172 sctpEV3<<"Packet has bit-error. delete it\n"; 00173 00174 bitError = true; 00175 numPacketsDropped++; 00176 delete msg; 00177 return; 00178 } 00179 if (msg->arrivedOn("from_ip")) 00180 { 00181 if (par("udpEncapsEnabled")) 00182 { 00183 std::cout<<"Laenge SCTPMSG="<<sctpmsg->getByteLength()<<"\n"; 00184 UDPControlInfo *ctrl = check_and_cast<UDPControlInfo *>(msg->removeControlInfo()); 00185 srcAddr = ctrl->getSrcAddr(); 00186 destAddr = ctrl->getDestAddr(); 00187 std::cout<<"controlInfo srcAddr="<<srcAddr<<" destAddr="<<destAddr<<"\n"; 00188 std::cout<<"VTag="<<sctpmsg->getTag()<<"\n"; 00189 } 00190 else 00191 { 00192 controlInfo = check_and_cast<IPControlInfo *>(msg->removeControlInfo()); 00193 IPDatagram *datagram = controlInfo->removeOrigDatagram(); 00194 delete datagram; 00195 sctpEV3<<"controlInfo srcAddr="<<controlInfo->getSrcAddr()<<" destAddr="<<controlInfo->getDestAddr()<<"\n"; 00196 srcAddr = controlInfo->getSrcAddr(); 00197 destAddr = controlInfo->getDestAddr(); 00198 } 00199 } 00200 else 00201 { 00202 controlInfoV6 = check_and_cast<IPv6ControlInfo *>(msg->removeControlInfo()); 00203 srcAddr = controlInfoV6->getSrcAddr(); 00204 destAddr = controlInfoV6->getDestAddr(); 00205 } 00206 00207 00208 sctpEV3<<"srcAddr="<<srcAddr<<" destAddr="<<destAddr<<"\n"; 00209 if (sctpmsg->getBitLength()>(SCTP_COMMON_HEADER*8)) 00210 { 00211 if (((SCTPChunk*)(sctpmsg->getChunks(0)))->getChunkType()==INIT || ((SCTPChunk*)(sctpmsg->getChunks(0)))->getChunkType()==INIT_ACK ) 00212 findListen = true; 00213 00214 SCTPAssociation *assoc = findAssocForMessage(srcAddr, destAddr, sctpmsg->getSrcPort(),sctpmsg->getDestPort(), findListen); 00215 if (!assoc && sctpConnMap.size()>0) 00216 assoc = findAssocWithVTag(sctpmsg->getTag(),sctpmsg->getSrcPort(), sctpmsg->getDestPort()); 00217 if (!assoc) 00218 { 00219 sctpEV3<<"no assoc found msg="<<sctpmsg->getName()<<"\n"; 00220 if (bitError) 00221 { 00222 delete sctpmsg; 00223 return; 00224 } 00225 if (((SCTPChunk*)(sctpmsg->getChunks(0)))->getChunkType()==SHUTDOWN_ACK) 00226 sendShutdownCompleteFromMain(sctpmsg, destAddr, srcAddr); 00227 else if (((SCTPChunk*)(sctpmsg->getChunks(0)))->getChunkType()!=ABORT && 00228 ((SCTPChunk*)(sctpmsg->getChunks(0)))->getChunkType()!=SHUTDOWN_COMPLETE) 00229 { 00230 sendAbortFromMain(sctpmsg, destAddr, srcAddr); 00231 } 00232 delete sctpmsg; 00233 } 00234 else 00235 { 00236 bool ret = assoc->processSCTPMessage(sctpmsg, srcAddr, destAddr); 00237 if (!ret) 00238 { 00239 sctpEV3<<"SCTPMain:: removeAssociation \n"; 00240 removeAssociation(assoc); 00241 delete sctpmsg; 00242 } 00243 else 00244 { 00245 delete sctpmsg; 00246 } 00247 } 00248 } 00249 else 00250 { 00251 delete sctpmsg; 00252 } 00253 } 00254 else // must be from app 00255 { 00256 sctpEV3<<"must be from app\n"; 00257 SCTPCommand *controlInfo = check_and_cast<SCTPCommand *>(msg->getControlInfo()); 00258 00259 int32 appGateIndex; 00260 if (controlInfo->getGate()!=-1) 00261 appGateIndex = controlInfo->getGate(); 00262 else 00263 appGateIndex = msg->getArrivalGate()->getIndex(); 00264 int32 assocId = controlInfo->getAssocId(); 00265 sctpEV3<<"msg arrived from app for assoc "<<assocId<<"\n"; 00266 SCTPAssociation *assoc = findAssocForApp(appGateIndex, assocId); 00267 00268 if (!assoc) 00269 { 00270 sctpEV3 << "no assoc found. msg="<<msg->getName()<<" number of assocs = "<<assocList.size()<<"\n"; 00271 00272 if (strcmp(msg->getName(),"PassiveOPEN")==0 || strcmp(msg->getName(),"Associate")==0) 00273 { 00274 if (assocList.size()>0) 00275 { 00276 assoc = NULL; 00277 SCTPOpenCommand* open = check_and_cast<SCTPOpenCommand*>(controlInfo); 00278 sctpEV3<<"Looking for assoc with remoteAddr="<<open->getRemoteAddr()<<", remotePort="<<open->getRemotePort()<<", localPort="<<open->getLocalPort()<<"\n"; 00279 for (std::list<SCTPAssociation*>::iterator iter=assocList.begin(); iter!=assocList.end(); iter++) 00280 { 00281 sctpEV3<<"remoteAddr="<<(*iter)->remoteAddr<<", remotePort="<<(*iter)->remotePort<<", localPort="<<(*iter)->localPort<<"\n"; 00282 if ((*iter)->remoteAddr == open->getRemoteAddr() && (*iter)->localPort==open->getLocalPort() && (*iter)->remotePort==open->getRemotePort()) 00283 { 00284 assoc = (*iter); 00285 break; 00286 } 00287 } 00288 } 00289 if (assoc==NULL) 00290 { 00291 assoc = new SCTPAssociation(this,appGateIndex,assocId); 00292 00293 AppConnKey key; 00294 key.appGateIndex = appGateIndex; 00295 key.assocId = assocId; 00296 sctpAppConnMap[key] = assoc; 00297 sctpEV3 << "SCTP association created for appGateIndex " << appGateIndex << " and assoc "<<assocId<<"\n"; 00298 bool ret = assoc->processAppCommand(PK(msg)); 00299 if (!ret) 00300 { 00301 removeAssociation(assoc); 00302 } 00303 } 00304 } 00305 } 00306 else 00307 { 00308 sctpEV3<<"assoc found\n"; 00309 bool ret = assoc->processAppCommand(PK(msg)); 00310 00311 if (!ret) 00312 removeAssociation(assoc); 00313 } 00314 delete msg; 00315 } 00316 if (ev.isGUI()) 00317 updateDisplayString(); 00318 } 00319 00320 void SCTP::sendAbortFromMain(SCTPMessage* sctpmsg, IPvXAddress srcAddr, IPvXAddress destAddr) 00321 { 00322 SCTPMessage *msg = new SCTPMessage(); 00323 00324 sctpEV3<<"\n\nSCTPMain:sendABORT \n"; 00325 00326 msg->setSrcPort(sctpmsg->getDestPort()); 00327 msg->setDestPort(sctpmsg->getSrcPort()); 00328 msg->setBitLength(SCTP_COMMON_HEADER*8); 00329 msg->setChecksumOk(true); 00330 00331 SCTPAbortChunk* abortChunk = new SCTPAbortChunk("ABORT"); 00332 abortChunk->setChunkType(ABORT); 00333 if (sctpmsg->getChunksArraySize()>0 && ((SCTPChunk*)(sctpmsg->getChunks(0)))->getChunkType()==INIT) 00334 { 00335 00336 SCTPInitChunk* initChunk = check_and_cast<SCTPInitChunk *>(sctpmsg->getChunks(0)); 00337 abortChunk->setT_Bit(0); 00338 msg->setTag(initChunk->getInitTag()); 00339 } 00340 else 00341 { 00342 abortChunk->setT_Bit(1); 00343 msg->setTag(sctpmsg->getTag()); 00344 } 00345 abortChunk->setBitLength(SCTP_ABORT_CHUNK_LENGTH*8); 00346 msg->addChunk(abortChunk); 00347 if ((bool)par("udpEncapsEnabled")) 00348 { 00349 msg->setKind(UDP_C_DATA); 00350 std::cout<<"VTag="<<msg->getTag()<<"\n"; 00351 UDPControlInfo *ctrl = new UDPControlInfo(); 00352 ctrl->setSrcPort(9899); 00353 ctrl->setDestAddr(destAddr.get4()); 00354 ctrl->setDestPort(9899); 00355 msg->setControlInfo(ctrl); 00356 } 00357 else 00358 { 00359 IPControlInfo *controlInfo = new IPControlInfo(); 00360 controlInfo->setProtocol(IP_PROT_SCTP); 00361 controlInfo->setSrcAddr(srcAddr.get4()); 00362 controlInfo->setDestAddr(destAddr.get4()); 00363 msg->setControlInfo(controlInfo); 00364 } 00365 send(msg,"to_ip"); 00366 } 00367 00368 void SCTP::sendShutdownCompleteFromMain(SCTPMessage* sctpmsg, IPvXAddress srcAddr, IPvXAddress destAddr) 00369 { 00370 SCTPMessage *msg = new SCTPMessage(); 00371 00372 sctpEV3<<"\n\nSCTP:sendABORT \n"; 00373 00374 msg->setSrcPort(sctpmsg->getDestPort()); 00375 msg->setDestPort(sctpmsg->getSrcPort()); 00376 msg->setBitLength(SCTP_COMMON_HEADER*8); 00377 msg->setChecksumOk(true); 00378 00379 SCTPShutdownCompleteChunk* scChunk = new SCTPShutdownCompleteChunk("SHUTDOWN_COMPLETE"); 00380 scChunk->setChunkType(SHUTDOWN_COMPLETE); 00381 scChunk->setTBit(1); 00382 msg->setTag(sctpmsg->getTag()); 00383 00384 scChunk->setBitLength(SCTP_SHUTDOWN_ACK_LENGTH*8); 00385 msg->addChunk(scChunk); 00386 IPControlInfo *controlInfo = new IPControlInfo(); 00387 controlInfo->setProtocol(IP_PROT_SCTP); 00388 controlInfo->setSrcAddr(srcAddr.get4()); 00389 controlInfo->setDestAddr(destAddr.get4()); 00390 msg->setControlInfo(controlInfo); 00391 send(msg,"to_ip"); 00392 } 00393 00394 00395 void SCTP::updateDisplayString() 00396 { 00397 if (ev.disable_tracing) 00398 { 00399 // in express mode, we don't bother to update the display 00400 // (std::map's iteration is not very fast if map is large) 00401 getDisplayString().setTagArg("t",0,""); 00402 return; 00403 } 00404 00405 } 00406 00407 SCTPAssociation *SCTP::findAssocWithVTag(uint32 peerVTag, uint32 remotePort, uint32 localPort) 00408 { 00409 00410 printVTagMap(); 00411 sctpEV3<<"findAssocWithVTag: peerVTag="<<peerVTag<<" srcPort="<<remotePort<<" destPort="<<localPort<<"\n"; 00412 printInfoConnMap(); 00413 00414 // try with fully qualified SockPair 00415 for (SctpVTagMap::iterator i=sctpVTagMap.begin(); i!=sctpVTagMap.end();i++) 00416 { 00417 if ((i->second.peerVTag==peerVTag && i->second.localPort==localPort 00418 && i->second.remotePort==remotePort) 00419 || (i->second.localVTag==peerVTag && i->second.localPort==localPort 00420 && i->second.remotePort==remotePort)) 00421 return getAssoc(i->first); 00422 } 00423 return NULL; 00424 } 00425 00426 SCTPAssociation *SCTP::findAssocForMessage(IPvXAddress srcAddr, IPvXAddress destAddr, uint32 srcPort, uint32 destPort, bool findListen) 00427 { 00428 SockPair key; 00429 00430 key.localAddr = destAddr; 00431 key.remoteAddr = srcAddr; 00432 key.localPort = destPort; 00433 key.remotePort = srcPort; 00434 SockPair save = key; 00435 sctpEV3<<"findAssocForMessage: srcAddr="<<destAddr<<" destAddr="<<srcAddr<<" srcPort="<<destPort<<" destPort="<<srcPort<<"\n"; 00436 printInfoConnMap(); 00437 00438 // try with fully qualified SockPair 00439 SctpConnMap::iterator i; 00440 i = sctpConnMap.find(key); 00441 if (i!=sctpConnMap.end()) 00442 return i->second; 00443 00444 00445 // try with localAddr missing (only localPort specified in passive/active open) 00446 key.localAddr.set("0.0.0.0"); 00447 00448 i = sctpConnMap.find(key); 00449 if (i!=sctpConnMap.end()) 00450 { 00451 00452 //sctpEV3<<"try with localAddr missing (only localPort specified in passive/active open)\n"; 00453 00454 return i->second; 00455 } 00456 00457 if (findListen==true) 00458 { 00459 /*key = save; 00460 key.localPort = 0; 00461 key.localAddr.set("0.0.0.0"); 00462 i = sctpConnMap.find(key); 00463 if (i!=sctpConnMap.end()) 00464 { 00465 return i->second; 00466 }*/ 00467 00468 00469 // try fully qualified local socket + blank remote socket (for incoming SYN) 00470 key = save; 00471 key.remoteAddr.set("0.0.0.0"); 00472 key.remotePort = 0; 00473 i = sctpConnMap.find(key); 00474 if (i!=sctpConnMap.end()) 00475 { 00476 00477 //sctpEV3<<"try fully qualified local socket + blank remote socket \n"; 00478 00479 return i->second; 00480 } 00481 00482 00483 // try with blank remote socket, and localAddr missing (for incoming SYN) 00484 key.localAddr.set("0.0.0.0"); 00485 i = sctpConnMap.find(key); 00486 if (i!=sctpConnMap.end()) 00487 { 00488 00489 //sctpEV3<<"try with blank remote socket, and localAddr missing \n"; 00490 00491 return i->second; 00492 } 00493 } 00494 // given up 00495 00496 sctpEV3<<"giving up on trying to find assoc for localAddr="<<srcAddr<<" remoteAddr="<<destAddr<<" localPort="<<srcPort<<" remotePort="<<destPort<<"\n"; 00497 return NULL; 00498 } 00499 00500 SCTPAssociation *SCTP::findAssocForApp(int32 appGateIndex, int32 assocId) 00501 { 00502 AppConnKey key; 00503 key.appGateIndex = appGateIndex; 00504 key.assocId = assocId; 00505 sctpEV3<<"findAssoc for appGateIndex "<<appGateIndex<<" and assoc "<<assocId<<"\n"; 00506 SctpAppConnMap::iterator i = sctpAppConnMap.find(key); 00507 return i==sctpAppConnMap.end() ? NULL : i->second; 00508 } 00509 00510 uint16 SCTP::getEphemeralPort() 00511 { 00512 if (nextEphemeralPort==5000) 00513 error("Ephemeral port range 1024..4999 exhausted (email SCTP model " 00514 "author that he should implement reuse of ephemeral ports!!!)"); 00515 return nextEphemeralPort++; 00516 } 00517 00518 void SCTP::updateSockPair(SCTPAssociation *conn, IPvXAddress localAddr, IPvXAddress remoteAddr, int32 localPort, int32 remotePort) 00519 { 00520 SockPair key; 00521 sctpEV3<<"updateSockPair: localAddr: "<<localAddr<<" remoteAddr="<<remoteAddr<<" localPort="<<localPort<<" remotePort="<<remotePort<<"\n"; 00522 00523 key.localAddr = (conn->localAddr = localAddr); 00524 key.remoteAddr = (conn->remoteAddr = remoteAddr); 00525 key.localPort = conn->localPort = localPort; 00526 key.remotePort = conn->remotePort = remotePort; 00527 00528 for (SctpConnMap::iterator i=sctpConnMap.begin(); i!=sctpConnMap.end(); i++) 00529 { 00530 if (i->second == conn) 00531 { 00532 sctpConnMap.erase(i); 00533 break; 00534 } 00535 } 00536 00537 sctpEV3<<"updateSockPair conn="<<conn<<" localAddr="<<key.localAddr<<" remoteAddr="<<key.remoteAddr<<" localPort="<<key.localPort<<" remotePort="<<remotePort<<"\n"; 00538 00539 sctpConnMap[key] = conn; 00540 sizeConnMap = sctpConnMap.size(); 00541 //sctpEV3<<"number of connections="<<sctpConnMap.size()<<"\n"; 00542 sctpEV3<<"assoc inserted in sctpConnMap\n"; 00543 printInfoConnMap(); 00544 } 00545 00546 void SCTP::addLocalAddress(SCTPAssociation *conn, IPvXAddress address) 00547 { 00548 00549 //sctpEV3<<"Add local address: "<<address<<"\n"; 00550 00551 SockPair key; 00552 00553 key.localAddr = conn->localAddr; 00554 key.remoteAddr = conn->remoteAddr; 00555 key.localPort = conn->localPort; 00556 key.remotePort = conn->remotePort; 00557 00558 SctpConnMap::iterator i = sctpConnMap.find(key); 00559 if (i!=sctpConnMap.end()) 00560 { 00561 ASSERT(i->second==conn); 00562 if (key.localAddr.isUnspecified()) 00563 { 00564 sctpConnMap.erase(i); 00565 sizeConnMap--; 00566 } 00567 } 00568 else 00569 sctpEV3<<"no actual sockPair found\n"; 00570 key.localAddr = address; 00571 //key.localAddr = address.get4().getInt(); 00572 // //sctpEV3<<"laddr="<<key.localAddr<<" lp="<<key.localPort<<" raddr="<<key.remoteAddr<<" rPort="<<key.remotePort<<"\n"; 00573 sctpConnMap[key] = conn; 00574 sizeConnMap = sctpConnMap.size(); 00575 sctpEV3<<"number of connections="<<sizeConnMap<<"\n"; 00576 00577 printInfoConnMap(); 00578 } 00579 00580 void SCTP::addLocalAddressToAllRemoteAddresses(SCTPAssociation *conn, IPvXAddress address, std::vector<IPvXAddress> remAddresses) 00581 { 00582 00583 //sctpEV3<<"Add local address: "<<address<<"\n"; 00584 00585 SockPair key; 00586 00587 for (AddressVector::iterator i=remAddresses.begin(); i!=remAddresses.end(); ++i) 00588 { 00589 //sctpEV3<<"remote address="<<(*i)<<"\n"; 00590 key.localAddr = conn->localAddr; 00591 key.remoteAddr = (*i); 00592 key.localPort = conn->localPort; 00593 key.remotePort = conn->remotePort; 00594 00595 SctpConnMap::iterator j = sctpConnMap.find(key); 00596 if (j!=sctpConnMap.end()) 00597 { 00598 ASSERT(j->second==conn); 00599 if (key.localAddr.isUnspecified()) 00600 { 00601 sctpConnMap.erase(j); 00602 sizeConnMap--; 00603 } 00604 00605 } 00606 else 00607 sctpEV3<<"no actual sockPair found\n"; 00608 key.localAddr = address; 00609 sctpConnMap[key] = conn; 00610 00611 sizeConnMap++; 00612 sctpEV3<<"number of connections="<<sctpConnMap.size()<<"\n"; 00613 00614 printInfoConnMap(); 00615 } 00616 } 00617 00618 void SCTP::removeLocalAddressFromAllRemoteAddresses(SCTPAssociation *conn, IPvXAddress address, std::vector<IPvXAddress> remAddresses) 00619 { 00620 00621 //sctpEV3<<"Remove local address: "<<address<<"\n"; 00622 00623 SockPair key; 00624 00625 for (AddressVector::iterator i=remAddresses.begin(); i!=remAddresses.end(); ++i) 00626 { 00627 //sctpEV3<<"remote address="<<(*i)<<"\n"; 00628 key.localAddr = address; 00629 key.remoteAddr = (*i); 00630 key.localPort = conn->localPort; 00631 key.remotePort = conn->remotePort; 00632 00633 SctpConnMap::iterator j = sctpConnMap.find(key); 00634 if (j!=sctpConnMap.end()) 00635 { 00636 ASSERT(j->second==conn); 00637 sctpConnMap.erase(j); 00638 sizeConnMap--; 00639 } 00640 else 00641 sctpEV3<<"no actual sockPair found\n"; 00642 00643 //sctpEV3<<"number of connections="<<sctpConnMap.size()<<"\n"; 00644 00645 printInfoConnMap(); 00646 } 00647 } 00648 00649 void SCTP::removeRemoteAddressFromAllConnections(SCTPAssociation *conn, IPvXAddress address, std::vector<IPvXAddress> locAddresses) 00650 { 00651 00652 //sctpEV3<<"Remove remote address: "<<address<<"\n"; 00653 00654 SockPair key; 00655 00656 for (AddressVector::iterator i=locAddresses.begin(); i!=locAddresses.end(); i++) 00657 { 00658 //sctpEV3<<"local address="<<(*i)<<"\n"; 00659 key.localAddr = (*i); 00660 key.remoteAddr = address; 00661 key.localPort = conn->localPort; 00662 key.remotePort = conn->remotePort; 00663 00664 SctpConnMap::iterator j = sctpConnMap.find(key); 00665 if (j!=sctpConnMap.end()) 00666 { 00667 ASSERT(j->second==conn); 00668 sctpConnMap.erase(j); 00669 sizeConnMap--; 00670 } 00671 else 00672 sctpEV3<<"no actual sockPair found\n"; 00673 00674 //sctpEV3<<"number of connections="<<sctpConnMap.size()<<"\n"; 00675 00676 printInfoConnMap(); 00677 } 00678 } 00679 00680 void SCTP::addRemoteAddress(SCTPAssociation *conn, IPvXAddress localAddress, IPvXAddress remoteAddress) 00681 { 00682 00683 sctpEV3<<"Add remote Address: "<<remoteAddress<<" to local Address "<<localAddress<<"\n"; 00684 00685 SockPair key; 00686 key.localAddr = localAddress; 00687 key.remoteAddr = remoteAddress; 00688 key.localPort = conn->localPort; 00689 key.remotePort = conn->remotePort; 00690 00691 SctpConnMap::iterator i = sctpConnMap.find(key); 00692 if (i!=sctpConnMap.end()) 00693 { 00694 ASSERT(i->second==conn); 00695 } 00696 else 00697 { 00698 00699 //sctpEV3<<"no actual sockPair found\n"; 00700 00701 sctpConnMap[key] = conn; 00702 sizeConnMap++; 00703 } 00704 00705 //sctpEV3<<"number of connections="<<sctpConnMap.size()<<"\n"; 00706 printInfoConnMap(); 00707 } 00708 00709 void SCTP::addForkedAssociation(SCTPAssociation *assoc, SCTPAssociation *newAssoc, IPvXAddress localAddr, IPvXAddress remoteAddr, int32 localPort, int32 remotePort) 00710 { 00711 SockPair keyAssoc; 00712 00713 ev<<"addForkedConnection assocId="<<assoc->assocId<<" newId="<<newAssoc->assocId<<"\n"; 00714 00715 for (SctpConnMap::iterator j=sctpConnMap.begin(); j!=sctpConnMap.end(); ++j) 00716 if (assoc->assocId==j->second->assocId) 00717 keyAssoc = j->first; 00718 // update conn's socket pair, and register newConn (which'll keep LISTENing) 00719 updateSockPair(assoc, localAddr, remoteAddr, localPort, remotePort); 00720 updateSockPair(newAssoc, keyAssoc.localAddr, keyAssoc.remoteAddr, keyAssoc.localPort, keyAssoc.remotePort); 00721 // conn will get a new assocId... 00722 AppConnKey key; 00723 key.appGateIndex = assoc->appGateIndex; 00724 key.assocId = assoc->assocId; 00725 sctpAppConnMap.erase(key); 00726 key.assocId = assoc->assocId = getNewConnId(); 00727 sctpAppConnMap[key] = assoc; 00728 00729 // ...and newConn will live on with the old assocId 00730 key.appGateIndex = newAssoc->appGateIndex; 00731 key.assocId = newAssoc->assocId; 00732 sctpAppConnMap[key] = newAssoc; 00733 /*ev<<"assocId="<<assoc->assocId<<" remoteAddr="<<assoc->remoteAddr<<"\n"; 00734 assoc->removeOldPath();*/ 00735 printInfoConnMap(); 00736 } 00737 00738 00739 00740 void SCTP::removeAssociation(SCTPAssociation *conn) 00741 { 00742 bool ok = false; 00743 bool find = false; 00744 const int32 id = conn->assocId; 00745 00746 sctpEV3 << "Deleting SCTP connection " << conn << " id= "<< id << endl; 00747 00748 printInfoConnMap(); 00749 if (sizeConnMap > 0) { 00750 AssocStatMap::iterator assocStatMapIterator = assocStatMap.find(conn->assocId); 00751 if (assocStatMapIterator != assocStatMap.end()) { 00752 assocStatMapIterator->second.stop = simulation.getSimTime(); 00753 assocStatMapIterator->second.lifeTime = assocStatMapIterator->second.stop - assocStatMapIterator->second.start; 00754 assocStatMapIterator->second.throughput = assocStatMapIterator->second.ackedBytes*8 / assocStatMapIterator->second.lifeTime.dbl(); 00755 } 00756 while (!ok) { 00757 if (sizeConnMap == 0) { 00758 ok = true; 00759 } 00760 else { 00761 for (SctpConnMap::iterator sctpConnMapIterator = sctpConnMap.begin(); 00762 sctpConnMapIterator != sctpConnMap.end(); sctpConnMapIterator++) { 00763 if (sctpConnMapIterator->second != NULL) { 00764 SCTPAssociation* assoc = sctpConnMapIterator->second; 00765 if (assoc->assocId == conn->assocId) { 00766 if (assoc->T1_InitTimer) { 00767 assoc->stopTimer(assoc->T1_InitTimer); 00768 } 00769 if (assoc->T2_ShutdownTimer) { 00770 assoc->stopTimer(assoc->T2_ShutdownTimer); 00771 } 00772 if (assoc->T5_ShutdownGuardTimer) { 00773 assoc->stopTimer(assoc->T5_ShutdownGuardTimer); 00774 } 00775 if (assoc->SackTimer) { 00776 assoc->stopTimer(assoc->SackTimer); 00777 } 00778 sctpConnMap.erase(sctpConnMapIterator); 00779 sizeConnMap--; 00780 find = true; 00781 break; 00782 } 00783 } 00784 } 00785 } 00786 00787 if (!find) { 00788 ok = true; 00789 } 00790 else { 00791 find = false; 00792 } 00793 } 00794 } 00795 00796 // T.D. 26.11.09: Write statistics 00797 char str[128]; 00798 for (SCTPAssociation::SCTPPathMap::iterator pathMapIterator = conn->sctpPathMap.begin(); 00799 pathMapIterator != conn->sctpPathMap.end(); pathMapIterator++) { 00800 const SCTPPathVariables* path = pathMapIterator->second; 00801 snprintf((char*)&str, sizeof(str), "Number of Fast Retransmissions %d:%s", 00802 conn->assocId, path->remoteAddress.str().c_str()); 00803 recordScalar(str, path->numberOfFastRetransmissions); 00804 snprintf((char*)&str, sizeof(str), "Number of Timer-Based Retransmissions %d:%s", 00805 conn->assocId, path->remoteAddress.str().c_str()); 00806 recordScalar(str, path->numberOfTimerBasedRetransmissions); 00807 snprintf((char*)&str, sizeof(str), "Number of Heartbeats Sent %d:%s", 00808 conn->assocId, path->remoteAddress.str().c_str()); 00809 recordScalar(str, path->numberOfHeartbeatsSent); 00810 snprintf((char*)&str, sizeof(str), "Number of Heartbeats Received %d:%s", 00811 conn->assocId, path->remoteAddress.str().c_str()); 00812 recordScalar(str, path->numberOfHeartbeatsRcvd); 00813 snprintf((char*)&str, sizeof(str), "Number of Heartbeat ACKs Sent %d:%s", 00814 conn->assocId, path->remoteAddress.str().c_str()); 00815 recordScalar(str, path->numberOfHeartbeatAcksSent); 00816 snprintf((char*)&str, sizeof(str), "Number of Heartbeat ACKs Received %d:%s", 00817 conn->assocId, path->remoteAddress.str().c_str()); 00818 recordScalar(str, path->numberOfHeartbeatAcksRcvd); 00819 } 00820 00821 00822 conn->removePath(); 00823 conn->deleteStreams(); 00824 00825 // TD 20.11.09: Chunks may be in the transmission and retransmission queues simultaneously. 00826 // Remove entry from transmission queue if it is already in the retransmission queue. 00827 for (SCTPQueue::PayloadQueue::iterator i = conn->getRetransmissionQueue()->payloadQueue.begin(); 00828 i != conn->getRetransmissionQueue()->payloadQueue.end(); i++) { 00829 SCTPQueue::PayloadQueue::iterator j = conn->getTransmissionQueue()->payloadQueue.find(i->second->tsn); 00830 if(j != conn->getTransmissionQueue()->payloadQueue.end()) { 00831 conn->getTransmissionQueue()->payloadQueue.erase(j); 00832 } 00833 } 00834 // TD 20.11.09: Now, both queues can be safely deleted. 00835 delete conn->getRetransmissionQueue(); 00836 delete conn->getTransmissionQueue(); 00837 00838 AppConnKey key; 00839 key.appGateIndex = conn->appGateIndex; 00840 key.assocId = conn->assocId; 00841 sctpAppConnMap.erase(key); 00842 assocList.remove(conn); 00843 delete conn; 00844 } 00845 00846 SCTPAssociation* SCTP::getAssoc(int32 assocId) 00847 { 00848 for (SctpAppConnMap::iterator i = sctpAppConnMap.begin(); i!=sctpAppConnMap.end(); i++) 00849 { 00850 if (i->first.assocId==assocId) 00851 return i->second; 00852 } 00853 return NULL; 00854 } 00855 00856 void SCTP::finish() 00857 { 00858 SctpConnMap::iterator connMapIterator = sctpConnMap.begin(); 00859 while (connMapIterator != sctpConnMap.end()) { 00860 removeAssociation(connMapIterator->second); 00861 connMapIterator = sctpConnMap.begin(); 00862 } 00863 ev << getFullPath() << ": finishing SCTP with " 00864 << sctpConnMap.size() << " connections open." << endl; 00865 00866 for (AssocStatMap::const_iterator iterator = assocStatMap.begin(); 00867 iterator != assocStatMap.end(); iterator++) { 00868 const SCTP::AssocStat& assoc = iterator->second; 00869 00870 ev << "Association " << assoc.assocId << ": started at " << assoc.start 00871 << " and finished at " << assoc.stop << " --> lifetime: " << assoc.lifeTime << endl; 00872 ev << "Association " << assoc.assocId << ": sent bytes=" << assoc.sentBytes 00873 << ", acked bytes=" << assoc.ackedBytes<< ", throughput=" << assoc.throughput<< " bit/s" << endl; 00874 ev << "Association " << assoc.assocId << ": transmitted Bytes=" 00875 << assoc.transmittedBytes<< ", retransmitted Bytes=" << assoc.transmittedBytes-assoc.ackedBytes<< endl; 00876 ev << "Association " << assoc.assocId << ": number of Fast RTX=" 00877 << assoc.numFastRtx << ", number of Timer-Based RTX=" << assoc.numT3Rtx 00878 << ", path failures=" << assoc.numPathFailures<< ", ForwardTsns=" << assoc.numForwardTsn<< endl; 00879 ev << "AllMessages=" <<numPacketsReceived<< " BadMessages=" <<numPacketsDropped<< endl; 00880 00881 recordScalar("Association Lifetime", assoc.lifeTime); 00882 recordScalar("Acked Bytes", assoc.ackedBytes); 00883 recordScalar("Throughput [bit/s]", assoc.throughput); 00884 recordScalar("Transmitted Bytes", assoc.transmittedBytes); 00885 recordScalar("Fast RTX", assoc.numFastRtx); 00886 recordScalar("Timer-Based RTX", assoc.numT3Rtx); 00887 recordScalar("Duplicate Acks", assoc.numDups); 00888 recordScalar("Packets Received", numPacketsReceived); 00889 recordScalar("Packets Dropped", numPacketsDropped); 00890 00891 } 00892 }