|
INET Framework for OMNeT++/OMNEST
|
00001 // 00002 // Copyright (C) 2006 Sam Jansen, Andras Varga 00003 // 2009 Zoltan Bojthe 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, write to the Free Software 00017 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00018 // 00019 00020 #ifdef WITH_TCP_NSC 00021 00022 #include "TCP_NSC.h" 00023 00024 #include "headers/defs.h" // for endian macros 00025 00026 #include "IPControlInfo.h" 00027 #include "IPv6ControlInfo.h" 00028 #include "headers/tcp.h" 00029 #include "TCPCommand_m.h" 00030 #include "TCPIPchecksum.h" 00031 #include "TCP_NSC_Queues.h" 00032 #include "TCPSegment.h" 00033 #include "TCPSerializer.h" 00034 00035 #include <assert.h> 00036 #include <dlfcn.h> 00037 #include <netinet/in.h> 00038 00039 00040 Define_Module(TCP_NSC); 00041 00042 00043 //static member variables: 00044 const IPvXAddress TCP_NSC::localInnerIpS("1.0.0.253"); 00045 const IPvXAddress TCP_NSC::localInnerMaskS("255.255.255.0"); 00046 const IPvXAddress TCP_NSC::localInnerGwS("1.0.0.254"); 00047 const IPvXAddress TCP_NSC::remoteFirstInnerIpS("2.0.0.1"); 00048 00049 const char * TCP_NSC::stackNameParamNameS = "stackName"; 00050 00051 const char * TCP_NSC::bufferSizeParamNameS = "stackBufferSize"; 00052 00053 bool TCP_NSC::testingS; 00054 bool TCP_NSC::logverboseS; 00055 00056 // macro for normal ev<< logging (note: deliberately no parens in macro def) 00057 // FIXME 00058 //#define tcpEV (((ev.disable_tracing) || (TCP_NSC::testingS)) ? ev : std::cout) 00059 #define tcpEV ev 00060 //#define tcpEV std::cout 00061 00062 struct nsc_iphdr 00063 { 00064 #if BYTE_ORDER == LITTLE_ENDIAN 00065 unsigned int ihl:4; 00066 unsigned int version:4; 00067 #elif BYTE_ORDER == BIG_ENDIAN 00068 unsigned int version:4; 00069 unsigned int ihl:4; 00070 #else 00071 # error "Please check BYTE_ORDER declaration" 00072 #endif 00073 uint8_t tos; 00074 uint16_t tot_len; 00075 uint16_t id; 00076 uint16_t frag_off; 00077 uint8_t ttl; 00078 uint8_t protocol; 00079 uint16_t check; 00080 uint32_t saddr; 00081 uint32_t daddr; 00082 /*The options start here. */ 00083 } __attribute__((packed)); 00084 00085 struct nsc_ipv6hdr 00086 { 00087 #if BYTE_ORDER == LITTLE_ENDIAN 00088 uint32_t flow:20; 00089 uint32_t ds:8; 00090 uint32_t version:4; 00091 #elif BYTE_ORDER == BIG_ENDIAN 00092 uint32_t version:4; 00093 uint32_t ds:8; 00094 uint32_t flow:20; 00095 #else 00096 # error "Please check BYTE_ORDER declaration" 00097 #endif 00098 uint16_t len; 00099 uint8_t next_header; 00100 uint8_t hop_limit; 00101 uint16_t id; 00102 uint16_t frag_off; 00103 uint8_t ttl; 00104 uint8_t protocol; 00105 uint16_t check; 00106 uint32_t saddr[4]; 00107 uint32_t daddr[4]; 00108 } __attribute__((packed)); 00109 00110 static char *flags2str(unsigned char flags) 00111 { 00112 static char buf[512]; 00113 buf[0]='\0'; 00114 if(flags & TH_FIN) strcat(buf, " FIN"); 00115 if(flags & TH_SYN) strcat(buf, " SYN"); 00116 if(flags & TH_RST) strcat(buf, " RST"); 00117 if(flags & TH_PUSH) strcat(buf, " PUSH"); 00118 if(flags & TH_ACK) strcat(buf, " ACK"); 00119 if(flags & TH_URG) strcat(buf, " URG"); 00120 // if(flags & TH_ECE) strcat(buf, " ECE"); 00121 // if(flags & TH_CWR) strcat(buf, " CWR"); 00122 00123 return buf; 00124 } 00125 00126 static std::ostream& operator<<(std::ostream& osP, const TCP_NSC_Connection& connP) 00127 { 00128 osP << "Conn={" 00129 << "connId=" << connP.connIdM 00130 << " appGateIndex=" << connP.appGateIndexM 00131 << " nscsocket=" << connP.pNscSocketM 00132 << " sentEstablishedM=" << connP.sentEstablishedM 00133 << '}'; 00134 return osP; 00135 } 00136 00137 static std::ostream& operator<<(std::ostream& osP, const TCP_NSC_Connection::SockAddr& sockAddrP) 00138 { 00139 osP << sockAddrP.ipAddrM << ":" << sockAddrP.portM; 00140 return osP; 00141 } 00142 00143 static std::ostream& operator<<(std::ostream& osP, const TCP_NSC_Connection::SockPair& sockPairP) 00144 { 00145 osP << "{loc=" << sockPairP.localM << ", rem=" << sockPairP.remoteM << "}"; 00146 return osP; 00147 } 00148 00149 TCP_NSC::TCP_NSC() 00150 : pStackM(NULL), 00151 pNsiTimerM(NULL), 00152 isAliveM(false), 00153 curAddrCounterM(0), 00154 curConnM(NULL), 00155 00156 // statistics: 00157 sndWndVector(NULL), 00158 rcvWndVector(NULL), 00159 rcvAdvVector(NULL), 00160 sndNxtVector(NULL), 00161 sndAckVector(NULL), 00162 rcvSeqVector(NULL), 00163 rcvAckVector(NULL), 00164 unackedVector(NULL), 00165 dupAcksVector(NULL), 00166 pipeVector(NULL), 00167 sndSacksVector(NULL), 00168 rcvSacksVector(NULL), 00169 rcvOooSegVector(NULL), 00170 sackedBytesVector(NULL), 00171 tcpRcvQueueBytesVector(NULL), 00172 tcpRcvQueueDropsVector(NULL) 00173 { 00174 // statistics: 00175 if (true) // (getTcpMain()->recordStatistics) 00176 { 00177 //sndWndVector = new cOutVector("send window"); 00178 //rcvWndVector = new cOutVector("receive window"); 00179 sndNxtVector = new cOutVector("sent seq"); 00180 sndAckVector = new cOutVector("sent ack"); 00181 rcvSeqVector = new cOutVector("rcvd seq"); 00182 rcvAckVector = new cOutVector("rcvd ack"); 00183 //unackedVector = new cOutVector("unacked bytes"); 00184 //dupAcksVector = new cOutVector("rcvd dupAcks"); 00185 //pipeVector = new cOutVector("pipe"); 00186 //sndSacksVector = new cOutVector("sent sacks"); 00187 //rcvSacksVector = new cOutVector("rcvd sacks"); 00188 //rcvOooSegVector = new cOutVector("rcvd oooseg"); 00189 //sackedBytesVector = new cOutVector("rcvd sackedBytes"); 00190 //tcpRcvQueueBytesVector = new cOutVector("tcpRcvQueueBytes"); 00191 //tcpRcvQueueDropsVector = new cOutVector("tcpRcvQueueDrops"); 00192 } 00193 } 00194 00195 // return mapped remote ip in host byte order 00196 // if addrP not exists in map, it's create a new nsc addr 00197 uint32_t TCP_NSC::mapRemote2Nsc(IPvXAddress const& addrP) 00198 { 00199 Remote2NscMap::iterator i = remote2NscMapM.find(addrP); 00200 if (i != remote2NscMapM.end()) 00201 { 00202 return i->second; 00203 } 00204 00205 // get first free remote NSC IP 00206 uint32_t ret = remoteFirstInnerIpS.get4().getInt(); 00207 Nsc2RemoteMap::iterator j; 00208 for( j = nsc2RemoteMapM.begin(); j != nsc2RemoteMapM.end(); j++) 00209 { 00210 if(j->first > ret) 00211 break; 00212 ret = j->first + 1; 00213 } 00214 00215 // add new pair to maps 00216 remote2NscMapM[addrP] = ret; 00217 nsc2RemoteMapM[ret] = addrP; 00218 ASSERT( remote2NscMapM.find(addrP) != remote2NscMapM.end() ); 00219 ASSERT( nsc2RemoteMapM.find(ret) != nsc2RemoteMapM.end() ); 00220 return ret; 00221 } 00222 00223 // return original remote ip from remote NSC IP 00224 // assert if IP not exists in map 00225 // nscAddrP in host byte order! 00226 IPvXAddress const & TCP_NSC::mapNsc2Remote(uint32_t nscAddrP) 00227 { 00228 Nsc2RemoteMap::iterator i = nsc2RemoteMapM.find(nscAddrP); 00229 if (i != nsc2RemoteMapM.end()) 00230 { 00231 return i->second; 00232 } 00233 ASSERT(0); 00234 exit(1); 00235 } 00236 // x == mapNsc2Remote(mapRemote2Nsc(x)) 00237 00238 void TCP_NSC::decode_tcp(const void *packet_data, int hdr_len) 00239 { 00240 struct tcphdr const *tcp = (struct tcphdr const*)packet_data; 00241 char buf[4096]; 00242 00243 sprintf(buf, "Src port:%hu Dst port:%hu Seq:%u Ack:%u Off:%hhu %s\n", 00244 ntohs(tcp->th_sport), ntohs(tcp->th_dport), ntohl(tcp->th_seq), 00245 ntohl(tcp->th_ack), (unsigned char)tcp->th_offs, 00246 flags2str(tcp->th_flags) 00247 ); 00248 tcpEV << this << ": " << buf; 00249 sprintf(buf, "Win:%hu Sum:%hu Urg:%hu\n", 00250 ntohs(tcp->th_win), ntohs(tcp->th_sum), ntohs(tcp->th_urp)); 00251 tcpEV << this << ": " << buf; 00252 00253 if(hdr_len > 20) 00254 { 00255 unsigned char const *opt = (unsigned char const*)packet_data + sizeof(struct tcphdr); 00256 unsigned int optlen = tcp->th_offs*4 - 20; 00257 unsigned int optoffs = 0; 00258 00259 tcpEV << this << ": " << ("Options: "); 00260 while( 00261 (opt[optoffs] != 0) && 00262 (optoffs < optlen) 00263 ) 00264 { 00265 unsigned char len = opt[optoffs+1]; 00266 if(len == 0 && opt[optoffs] != 1) 00267 { 00268 sprintf(buf, "0-length option(%u)\n", opt[optoffs]); 00269 tcpEV << this << ": " << buf; 00270 break; 00271 } 00272 00273 len -= 2; 00274 00275 switch(opt[optoffs]) 00276 { 00277 case 1: tcpEV << ("No-Op "); optoffs++; break; 00278 case 2: { unsigned short mss = 0; 00279 //assert(len == 2); 00280 if(len == 2) { 00281 mss = (opt[optoffs+2] << 8) + (opt[optoffs+3]); 00282 sprintf(buf, "MSS(%u) ", mss); 00283 tcpEV << buf; 00284 } else { 00285 sprintf(buf, "MSS:l:%u ", len); 00286 tcpEV << buf; 00287 } 00288 optoffs += opt[optoffs+1]; 00289 break; 00290 } 00291 case 3: { 00292 unsigned char ws = 0; 00293 ASSERT(len == 1); 00294 ws = opt[optoffs+2]; 00295 sprintf(buf, "WS(%u) ", ws); 00296 tcpEV << buf; 00297 optoffs += opt[optoffs+1]; 00298 break; 00299 } 00300 case 4: { 00301 sprintf(buf, "SACK-Permitted "); 00302 tcpEV << buf; 00303 optoffs += opt[optoffs+1]; 00304 break; 00305 } 00306 case 5: { 00307 tcpEV << ("SACK "); 00308 optoffs += opt[optoffs+1]; 00309 break; 00310 } 00311 case 8: { 00312 int i; 00313 tcpEV << ("Timestamp("); 00314 for(i = 0; i < len; i++) { 00315 sprintf(buf, "%02x", opt[optoffs+2+i]); 00316 tcpEV << buf; 00317 } 00318 tcpEV << (") "); 00319 optoffs += opt[optoffs+1]; 00320 break; 00321 } 00322 default:{ 00323 sprintf(buf, "%u:%u ", opt[0], opt[1]); 00324 tcpEV << buf; 00325 optoffs += opt[optoffs+1]; 00326 break; 00327 } 00328 }; 00329 00330 } 00331 tcpEV << ("\n"); 00332 } 00333 } 00334 00335 void TCP_NSC::initialize() 00336 { 00337 tcpEV << this << ": initialize\n"; 00338 WATCH_MAP(tcpAppConnMapM); 00339 00340 cModule *netw = simulation.getSystemModule(); 00341 testingS = netw->hasPar("testing") && netw->par("testing").boolValue(); 00342 logverboseS = !testingS && netw->hasPar("logverbose") && netw->par("logverbose").boolValue(); 00343 00344 const char* stackName = this->par(stackNameParamNameS).stringValue(); 00345 00346 int bufferSize = (int)(this->par(bufferSizeParamNameS).longValue()); 00347 00348 loadStack(stackName, bufferSize); 00349 pStackM->if_attach(localInnerIpS.str().c_str(), localInnerMaskS.str().c_str(), 1500); 00350 pStackM->add_default_gateway(localInnerGwS.str().c_str()); 00351 00352 isAliveM = true; 00353 } 00354 00355 TCP_NSC::~TCP_NSC() 00356 { 00357 tcpEV << this << ": destructor\n"; 00358 isAliveM = false; 00359 while (!tcpAppConnMapM.empty()) 00360 { 00361 TcpAppConnMap::iterator i = tcpAppConnMapM.begin(); 00362 delete (*i).second.pNscSocketM; 00363 tcpAppConnMapM.erase(i); 00364 } 00365 00366 // statistics 00367 delete sndWndVector; 00368 delete rcvWndVector; 00369 delete rcvAdvVector; 00370 delete sndNxtVector; 00371 delete sndAckVector; 00372 delete rcvSeqVector; 00373 delete rcvAckVector; 00374 delete unackedVector; 00375 delete dupAcksVector; 00376 delete sndSacksVector; 00377 delete rcvSacksVector; 00378 delete rcvOooSegVector; 00379 delete tcpRcvQueueBytesVector; 00380 delete tcpRcvQueueDropsVector; 00381 delete pipeVector; 00382 delete sackedBytesVector; 00383 } 00384 00385 // send a TCP_I_ESTABLISHED msg to Application Layer 00386 void TCP_NSC::sendEstablishedMsg(TCP_NSC_Connection &connP) 00387 { 00388 00389 cMessage *msg = connP.createEstablishedMsg(); 00390 if(msg) 00391 { 00392 send(msg, "appOut", connP.appGateIndexM); 00393 connP.sentEstablishedM = true; 00394 } 00395 } 00396 00397 void TCP_NSC::changeAddresses(TCP_NSC_Connection &connP, 00398 const TCP_NSC_Connection::SockPair &inetSockPairP, 00399 const TCP_NSC_Connection::SockPair &nscSockPairP) 00400 { 00401 if (!(connP.inetSockPairM == inetSockPairP)) 00402 { 00403 tcpEV << "conn:" << connP << " change inetMap from " << connP.inetSockPairM << " to " << inetSockPairP << "\n"; 00404 inetSockPair2ConnIdMapM.erase(connP.inetSockPairM); 00405 connP.inetSockPairM = inetSockPairP; 00406 inetSockPair2ConnIdMapM[connP.inetSockPairM] = connP.connIdM; 00407 } 00408 if (!(connP.nscSockPairM == nscSockPairP)) 00409 { 00410 tcpEV << "conn:" << connP << " change nscMap from " << connP.nscSockPairM << " to " << nscSockPairP << "\n"; 00411 // remove old from map: 00412 nscSockPair2ConnIdMapM.erase(connP.nscSockPairM); 00413 // change addresses: 00414 connP.nscSockPairM = nscSockPairP; 00415 // and add to map: 00416 nscSockPair2ConnIdMapM[connP.nscSockPairM] = connP.connIdM; 00417 } 00418 } 00419 00420 void TCP_NSC::handleIpInputMessage(TCPSegment* tcpsegP) 00421 { 00422 // get src/dest addresses 00423 TCP_NSC_Connection::SockPair nscSockPair, inetSockPair, inetSockPairAny; 00424 00425 if (dynamic_cast<IPControlInfo *>(tcpsegP->getControlInfo())!=NULL) 00426 { 00427 IPControlInfo *controlInfo = (IPControlInfo *)tcpsegP->removeControlInfo(); 00428 inetSockPair.remoteM.ipAddrM = controlInfo->getSrcAddr(); 00429 inetSockPair.localM.ipAddrM = controlInfo->getDestAddr(); 00430 delete controlInfo; 00431 } 00432 else if (dynamic_cast<IPv6ControlInfo *>(tcpsegP->getControlInfo())!=NULL) 00433 { 00434 IPv6ControlInfo *controlInfo = (IPv6ControlInfo *)tcpsegP->removeControlInfo(); 00435 inetSockPair.remoteM.ipAddrM = controlInfo->getSrcAddr(); 00436 inetSockPair.localM.ipAddrM = controlInfo->getDestAddr(); 00437 delete controlInfo; 00438 { 00439 // HACK: when IPv6, then correcting the TCPOPTION_MAXIMUM_SEGMENT_SIZE option 00440 // with IP header size difference 00441 unsigned short numOptions = tcpsegP->getOptionsArraySize(); 00442 for (unsigned short i=0; i < numOptions; i++) 00443 { 00444 TCPOption& option = tcpsegP->getOptions(i); 00445 if(option.getKind() == TCPOPTION_MAXIMUM_SEGMENT_SIZE) 00446 { 00447 unsigned int value = option.getValues(0); 00448 value -= sizeof(struct nsc_ipv6hdr) - sizeof(struct nsc_iphdr); 00449 option.setValues(0, value); 00450 //tcpsegP->setOptions(i, option); 00451 } 00452 } 00453 } 00454 } 00455 else 00456 { 00457 error("(%s)%s arrived without control info", tcpsegP->getClassName(), tcpsegP->getName()); 00458 } 00459 00460 // statistics: 00461 if (rcvSeqVector) 00462 rcvSeqVector->record(tcpsegP->getSequenceNo()); 00463 if (rcvAckVector) 00464 rcvAckVector->record(tcpsegP->getAckNo()); 00465 00466 inetSockPair.remoteM.portM = tcpsegP->getSrcPort(); 00467 inetSockPair.localM.portM = tcpsegP->getDestPort(); 00468 nscSockPair.remoteM.portM = tcpsegP->getSrcPort(); 00469 nscSockPair.localM.portM = tcpsegP->getDestPort(); 00470 inetSockPairAny.localM = inetSockPair.localM; 00471 00472 // process segment 00473 size_t ipHdrLen = sizeof(nsc_iphdr); 00474 size_t const maxBufferSize = 4096; 00475 char *data = new char[maxBufferSize]; 00476 memset(data, 0, maxBufferSize); 00477 uint32_t nscSrcAddr = mapRemote2Nsc(inetSockPair.remoteM.ipAddrM); 00478 nscSockPair.localM.ipAddrM = localInnerIpS; 00479 nscSockPair.remoteM.ipAddrM.set(nscSrcAddr); 00480 00481 tcpEV << this << ": data arrived for interface of stack " 00482 << pStackM << "\n" << "src:"<< inetSockPair.remoteM.ipAddrM <<",dest:"<< inetSockPair.localM.ipAddrM <<"\n"; 00483 00484 nsc_iphdr *ih = (nsc_iphdr *)data; 00485 tcphdr *tcph = (tcphdr *)(data + ipHdrLen); 00486 // set IP header: 00487 ih->version = 4; 00488 ih->ihl = ipHdrLen/4; 00489 ih->tos = 0; 00490 ih->id = htons(tcpsegP->getSequenceNo()); 00491 ih->frag_off = htons(0x4000); // don't fragment, offset = 0; 00492 ih->ttl = 64; 00493 ih->protocol = 6; // TCP 00494 ih->check = 0; 00495 ih->saddr = htonl(nscSrcAddr); 00496 ih->daddr = htonl(localInnerIpS.get4().getInt()); 00497 00498 tcpEV << this << ": modified to: IP " << ih->version << " len " << ih->ihl 00499 << " protocol " << (unsigned int)(ih->protocol) 00500 << " saddr " << (ih->saddr) 00501 << " daddr " << (ih->daddr) 00502 << "\n"; 00503 00504 size_t totalTcpLen = maxBufferSize - ipHdrLen; 00505 TCP_NSC_Connection *conn; 00506 conn = findConnByInetSockPair(inetSockPair); 00507 if (!conn) 00508 conn = findConnByInetSockPair(inetSockPairAny); 00509 if(conn) 00510 { 00511 totalTcpLen = conn->receiveQueueM->insertBytesFromSegment(tcpsegP, (void *)tcph, totalTcpLen); 00512 } 00513 else 00514 { 00515 totalTcpLen = TCPSerializer().serialize(tcpsegP, (unsigned char *)tcph, totalTcpLen); 00516 //TODO the PayLoad data are destroyed... 00517 } 00518 00519 // calculate TCP checksum 00520 tcph->th_sum = 0; 00521 tcph->th_sum = TCPSerializer().checksum(tcph, totalTcpLen, nscSockPair.remoteM.ipAddrM, nscSockPair.localM.ipAddrM); 00522 00523 size_t totalIpLen = ipHdrLen + totalTcpLen; 00524 ih->tot_len = htons(totalIpLen); 00525 ih->check = 0; 00526 ih->check = TCPIPchecksum::checksum(ih, ipHdrLen); 00527 00528 decode_tcp( (void *)tcph, totalTcpLen); 00529 00530 // receive msg from network 00531 00532 pStackM->if_receive_packet(0, data, totalIpLen); 00533 00534 // Attempt to read from sockets 00535 TcpAppConnMap::iterator j; 00536 int changes = 0; 00537 for(j = tcpAppConnMapM.begin(); j != tcpAppConnMapM.end(); ++j) 00538 { 00539 TCP_NSC_Connection &c = j->second; 00540 00541 if(c.pNscSocketM && c.isListenerM) 00542 { 00543 // accepting socket 00544 tcpEV << this << ": NSC: attempting to accept:\n"; 00545 00546 INetStreamSocket *sock = NULL; 00547 int err; 00548 00549 err = c.pNscSocketM->accept( &sock ); 00550 00551 tcpEV << this << ": accept returned " << err << " , sock is " << sock 00552 << " socket" << c.pNscSocketM << "\n"; 00553 00554 if(sock) 00555 { 00556 ASSERT(changes == 0); 00557 ASSERT(c.inetSockPairM.localM.portM == inetSockPair.localM.portM); 00558 ++changes; 00559 00560 TCP_NSC_Connection *conn; 00561 int newConnId = ev.getUniqueNumber(); 00562 // add into appConnMap 00563 conn = &tcpAppConnMapM[newConnId]; 00564 conn->connIdM = newConnId; 00565 conn->appGateIndexM = c.appGateIndexM; 00566 conn->pNscSocketM = sock; 00567 00568 // set sockPairs: 00569 changeAddresses(*conn, inetSockPair, nscSockPair); 00570 00571 // following code to be kept consistent with initConnection() 00572 const char *sendQueueClass = c.sendQueueM->getClassName(); 00573 conn->sendQueueM = check_and_cast<TCP_NSC_SendQueue *>(createOne(sendQueueClass)); 00574 conn->sendQueueM->setConnection(conn); 00575 00576 const char *receiveQueueClass = c.receiveQueueM->getClassName(); 00577 conn->receiveQueueM = check_and_cast<TCP_NSC_ReceiveQueue *>(createOne(receiveQueueClass)); 00578 conn->receiveQueueM->setConnection(conn); 00579 tcpEV << this << ": NSC: got accept!\n"; 00580 00581 sendEstablishedMsg(*conn); 00582 } 00583 } 00584 else if(c.pNscSocketM && c.pNscSocketM->is_connected() ) // not listener 00585 { 00586 bool hasData = false; 00587 tcpEV << this << ": NSC: attempting to read from socket " << c.pNscSocketM << "\n"; 00588 00589 if ((!c.sentEstablishedM) && c.pNscSocketM->is_connected()) 00590 { 00591 ASSERT(changes == 0); 00592 hasData = true; 00593 changeAddresses(c, inetSockPair, nscSockPair); 00594 sendEstablishedMsg(c); 00595 } 00596 while(true) 00597 { 00598 static char buf[4096]; 00599 00600 int buflen = sizeof(buf); 00601 00602 int err = c.pNscSocketM->read_data(buf, &buflen); 00603 00604 tcpEV << this << ": NSC: read: err " << err << " , buflen " << buflen << "\n"; 00605 00606 if(err == 0 && buflen > 0) 00607 { 00608 ASSERT(changes == 0); 00609 if(!hasData) 00610 changeAddresses(c, inetSockPair, nscSockPair); 00611 00612 hasData = true; 00613 c.receiveQueueM->enqueueNscData(buf, buflen); 00614 /* 00615 struct sockaddr_in peerAddr,sockAddr; 00616 size_t peerAddrLen=sizeof(peerAddr),sockAddrLen=sizeof(sockAddr); 00617 c.pNscSocketM->getpeername((sockaddr*)&peerAddr, &peerAddrLen); 00618 c.pNscSocketM->getsockname((sockaddr*)&sockAddr, &sockAddrLen); 00619 */ 00620 } 00621 else 00622 break; 00623 } 00624 if(hasData) 00625 { 00626 while(cPacket *dataMsg = c.receiveQueueM->extractBytesUpTo()) 00627 { 00628 // send Msg to Application layer: 00629 send(dataMsg, "appOut", c.appGateIndexM); 00630 } 00631 ++changes; 00632 changeAddresses(c, inetSockPair, nscSockPair); 00633 } 00634 } 00635 } 00636 00637 /* 00638 ... 00639 NSC: process segment (data,len); should call removeConnection() if socket has 00640 closed and completely done 00641 00642 XXX: probably need to poll sockets to see if they are closed. 00643 ... 00644 */ 00645 00646 delete [] data; 00647 delete tcpsegP; 00648 } 00649 00650 void TCP_NSC::handleAppMessage(cMessage *msgP) 00651 { 00652 TCPCommand *controlInfo = check_and_cast<TCPCommand *>(msgP->getControlInfo()); 00653 int connId = controlInfo->getConnId(); 00654 00655 TCP_NSC_Connection *conn = findAppConn(connId); 00656 if (!conn) 00657 { 00658 TCPOpenCommand *openCmd = check_and_cast<TCPOpenCommand *>(controlInfo); 00659 // add into appConnMap 00660 conn = &tcpAppConnMapM[connId]; 00661 conn->connIdM = connId; 00662 conn->appGateIndexM = msgP->getArrivalGate()->getIndex(); 00663 conn->pNscSocketM = NULL; // will be filled in within processAppCommand() 00664 00665 // create send queue 00666 const char *sendQueueClass = openCmd->getSendQueueClass(); 00667 if (!sendQueueClass || !sendQueueClass[0]) 00668 sendQueueClass = this->par("sendQueueClass"); 00669 conn->sendQueueM = check_and_cast<TCP_NSC_SendQueue *>(createOne(sendQueueClass)); 00670 conn->sendQueueM->setConnection(conn); 00671 00672 // create receive queue 00673 const char *receiveQueueClass = openCmd->getReceiveQueueClass(); 00674 if (!receiveQueueClass || !receiveQueueClass[0]) 00675 receiveQueueClass = this->par("receiveQueueClass"); 00676 conn->receiveQueueM = check_and_cast<TCP_NSC_ReceiveQueue *>(createOne(receiveQueueClass)); 00677 conn->receiveQueueM->setConnection(conn); 00678 00679 tcpEV << this << ": TCP connection created for " << msgP << "\n"; 00680 } 00681 processAppCommand(*conn, msgP); 00682 } 00683 00684 void TCP_NSC::handleMessage(cMessage *msgP) 00685 { 00686 if (msgP->isSelfMessage()) 00687 { 00688 // timer expired 00689 /* 00690 ... 00691 NSC timer processing 00692 ... 00693 Timers are ordinary cMessage objects that are started by 00694 scheduleAt(simTime()+timeout, msg), and can be cancelled 00695 via cancelEvent(msg); when they expire (fire) they are delivered 00696 to the module via handleMessage(), i.e. they end up here. 00697 */ 00698 if(msgP == pNsiTimerM ) 00699 { // nsc_nsi_timer 00700 do_SEND_all(); 00701 00702 pStackM->increment_ticks(); 00703 00704 pStackM->timer_interrupt(); 00705 00706 scheduleAt(msgP->getArrivalTime() + 1.0 / (double)pStackM->get_hz(), msgP); 00707 } 00708 } 00709 else if (msgP->arrivedOn("ipIn") || msgP->arrivedOn("ipv6In")) 00710 { 00711 tcpEV << this << ": handle msg: " << msgP->getName() << "\n"; 00712 // must be a TCPSegment 00713 TCPSegment *tcpseg = check_and_cast<TCPSegment *>(msgP); 00714 handleIpInputMessage(tcpseg); 00715 00716 } 00717 else // must be from app 00718 { 00719 tcpEV << this << ": handle msg: " << msgP->getName() << "\n"; 00720 handleAppMessage(msgP); 00721 } 00722 00723 if (ev.isGUI()) 00724 updateDisplayString(); 00725 } 00726 00727 void TCP_NSC::updateDisplayString() 00728 { 00729 //... 00730 } 00731 00732 TCP_NSC_Connection *TCP_NSC::findAppConn(int connIdP) 00733 { 00734 TcpAppConnMap::iterator i = tcpAppConnMapM.find(connIdP); 00735 return i==tcpAppConnMapM.end() ? NULL : &(i->second); 00736 } 00737 00738 TCP_NSC_Connection *TCP_NSC::findConnByInetSockPair(TCP_NSC_Connection::SockPair const & sockPairP) 00739 { 00740 SockPair2ConnIdMap::iterator i = inetSockPair2ConnIdMapM.find(sockPairP); 00741 return i==inetSockPair2ConnIdMapM.end() ? NULL : findAppConn(i->second); 00742 } 00743 00744 TCP_NSC_Connection *TCP_NSC::findConnByNscSockPair(TCP_NSC_Connection::SockPair const & sockPairP) 00745 { 00746 SockPair2ConnIdMap::iterator i = nscSockPair2ConnIdMapM.find(sockPairP); 00747 return i==nscSockPair2ConnIdMapM.end() ? NULL : findAppConn(i->second); 00748 } 00749 00750 void TCP_NSC::finish() 00751 { 00752 isAliveM = false; 00753 } 00754 00755 void TCP_NSC::removeConnection(int connIdP) 00756 { 00757 TcpAppConnMap::iterator i = tcpAppConnMapM.find(connIdP); 00758 if (i != tcpAppConnMapM.end()) 00759 tcpAppConnMapM.erase(i); 00760 } 00761 00762 void TCP_NSC::printConnBrief(TCP_NSC_Connection& connP) 00763 { 00764 tcpEV << this << ": connId=" << connP.connIdM << " appGateIndex=" << connP.appGateIndexM; 00765 tcpEV << " nscsocket=" << connP.pNscSocketM << "\n"; 00766 } 00767 00768 void TCP_NSC::loadStack(const char* stacknameP, int bufferSizeP) 00769 { 00770 void *handle = NULL; 00771 FCreateStack create = NULL; 00772 00773 tcpEV << this << ": Loading stack " << stacknameP << "\n"; 00774 00775 handle = dlopen(stacknameP, RTLD_NOW); 00776 if(!handle) { 00777 fputs("The loading of NSC stack is unsuccessful: ", stderr); 00778 fputs(dlerror(), stderr); 00779 fputs("\nCheck the LD_LIBRARY_PATH or stackname!\n", stderr); 00780 exit(1); 00781 } 00782 00783 create = (FCreateStack)dlsym(handle, "nsc_create_stack"); 00784 if(!create) { 00785 fputs(dlerror(), stderr); 00786 fputs("\n", stderr); 00787 exit(1); 00788 } 00789 00790 pStackM = create(this, this, NULL); 00791 00792 tcpEV << "TCP_NSC " << this << " has stack " << pStackM << "\n"; 00793 00794 fprintf(stderr, "Created stack = %p\n", pStackM); 00795 00796 fprintf(stderr, "Initialising stack, name=%s\n", pStackM->get_name()); 00797 00798 pStackM->init(pStackM->get_hz()); 00799 00800 pStackM->buffer_size(bufferSizeP); 00801 00802 fprintf(stderr, "done.\n"); 00803 00804 // set timer for 1.0 / pStackM->get_hz() 00805 pNsiTimerM = new cMessage("nsc_nsi_timer"); 00806 scheduleAt(1.0 / (double)pStackM->get_hz(), pNsiTimerM); 00807 } 00808 00810 void TCP_NSC::send_callback(const void *dataP, int datalenP) 00811 { 00812 if(!isAliveM) 00813 return; 00814 tcpEV << this << ": NSC: send_callback(" << dataP << ", " << datalenP << ") called\n"; 00815 00816 sendToIP(dataP, datalenP); 00817 00818 // comment from nsc.cc: 00819 // New method: if_send_finish. This should be called by the nic 00820 // driver code when there is space in it's queue. Unfortunately 00821 // we don't know whether that is the case from here, so we just 00822 // call it immediately for now. **THIS IS INCORRECT**. It should 00823 // only be called when a space becomes free in the nic queue. 00824 pStackM->if_send_finish(0); // XXX: hardcoded inerface id 00825 } 00826 00827 /* 00828 void TCP_NSC::interrupt() 00829 { 00830 } 00831 */ 00832 00844 void TCP_NSC::wakeup() 00845 { 00846 if(!isAliveM) 00847 return; 00848 tcpEV << this << ": wakeup() called\n"; 00849 } 00850 00851 void TCP_NSC::gettime(unsigned int *secP, unsigned int *usecP) 00852 { 00853 #if OMNETPP_VERSION < 0x0400 00854 simtime_t t = simTime(); 00855 *sec = (unsigned int)(t); 00856 *usec = (unsigned int)((t - *sec) * 1000000 + 0.5); 00857 #else 00858 #ifdef USE_DOUBLE_SIMTIME 00859 double t = simTime().dbl(); 00860 *sec = (unsigned int)(t); 00861 *usec = (unsigned int)((t - *sec) * 1000000 + 0.5); 00862 #else 00863 simtime_t t = simTime(); 00864 int64 raw = t.raw(); 00865 int64 scale = t.getScale(); 00866 int64 secs = raw / scale; 00867 int64 usecs = (raw - (secs * scale)); 00868 //usecs = usecs * 1000000 / scale; 00869 if(scale>1000000) // scale always 10^n 00870 usecs /= (scale / 1000000); 00871 else 00872 usecs *= (1000000 / scale); 00873 *secP = secs; 00874 *usecP = usecs; 00875 #endif 00876 #endif 00877 tcpEV << this << ": gettime(" << *secP << "," << *usecP << ") called\n"; 00878 } 00879 00880 void TCP_NSC::sendToIP(const void *dataP, int lenP) 00881 { 00882 IPvXAddress src,dest; 00883 const nsc_iphdr *iph = (const nsc_iphdr *)dataP; 00884 00885 int ipHdrLen = 4 * iph->ihl; 00886 ASSERT(ipHdrLen <= lenP); 00887 int totalLen = ntohs(iph->tot_len); 00888 ASSERT(totalLen == lenP); 00889 tcphdr const *tcph = (tcphdr const*)(((const char *)(iph)) + ipHdrLen); 00890 00891 // XXX add some info (seqNo, len, etc) 00892 00893 TCP_NSC_Connection::SockPair nscSockPair; 00894 00895 TCP_NSC_Connection *conn; 00896 00897 nscSockPair.localM.ipAddrM.set(ntohl(iph->saddr)); 00898 nscSockPair.localM.portM = ntohs(tcph->th_sport); 00899 nscSockPair.remoteM.ipAddrM.set(ntohl(iph->daddr)); 00900 nscSockPair.remoteM.portM = ntohs(tcph->th_dport); 00901 00902 if(curConnM) 00903 { 00904 changeAddresses(*curConnM, curConnM->inetSockPairM, nscSockPair); 00905 conn = curConnM; 00906 } 00907 else 00908 { 00909 conn = findConnByNscSockPair(nscSockPair); 00910 } 00911 00912 TCPSegment *tcpseg; 00913 if(conn) 00914 { 00915 tcpseg = conn->sendQueueM->createSegmentWithBytes(tcph, totalLen-ipHdrLen); 00916 src = conn->inetSockPairM.localM.ipAddrM; 00917 dest = conn->inetSockPairM.remoteM.ipAddrM; 00918 } 00919 else 00920 { 00921 tcpseg = new TCPSegment("tcp-segment"); 00922 00923 TCPSerializer().parse((const unsigned char *)tcph, totalLen-ipHdrLen, tcpseg); 00924 dest = mapNsc2Remote(ntohl(iph->daddr)); 00925 } 00926 ASSERT(tcpseg); 00927 00928 tcpEV << this << ": Sending: conn=" << conn << ", data: " << dataP << " of len " << lenP << " from " << src 00929 << " to " << dest << "\n"; 00930 00931 const char* output; 00932 if (!dest.isIPv6()) 00933 { 00934 // send over IPv4 00935 IPControlInfo *controlInfo = new IPControlInfo(); 00936 controlInfo->setProtocol(IP_PROT_TCP); 00937 controlInfo->setSrcAddr(src.get4()); 00938 controlInfo->setDestAddr(dest.get4()); 00939 tcpseg->setControlInfo(controlInfo); 00940 00941 output = "ipOut"; 00942 } 00943 else 00944 { 00945 // send over IPv6 00946 IPv6ControlInfo *controlInfo = new IPv6ControlInfo(); 00947 controlInfo->setProtocol(IP_PROT_TCP); 00948 controlInfo->setSrcAddr(src.get6()); 00949 controlInfo->setDestAddr(dest.get6()); 00950 tcpseg->setControlInfo(controlInfo); 00951 00952 output ="ipv6Out"; 00953 } 00954 if(conn) 00955 { 00956 conn->receiveQueueM->notifyAboutSending(tcpseg); 00957 } 00958 00959 // record seq (only if we do send data) and ackno 00960 if (sndNxtVector && tcpseg->getPayloadLength()!=0) 00961 sndNxtVector->record(tcpseg->getSequenceNo()); 00962 if (sndAckVector) 00963 sndAckVector->record(tcpseg->getAckNo()); 00964 00965 send(tcpseg, output); 00966 } 00967 00968 void TCP_NSC::processAppCommand(TCP_NSC_Connection& connP, cMessage *msgP) 00969 { 00970 printConnBrief(connP); 00971 00972 // first do actions 00973 TCPCommand *tcpCommand = (TCPCommand *)(msgP->removeControlInfo()); 00974 00975 switch (msgP->getKind()) 00976 { 00977 case TCP_C_OPEN_ACTIVE: process_OPEN_ACTIVE(connP, tcpCommand, msgP); break; 00978 case TCP_C_OPEN_PASSIVE: process_OPEN_PASSIVE(connP, tcpCommand, msgP); break; 00979 case TCP_C_SEND: process_SEND(connP, tcpCommand, check_and_cast<cPacket*>(msgP)); break; 00980 case TCP_C_CLOSE: process_CLOSE(connP, tcpCommand, msgP); break; 00981 case TCP_C_ABORT: process_ABORT(connP, tcpCommand, msgP); break; 00982 case TCP_C_STATUS: process_STATUS(connP, tcpCommand, msgP); break; 00983 default: opp_error("wrong command from app: %d", msgP->getKind()); 00984 } 00985 00986 /* 00987 ... 00988 NSC: should call removeConnection(connP.connIdM) if socket has been destroyed 00989 ... 00990 */ 00991 } 00992 00993 void TCP_NSC::process_OPEN_ACTIVE(TCP_NSC_Connection& connP, TCPCommand *tcpCommandP, cMessage *msgP) 00994 { 00995 TCPOpenCommand *openCmd = check_and_cast<TCPOpenCommand *>(tcpCommandP); 00996 00997 TCP_NSC_Connection::SockPair inetSockPair,nscSockPair; 00998 inetSockPair.localM.ipAddrM = openCmd->getLocalAddr(); 00999 inetSockPair.remoteM.ipAddrM = openCmd->getRemoteAddr(); 01000 inetSockPair.localM.portM = openCmd->getLocalPort(); 01001 inetSockPair.remoteM.portM = openCmd->getRemotePort(); 01002 01003 if (inetSockPair.remoteM.ipAddrM.isUnspecified() || inetSockPair.remoteM.portM == -1) 01004 opp_error("Error processing command OPEN_ACTIVE: remote address and port must be specified"); 01005 01006 tcpEV << this << ": OPEN: " 01007 << inetSockPair.localM.ipAddrM << ":" << inetSockPair.localM.portM << " --> " 01008 << inetSockPair.remoteM.ipAddrM << ":" << inetSockPair.remoteM.portM << "\n"; 01009 01010 // insert to map: 01011 uint32_t nscRemoteAddr = mapRemote2Nsc(inetSockPair.remoteM.ipAddrM); 01012 01013 ASSERT(pStackM); 01014 01015 nscSockPair.localM.portM = inetSockPair.localM.portM; 01016 if (nscSockPair.localM.portM == -1) 01017 nscSockPair.localM.portM = 0; // NSC uses 0 to mean "not specified" 01018 nscSockPair.remoteM.ipAddrM.set(nscRemoteAddr); 01019 nscSockPair.remoteM.portM = inetSockPair.remoteM.portM; 01020 01021 changeAddresses(connP, inetSockPair, nscSockPair); 01022 01023 ASSERT(!curConnM); 01024 curConnM = &connP; 01025 connP.connect(*pStackM, inetSockPair, nscSockPair); 01026 curConnM = NULL; 01027 01028 // and add to map: 01029 // TODO sendToIp already set the addresses. 01030 //changeAddresses(connP, inetSockPair, nscSockPair); 01031 01032 delete tcpCommandP; 01033 delete msgP; 01034 } 01035 01036 void TCP_NSC::process_OPEN_PASSIVE(TCP_NSC_Connection& connP, TCPCommand *tcpCommandP, cMessage *msgP) 01037 { 01038 ASSERT(pStackM); 01039 01040 TCPOpenCommand *openCmd = check_and_cast<TCPOpenCommand *>(tcpCommandP); 01041 01042 ASSERT(openCmd->getFork()==true); 01043 01044 TCP_NSC_Connection::SockPair inetSockPair, nscSockPair; 01045 inetSockPair.localM.ipAddrM = openCmd->getLocalAddr(); 01046 inetSockPair.remoteM.ipAddrM = openCmd->getRemoteAddr(); 01047 inetSockPair.localM.portM = openCmd->getLocalPort(); 01048 inetSockPair.remoteM.portM = openCmd->getRemotePort(); 01049 01050 uint32_t nscRemoteAddr = inetSockPair.remoteM.ipAddrM.isUnspecified() 01051 ? ntohl(INADDR_ANY) 01052 : mapRemote2Nsc(inetSockPair.remoteM.ipAddrM); // Don't remove! It's insert remoteAddr into MAP. 01053 (void)nscRemoteAddr; // Eliminate "unused variable" warning. 01054 01055 if (inetSockPair.localM.portM == -1) 01056 opp_error("Error processing command OPEN_PASSIVE: local port must be specified"); 01057 01058 tcpEV << this << "Starting to listen on: " << inetSockPair.localM.ipAddrM << ":" << inetSockPair.localM.portM << "\n"; 01059 01060 /* 01061 ... 01062 NSC: process passive open request 01063 ... 01064 */ 01065 nscSockPair.localM.portM = inetSockPair.localM.portM; 01066 01067 changeAddresses(connP, inetSockPair, nscSockPair); 01068 01069 ASSERT(!curConnM); 01070 curConnM = &connP; 01071 connP.listen(*pStackM, inetSockPair, nscSockPair); 01072 curConnM = NULL; 01073 01074 changeAddresses(connP, inetSockPair, nscSockPair); 01075 01076 delete openCmd; 01077 delete msgP; 01078 } 01079 01080 void TCP_NSC::process_SEND(TCP_NSC_Connection& connP, TCPCommand *tcpCommandP, cPacket *msgP) 01081 { 01082 TCPSendCommand *sendCommand = check_and_cast<TCPSendCommand *>(tcpCommandP); 01083 delete sendCommand; 01084 01085 connP.send(msgP); 01086 01087 connP.do_SEND(); 01088 } 01089 01090 void TCP_NSC::do_SEND_all() 01091 { 01092 TcpAppConnMap::iterator j = tcpAppConnMapM.begin(); 01093 for(; j != tcpAppConnMapM.end(); ++j) 01094 { 01095 TCP_NSC_Connection& conn = j->second; 01096 conn.do_SEND(); 01097 } 01098 } 01099 01100 void TCP_NSC::process_CLOSE(TCP_NSC_Connection& connP, TCPCommand *tcpCommandP, cMessage *msgP) 01101 { 01102 tcpEV << this << ": process_CLOSE()\n"; 01103 01104 delete tcpCommandP; 01105 delete msgP; 01106 01107 connP.close(); 01108 } 01109 01110 void TCP_NSC::process_ABORT(TCP_NSC_Connection& connP, TCPCommand *tcpCommandP, cMessage *msgP) 01111 { 01112 tcpEV << this << ": process_ABORT()\n"; 01113 01114 delete tcpCommandP; 01115 delete msgP; 01116 01117 connP.abort(); 01118 } 01119 01120 void TCP_NSC::process_STATUS(TCP_NSC_Connection& connP, TCPCommand *tcpCommandP, cMessage *msgP) 01121 { 01122 delete tcpCommandP; // but we'll reuse msg for reply 01123 01124 TCPStatusInfo *statusInfo = new TCPStatusInfo(); 01125 01126 /* 01127 ... 01128 NSC: fill in status if possible 01129 01130 Still more work to do here. Some of this needs to be implemented on 01131 the NSC side, which is fairly trivial, just updating the get_var 01132 function for each stack. 01133 ... 01134 */ 01135 01136 char result[512]; 01137 01138 ASSERT(connP.pNscSocketM); 01139 01140 connP.pNscSocketM->get_var("cwnd_", result, sizeof(result)); 01141 statusInfo->setSnd_wnd(atoi(result)); 01142 01143 //connP.pNscSocketM->get_var("ssthresh_", result, sizeof(result)); 01144 //connP.pNscSocketM->get_var("rxtcur_", result, sizeof(result)); 01145 01146 01147 /* other TCP model: 01148 statusInfo->setState(fsm.getState()); 01149 statusInfo->setStateName(stateName(fsm.getState())); 01150 01151 statusInfo->setLocalAddr(localAddr); 01152 statusInfo->setRemoteAddr(remoteAddr); 01153 statusInfo->setLocalPort(localPort); 01154 statusInfo->setRemotePort(remotePort); 01155 01156 statusInfo->setSnd_mss(state->snd_mss); 01157 statusInfo->setSnd_una(state->snd_una); 01158 statusInfo->setSnd_nxt(state->snd_nxt); 01159 statusInfo->setSnd_max(state->snd_max); 01160 statusInfo->setSnd_wnd(state->snd_wnd); 01161 statusInfo->setSnd_up(state->snd_up); 01162 statusInfo->setSnd_wl1(state->snd_wl1); 01163 statusInfo->setSnd_wl2(state->snd_wl2); 01164 statusInfo->setIss(state->iss); 01165 statusInfo->setRcv_nxt(state->rcv_nxt); 01166 statusInfo->setRcv_wnd(state->rcv_wnd); 01167 statusInfo->setRcv_up(state->rcv_up); 01168 statusInfo->setIrs(state->irs); 01169 statusInfo->setFin_ack_rcvd(state->fin_ack_rcvd); 01170 */ 01171 01172 msgP->setControlInfo(statusInfo); 01173 send(msgP, "appOut", connP.appGateIndexM); 01174 } 01175 01176 #endif // WITH_TCP_NSC