TCP_NSC.cc

Go to the documentation of this file.
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 
00257         tcpEV << this << ": " << ("Options: ");
00258         while(
00259                 (*opt != 0) &&
00260                 ((unsigned int)opt < (unsigned int)packet_data + tcp->th_offs*4)
00261              )
00262         {
00263             unsigned char len = opt[1];
00264             if(len == 0 && opt[0] != 1)
00265             {
00266                 sprintf(buf, "0-length option(%u)\n", opt[0]);
00267                 tcpEV << this << ": " << buf;
00268                 break;
00269             }
00270 
00271             len -= 2;
00272 
00273             switch(*opt)
00274             {
00275                 case 1: tcpEV << ("No-Op "); opt++; break;
00276                 case 2: {       unsigned short mss = 0;
00277                             //assert(len == 2);
00278                             if(len == 2) {
00279                                 mss = (opt[2] << 8) + (opt[3]);
00280                                 sprintf(buf, "MSS(%u) ", mss);
00281                                 tcpEV << buf;
00282                             } else {
00283                                 sprintf(buf, "MSS:l:%u ", len);
00284                                 tcpEV << buf;
00285                             }
00286                             opt += opt[1];
00287                             break;
00288                         }
00289                 case 3: {
00290                             unsigned char ws = 0;
00291                             ASSERT(len == 1);
00292                             ws = opt[2];
00293                             sprintf(buf, "WS(%u) ", ws);
00294                             tcpEV << buf;
00295                             opt += opt[1];
00296                             break;
00297                         }
00298                 case 4: {
00299                             sprintf(buf, "SACK-Permitted ");
00300                             tcpEV << buf;
00301                             opt += opt[1];
00302                             break;
00303                         }
00304                 case 5: {
00305                             tcpEV << ("SACK ");
00306                             opt += opt[1];
00307                             break;
00308                         }
00309                 case 8: {
00310                             int i;
00311                             tcpEV << ("Timestamp(");
00312                             for(i = 0; i < len; i++) {
00313                                 sprintf(buf, "%02x", opt[2+i]);
00314                                 tcpEV << buf;
00315                             }
00316                             tcpEV << (") ");
00317                             opt += opt[1];
00318                             break;
00319                         }
00320                 default:{
00321                             sprintf(buf, "%u:%u ", opt[0], opt[1]);
00322                             tcpEV << buf;
00323                             opt += opt[1];
00324                             break;
00325                         }
00326             };
00327 
00328         }
00329         tcpEV << ("\n");
00330     }
00331 
00332 }
00333 
00334 void TCP_NSC::initialize()
00335 {
00336     tcpEV << this << ": initialize\n";
00337     WATCH_MAP(tcpAppConnMapM);
00338 
00339     cModule *netw = simulation.getSystemModule();
00340     testingS = netw->hasPar("testing") && netw->par("testing").boolValue();
00341     logverboseS = !testingS && netw->hasPar("logverbose") && netw->par("logverbose").boolValue();
00342 
00343     const char* stackName = this->par(stackNameParamNameS).stringValue();
00344 
00345     int bufferSize = (int)(this->par(bufferSizeParamNameS).longValue());
00346 
00347     loadStack(stackName, bufferSize);
00348     pStackM->if_attach(localInnerIpS.str().c_str(), localInnerMaskS.str().c_str(), 1500);
00349     pStackM->add_default_gateway(localInnerGwS.str().c_str());
00350 
00351     isAliveM = true;
00352 }
00353 
00354 TCP_NSC::~TCP_NSC()
00355 {
00356     tcpEV << this << ": destructor\n";
00357     isAliveM = false;
00358     while (!tcpAppConnMapM.empty())
00359     {
00360         TcpAppConnMap::iterator i = tcpAppConnMapM.begin();
00361         delete (*i).second.pNscSocketM;
00362         tcpAppConnMapM.erase(i);
00363     }
00364 
00365     // statistics
00366     delete sndWndVector;
00367     delete rcvWndVector;
00368     delete rcvAdvVector;
00369     delete sndNxtVector;
00370     delete sndAckVector;
00371     delete rcvSeqVector;
00372     delete rcvAckVector;
00373     delete unackedVector;
00374     delete dupAcksVector;
00375     delete sndSacksVector;
00376     delete rcvSacksVector;
00377     delete rcvOooSegVector;
00378     delete tcpRcvQueueBytesVector;
00379     delete tcpRcvQueueDropsVector;
00380     delete pipeVector;
00381     delete sackedBytesVector;
00382 }
00383 
00384 // send a TCP_I_ESTABLISHED msg to Application Layer
00385 void TCP_NSC::sendEstablishedMsg(TCP_NSC_Connection &connP)
00386 {
00387 
00388     cMessage *msg = connP.createEstablishedMsg();
00389     if(msg)
00390     {
00391         send(msg, "appOut", connP.appGateIndexM);
00392         connP.sentEstablishedM = true;
00393     }
00394 }
00395 
00396 void TCP_NSC::changeAddresses(TCP_NSC_Connection &connP,
00397         const TCP_NSC_Connection::SockPair &inetSockPairP,
00398         const TCP_NSC_Connection::SockPair &nscSockPairP)
00399 {
00400     if (!(connP.inetSockPairM == inetSockPairP))
00401     {
00402         tcpEV << "conn:" << connP << " change inetMap from " << connP.inetSockPairM << " to " << inetSockPairP << "\n";
00403         inetSockPair2ConnIdMapM.erase(connP.inetSockPairM);
00404         connP.inetSockPairM = inetSockPairP;
00405         inetSockPair2ConnIdMapM[connP.inetSockPairM] = connP.connIdM;
00406     }
00407     if (!(connP.nscSockPairM == nscSockPairP))
00408     {
00409         tcpEV << "conn:" << connP << " change nscMap from " << connP.nscSockPairM << " to " << nscSockPairP << "\n";
00410         // remove old from map:
00411         nscSockPair2ConnIdMapM.erase(connP.nscSockPairM);
00412         // change addresses:
00413         connP.nscSockPairM = nscSockPairP;
00414         // and add to map:
00415         nscSockPair2ConnIdMapM[connP.nscSockPairM] = connP.connIdM;
00416     }
00417 }
00418 
00419 void TCP_NSC::handleIpInputMessage(TCPSegment* tcpsegP)
00420 {
00421     // get src/dest addresses
00422     TCP_NSC_Connection::SockPair nscSockPair, inetSockPair, inetSockPairAny;
00423 
00424     if (dynamic_cast<IPControlInfo *>(tcpsegP->getControlInfo())!=NULL)
00425     {
00426         IPControlInfo *controlInfo = (IPControlInfo *)tcpsegP->removeControlInfo();
00427         inetSockPair.remoteM.ipAddrM = controlInfo->getSrcAddr();
00428         inetSockPair.localM.ipAddrM = controlInfo->getDestAddr();
00429         delete controlInfo;
00430     }
00431     else if (dynamic_cast<IPv6ControlInfo *>(tcpsegP->getControlInfo())!=NULL)
00432     {
00433         IPv6ControlInfo *controlInfo = (IPv6ControlInfo *)tcpsegP->removeControlInfo();
00434         inetSockPair.remoteM.ipAddrM = controlInfo->getSrcAddr();
00435         inetSockPair.localM.ipAddrM = controlInfo->getDestAddr();
00436         delete controlInfo;
00437         {
00438             // HACK: when IPv6, then correcting the TCPOPTION_MAXIMUM_SEGMENT_SIZE option
00439             //       with IP header size difference
00440             unsigned short numOptions = tcpsegP->getOptionsArraySize();
00441             for (unsigned short i=0; i < numOptions; i++)
00442             {
00443                 TCPOption& option = tcpsegP->getOptions(i);
00444                 if(option.getKind() == TCPOPTION_MAXIMUM_SEGMENT_SIZE)
00445                 {
00446                     unsigned int value = option.getValues(0);
00447                     value -= sizeof(struct nsc_ipv6hdr) - sizeof(struct nsc_iphdr);
00448                     option.setValues(0, value);
00449                     //tcpsegP->setOptions(i, option);
00450                 }
00451             }
00452         }
00453     }
00454     else
00455     {
00456         error("(%s)%s arrived without control info", tcpsegP->getClassName(), tcpsegP->getName());
00457     }
00458 
00459     // statistics:
00460     if (rcvSeqVector)
00461         rcvSeqVector->record(tcpsegP->getSequenceNo());
00462     if (rcvAckVector)
00463         rcvAckVector->record(tcpsegP->getAckNo());
00464 
00465     inetSockPair.remoteM.portM = tcpsegP->getSrcPort();
00466     inetSockPair.localM.portM = tcpsegP->getDestPort();
00467     nscSockPair.remoteM.portM = tcpsegP->getSrcPort();
00468     nscSockPair.localM.portM = tcpsegP->getDestPort();
00469     inetSockPairAny.localM = inetSockPair.localM;
00470 
00471     // process segment
00472     size_t ipHdrLen = sizeof(nsc_iphdr);
00473     size_t const maxBufferSize = 4096;
00474     char *data = new char[maxBufferSize];
00475     memset(data, 0, maxBufferSize);
00476     uint32_t nscSrcAddr = mapRemote2Nsc(inetSockPair.remoteM.ipAddrM);
00477     nscSockPair.localM.ipAddrM = localInnerIpS;
00478     nscSockPair.remoteM.ipAddrM.set(nscSrcAddr);
00479 
00480     tcpEV << this << ": data arrived for interface of stack "
00481         << pStackM << "\n" << "src:"<< inetSockPair.remoteM.ipAddrM <<",dest:"<< inetSockPair.localM.ipAddrM <<"\n";
00482 
00483     nsc_iphdr *ih = (nsc_iphdr *)data;
00484     tcphdr *tcph = (tcphdr *)(data + ipHdrLen);
00485     // set IP header:
00486     ih->version = 4;
00487     ih->ihl = ipHdrLen/4;
00488     ih->tos = 0;
00489     ih->id = htons(tcpsegP->getSequenceNo());
00490     ih->frag_off = htons(0x4000);   // don't fragment, offset = 0;
00491     ih->ttl = 64;
00492     ih->protocol = 6;       // TCP
00493     ih->check = 0;
00494     ih->saddr = htonl(nscSrcAddr);
00495     ih->daddr = htonl(localInnerIpS.get4().getInt());
00496 
00497     tcpEV << this << ": modified to: IP " << ih->version << " len " << ih->ihl
00498           << " protocol " << (unsigned int)(ih->protocol)
00499           << " saddr " << (ih->saddr)
00500           << " daddr " << (ih->daddr)
00501           << "\n";
00502 
00503     size_t totalTcpLen = maxBufferSize - ipHdrLen;
00504     TCP_NSC_Connection *conn;
00505     conn = findConnByInetSockPair(inetSockPair);
00506     if (!conn)
00507         conn = findConnByInetSockPair(inetSockPairAny);
00508     if(conn)
00509     {
00510         totalTcpLen = conn->receiveQueueM->insertBytesFromSegment(tcpsegP, (void *)tcph, totalTcpLen);
00511     }
00512     else
00513     {
00514         totalTcpLen = TCPSerializer().serialize(tcpsegP, (unsigned char *)tcph, totalTcpLen);
00515         //TODO the PayLoad data are destroyed...
00516     }
00517 
00518     // calculate TCP checksum
00519     tcph->th_sum = 0;
00520     tcph->th_sum = TCPSerializer().checksum(tcph, totalTcpLen, nscSockPair.remoteM.ipAddrM, nscSockPair.localM.ipAddrM);
00521 
00522     size_t totalIpLen = ipHdrLen + totalTcpLen;
00523     ih->tot_len = htons(totalIpLen);
00524     ih->check = 0;
00525     ih->check = TCPIPchecksum::checksum(ih, ipHdrLen);
00526 
00527     decode_tcp( (void *)tcph, totalTcpLen);
00528 
00529     // receive msg from network
00530 
00531     pStackM->if_receive_packet(0, data, totalIpLen);
00532 
00533     // Attempt to read from sockets
00534     TcpAppConnMap::iterator j;
00535     int changes = 0;
00536     for(j = tcpAppConnMapM.begin(); j != tcpAppConnMapM.end(); ++j)
00537     {
00538         TCP_NSC_Connection &c = j->second;
00539 
00540         if(c.pNscSocketM && c.isListenerM)
00541         {
00542             // accepting socket
00543             tcpEV << this << ": NSC: attempting to accept:\n";
00544 
00545             INetStreamSocket *sock = NULL;
00546             int err;
00547 
00548             err = c.pNscSocketM->accept( &sock );
00549 
00550             tcpEV << this << ": accept returned " << err << " , sock is " << sock
00551                 << " socket" << c.pNscSocketM << "\n";
00552 
00553             if(sock)
00554             {
00555                 ASSERT(changes == 0);
00556                 ASSERT(c.inetSockPairM.localM.portM == inetSockPair.localM.portM);
00557                 ++changes;
00558 
00559                 TCP_NSC_Connection *conn;
00560                 int newConnId = ev.getUniqueNumber();
00561                 // add into appConnMap
00562                 conn = &tcpAppConnMapM[newConnId];
00563                 conn->connIdM = newConnId;
00564                 conn->appGateIndexM = c.appGateIndexM;
00565                 conn->pNscSocketM = sock;
00566 
00567                 // set sockPairs:
00568                 changeAddresses(*conn, inetSockPair, nscSockPair);
00569 
00570                 // following code to be kept consistent with initConnection()
00571                 const char *sendQueueClass = c.sendQueueM->getClassName();
00572                 conn->sendQueueM = check_and_cast<TCP_NSC_SendQueue *>(createOne(sendQueueClass));
00573                 conn->sendQueueM->setConnection(conn);
00574 
00575                 const char *receiveQueueClass = c.receiveQueueM->getClassName();
00576                 conn->receiveQueueM = check_and_cast<TCP_NSC_ReceiveQueue *>(createOne(receiveQueueClass));
00577                 conn->receiveQueueM->setConnection(conn);
00578                 tcpEV << this << ": NSC: got accept!\n";
00579 
00580                 sendEstablishedMsg(*conn);
00581             }
00582         }
00583         else if(c.pNscSocketM && c.pNscSocketM->is_connected() ) // not listener
00584         {
00585             bool hasData = false;
00586             tcpEV << this << ": NSC: attempting to read from socket " << c.pNscSocketM << "\n";
00587 
00588             if ((!c.sentEstablishedM) && c.pNscSocketM->is_connected())
00589             {
00590                 ASSERT(changes == 0);
00591                 hasData = true;
00592                 changeAddresses(c, inetSockPair, nscSockPair);
00593                 sendEstablishedMsg(c);
00594             }
00595             while(true)
00596             {
00597                 static char buf[4096];
00598 
00599                 int buflen = sizeof(buf);
00600 
00601                 int err = c.pNscSocketM->read_data(buf, &buflen);
00602 
00603                 tcpEV << this << ": NSC: read: err " << err << " , buflen " << buflen << "\n";
00604 
00605                 if(err == 0 && buflen > 0)
00606                 {
00607                     ASSERT(changes == 0);
00608                     if(!hasData)
00609                         changeAddresses(c, inetSockPair, nscSockPair);
00610 
00611                     hasData = true;
00612                     c.receiveQueueM->enqueueNscData(buf, buflen);
00613 /*
00614                     struct sockaddr_in peerAddr,sockAddr;
00615                     size_t peerAddrLen=sizeof(peerAddr),sockAddrLen=sizeof(sockAddr);
00616                     c.pNscSocketM->getpeername((sockaddr*)&peerAddr, &peerAddrLen);
00617                     c.pNscSocketM->getsockname((sockaddr*)&sockAddr, &sockAddrLen);
00618 */
00619                 }
00620                 else
00621                     break;
00622             }
00623             if(hasData)
00624             {
00625                 while(cPacket *dataMsg = c.receiveQueueM->extractBytesUpTo())
00626                 {
00627                     // send Msg to Application layer:
00628                     send(dataMsg, "appOut", c.appGateIndexM);
00629                 }
00630                 ++changes;
00631                 changeAddresses(c, inetSockPair, nscSockPair);
00632             }
00633         }
00634     }
00635 
00636     /*
00637     ...
00638     NSC: process segment (data,len); should call removeConnection() if socket has
00639     closed and completely done
00640 
00641     XXX: probably need to poll sockets to see if they are closed.
00642     ...
00643     */
00644 
00645     delete [] data;
00646     delete tcpsegP;
00647 }
00648 
00649 void TCP_NSC::handleAppMessage(cMessage *msgP)
00650 {
00651     TCPCommand *controlInfo = check_and_cast<TCPCommand *>(msgP->getControlInfo());
00652     int connId = controlInfo->getConnId();
00653 
00654     TCP_NSC_Connection *conn = findAppConn(connId);
00655     if (!conn)
00656     {
00657         TCPOpenCommand *openCmd = check_and_cast<TCPOpenCommand *>(controlInfo);
00658         // add into appConnMap
00659         conn = &tcpAppConnMapM[connId];
00660         conn->connIdM = connId;
00661         conn->appGateIndexM = msgP->getArrivalGate()->getIndex();
00662         conn->pNscSocketM = NULL;  // will be filled in within processAppCommand()
00663 
00664         // create send queue
00665         const char *sendQueueClass = openCmd->getSendQueueClass();
00666         if (!sendQueueClass || !sendQueueClass[0])
00667             sendQueueClass = this->par("sendQueueClass");
00668         conn->sendQueueM = check_and_cast<TCP_NSC_SendQueue *>(createOne(sendQueueClass));
00669         conn->sendQueueM->setConnection(conn);
00670 
00671         // create receive queue
00672         const char *receiveQueueClass = openCmd->getReceiveQueueClass();
00673         if (!receiveQueueClass || !receiveQueueClass[0])
00674             receiveQueueClass = this->par("receiveQueueClass");
00675         conn->receiveQueueM = check_and_cast<TCP_NSC_ReceiveQueue *>(createOne(receiveQueueClass));
00676         conn->receiveQueueM->setConnection(conn);
00677 
00678         tcpEV << this << ": TCP connection created for " << msgP << "\n";
00679     }
00680     processAppCommand(*conn, msgP);
00681 }
00682 
00683 void TCP_NSC::handleMessage(cMessage *msgP)
00684 {
00685     if (msgP->isSelfMessage())
00686     {
00687         // timer expired
00688         /*
00689         ...
00690         NSC timer processing
00691         ...
00692            Timers are ordinary cMessage objects that are started by
00693            scheduleAt(simTime()+timeout, msg), and can be cancelled
00694            via cancelEvent(msg); when they expire (fire) they are delivered
00695            to the module via handleMessage(), i.e. they end up here.
00696         */
00697         if(msgP == pNsiTimerM )
00698         { // nsc_nsi_timer
00699             do_SEND_all();
00700 
00701             pStackM->increment_ticks();
00702 
00703             pStackM->timer_interrupt();
00704 
00705             scheduleAt(msgP->getArrivalTime() + 1.0 / (double)pStackM->get_hz(), msgP);
00706         }
00707     }
00708     else if (msgP->arrivedOn("ipIn") || msgP->arrivedOn("ipv6In"))
00709     {
00710         tcpEV << this << ": handle msg: " << msgP->getName() << "\n";
00711         // must be a TCPSegment
00712         TCPSegment *tcpseg = check_and_cast<TCPSegment *>(msgP);
00713         handleIpInputMessage(tcpseg);
00714 
00715     }
00716     else // must be from app
00717     {
00718         tcpEV << this << ": handle msg: " << msgP->getName() << "\n";
00719         handleAppMessage(msgP);
00720     }
00721 
00722     if (ev.isGUI())
00723         updateDisplayString();
00724 }
00725 
00726 void TCP_NSC::updateDisplayString()
00727 {
00728     //...
00729 }
00730 
00731 TCP_NSC_Connection *TCP_NSC::findAppConn(int connIdP)
00732 {
00733     TcpAppConnMap::iterator i = tcpAppConnMapM.find(connIdP);
00734     return i==tcpAppConnMapM.end() ? NULL : &(i->second);
00735 }
00736 
00737 TCP_NSC_Connection *TCP_NSC::findConnByInetSockPair(TCP_NSC_Connection::SockPair const & sockPairP)
00738 {
00739     SockPair2ConnIdMap::iterator i = inetSockPair2ConnIdMapM.find(sockPairP);
00740     return i==inetSockPair2ConnIdMapM.end() ? NULL : findAppConn(i->second);
00741 }
00742 
00743 TCP_NSC_Connection *TCP_NSC::findConnByNscSockPair(TCP_NSC_Connection::SockPair const & sockPairP)
00744 {
00745     SockPair2ConnIdMap::iterator i = nscSockPair2ConnIdMapM.find(sockPairP);
00746     return i==nscSockPair2ConnIdMapM.end() ? NULL : findAppConn(i->second);
00747 }
00748 
00749 void TCP_NSC::finish()
00750 {
00751     isAliveM = false;
00752 }
00753 
00754 void TCP_NSC::removeConnection(int connIdP)
00755 {
00756     TcpAppConnMap::iterator i = tcpAppConnMapM.find(connIdP);
00757     if (i != tcpAppConnMapM.end())
00758         tcpAppConnMapM.erase(i);
00759 }
00760 
00761 void TCP_NSC::printConnBrief(TCP_NSC_Connection& connP)
00762 {
00763     tcpEV << this << ": connId=" << connP.connIdM << " appGateIndex=" << connP.appGateIndexM;
00764     tcpEV << " nscsocket=" << connP.pNscSocketM << "\n";
00765 }
00766 
00767 void TCP_NSC::loadStack(const char* stacknameP, int bufferSizeP)
00768 {
00769     void *handle = NULL;
00770     FCreateStack create = NULL;
00771 
00772     tcpEV << this << ": Loading stack " << stacknameP << "\n";
00773 
00774     handle = dlopen(stacknameP, RTLD_NOW);
00775     if(!handle) {
00776         fputs("The loading of NSC stack is unsuccessful: ", stderr);
00777         fputs(dlerror(), stderr);
00778         fputs("\nCheck the LD_LIBRARY_PATH or stackname!\n", stderr);
00779         exit(1);
00780     }
00781 
00782     create = (FCreateStack)dlsym(handle, "nsc_create_stack");
00783     if(!create) {
00784         fputs(dlerror(), stderr);
00785         fputs("\n", stderr);
00786         exit(1);
00787     }
00788 
00789     pStackM = create(this, this, NULL);
00790 
00791     tcpEV << "TCP_NSC " << this << " has stack " << pStackM << "\n";
00792 
00793     fprintf(stderr, "Created stack = %p\n", pStackM);
00794 
00795     fprintf(stderr, "Initialising stack, name=%s\n", pStackM->get_name());
00796 
00797     pStackM->init(pStackM->get_hz());
00798 
00799     pStackM->buffer_size(bufferSizeP);
00800 
00801     fprintf(stderr, "done.\n");
00802 
00803     // set timer for 1.0 / pStackM->get_hz()
00804     pNsiTimerM = new cMessage("nsc_nsi_timer");
00805     scheduleAt(1.0 / (double)pStackM->get_hz(), pNsiTimerM);
00806 }
00807 
00809 void TCP_NSC::send_callback(const void *dataP, int datalenP)
00810 {
00811     if(!isAliveM)
00812         return;
00813     tcpEV << this << ": NSC: send_callback(" << dataP << ", " << datalenP << ") called\n";
00814 
00815     sendToIP(dataP, datalenP);
00816 
00817     // comment from nsc.cc:
00818     //   New method: if_send_finish. This should be called by the nic
00819     //   driver code when there is space in it's queue. Unfortunately
00820     //   we don't know whether that is the case from here, so we just
00821     //   call it immediately for now. **THIS IS INCORRECT**. It should
00822     //   only be called when a space becomes free in the nic queue.
00823     pStackM->if_send_finish(0);    // XXX: hardcoded inerface id
00824 }
00825 
00826 /*
00827 void TCP_NSC::interrupt()
00828 {
00829 }
00830 */
00831 
00843 void TCP_NSC::wakeup()
00844 {
00845     if(!isAliveM)
00846         return;
00847     tcpEV << this << ": wakeup() called\n";
00848 }
00849 
00850 void TCP_NSC::gettime(unsigned int *secP, unsigned int *usecP)
00851 {
00852 #if OMNETPP_VERSION < 0x0400
00853     simtime_t t = simTime();
00854     *sec = (unsigned int)(t);
00855     *usec = (unsigned int)((t - *sec) * 1000000 + 0.5);
00856 #else
00857 #ifdef USE_DOUBLE_SIMTIME
00858     double t = simTime().dbl();
00859     *sec = (unsigned int)(t);
00860     *usec = (unsigned int)((t - *sec) * 1000000 + 0.5);
00861 #else
00862     simtime_t t = simTime();
00863     int64 raw = t.raw();
00864     int64 scale = t.getScale();
00865     int64 secs = raw / scale;
00866     int64 usecs = (raw - (secs * scale));
00867     //usecs = usecs * 1000000 / scale;
00868     if(scale>1000000) // scale always 10^n
00869         usecs /= (scale / 1000000);
00870     else
00871         usecs *= (1000000 / scale);
00872     *secP = secs;
00873     *usecP = usecs;
00874 #endif
00875 #endif
00876     tcpEV << this << ": gettime(" << *secP << "," << *usecP << ") called\n";
00877 }
00878 
00879 void TCP_NSC::sendToIP(const void *dataP, int lenP)
00880 {
00881     IPvXAddress src,dest;
00882     const nsc_iphdr *iph = (const nsc_iphdr *)dataP;
00883 
00884     int ipHdrLen = 4 * iph->ihl;
00885     ASSERT(ipHdrLen <= lenP);
00886     int totalLen = ntohs(iph->tot_len);
00887     ASSERT(totalLen == lenP);
00888     tcphdr const *tcph = (tcphdr const*)(((const char *)(iph)) + ipHdrLen);
00889 
00890         // XXX add some info (seqNo, len, etc)
00891 
00892     TCP_NSC_Connection::SockPair nscSockPair;
00893 
00894     TCP_NSC_Connection *conn;
00895 
00896     nscSockPair.localM.ipAddrM.set(ntohl(iph->saddr));
00897     nscSockPair.localM.portM = ntohs(tcph->th_sport);
00898     nscSockPair.remoteM.ipAddrM.set(ntohl(iph->daddr));
00899     nscSockPair.remoteM.portM = ntohs(tcph->th_dport);
00900 
00901     if(curConnM)
00902     {
00903         changeAddresses(*curConnM, curConnM->inetSockPairM, nscSockPair);
00904         conn = curConnM;
00905     }
00906     else
00907     {
00908         conn = findConnByNscSockPair(nscSockPair);
00909     }
00910 
00911     TCPSegment *tcpseg;
00912     if(conn)
00913     {
00914         tcpseg = conn->sendQueueM->createSegmentWithBytes(tcph, totalLen-ipHdrLen);
00915         src = conn->inetSockPairM.localM.ipAddrM;
00916         dest = conn->inetSockPairM.remoteM.ipAddrM;
00917     }
00918     else
00919     {
00920         tcpseg = new TCPSegment("tcp-segment");
00921 
00922         TCPSerializer().parse((const unsigned char *)tcph, totalLen-ipHdrLen, tcpseg);
00923         dest = mapNsc2Remote(ntohl(iph->daddr));
00924     }
00925     ASSERT(tcpseg);
00926 
00927     tcpEV << this << ": Sending: conn=" << conn << ", data: " << dataP << " of len " << lenP << " from " << src
00928        << " to " << dest << "\n";
00929 
00930     const char* output;
00931     if (!dest.isIPv6())
00932     {
00933         // send over IPv4
00934         IPControlInfo *controlInfo = new IPControlInfo();
00935         controlInfo->setProtocol(IP_PROT_TCP);
00936         controlInfo->setSrcAddr(src.get4());
00937         controlInfo->setDestAddr(dest.get4());
00938         tcpseg->setControlInfo(controlInfo);
00939 
00940         output = "ipOut";
00941     }
00942     else
00943     {
00944         // send over IPv6
00945         IPv6ControlInfo *controlInfo = new IPv6ControlInfo();
00946         controlInfo->setProtocol(IP_PROT_TCP);
00947         controlInfo->setSrcAddr(src.get6());
00948         controlInfo->setDestAddr(dest.get6());
00949         tcpseg->setControlInfo(controlInfo);
00950 
00951         output ="ipv6Out";
00952     }
00953     if(conn)
00954     {
00955         conn->receiveQueueM->notifyAboutSending(tcpseg);
00956     }
00957 
00958     // record seq (only if we do send data) and ackno
00959     if (sndNxtVector && tcpseg->getPayloadLength()!=0)
00960         sndNxtVector->record(tcpseg->getSequenceNo());
00961     if (sndAckVector)
00962         sndAckVector->record(tcpseg->getAckNo());
00963 
00964     send(tcpseg, output);
00965 }
00966 
00967 void TCP_NSC::processAppCommand(TCP_NSC_Connection& connP, cMessage *msgP)
00968 {
00969     printConnBrief(connP);
00970 
00971     // first do actions
00972     TCPCommand *tcpCommand = (TCPCommand *)(msgP->removeControlInfo());
00973 
00974     switch (msgP->getKind())
00975     {
00976         case TCP_C_OPEN_ACTIVE: process_OPEN_ACTIVE(connP, tcpCommand, msgP); break;
00977         case TCP_C_OPEN_PASSIVE: process_OPEN_PASSIVE(connP, tcpCommand, msgP); break;
00978         case TCP_C_SEND: process_SEND(connP, tcpCommand, check_and_cast<cPacket*>(msgP)); break;
00979         case TCP_C_CLOSE: process_CLOSE(connP, tcpCommand, msgP); break;
00980         case TCP_C_ABORT: process_ABORT(connP, tcpCommand, msgP); break;
00981         case TCP_C_STATUS: process_STATUS(connP, tcpCommand, msgP); break;
00982         default: opp_error("wrong command from app: %d", msgP->getKind());
00983     }
00984 
00985     /*
00986     ...
00987     NSC: should call removeConnection(connP.connIdM) if socket has been destroyed
00988     ...
00989     */
00990 }
00991 
00992 void TCP_NSC::process_OPEN_ACTIVE(TCP_NSC_Connection& connP, TCPCommand *tcpCommandP, cMessage *msgP)
00993 {
00994     TCPOpenCommand *openCmd = check_and_cast<TCPOpenCommand *>(tcpCommandP);
00995 
00996     TCP_NSC_Connection::SockPair inetSockPair,nscSockPair;
00997     inetSockPair.localM.ipAddrM = openCmd->getLocalAddr();
00998     inetSockPair.remoteM.ipAddrM = openCmd->getRemoteAddr();
00999     inetSockPair.localM.portM = openCmd->getLocalPort();
01000     inetSockPair.remoteM.portM = openCmd->getRemotePort();
01001 
01002     if (inetSockPair.remoteM.ipAddrM.isUnspecified() || inetSockPair.remoteM.portM == -1)
01003         opp_error("Error processing command OPEN_ACTIVE: remote address and port must be specified");
01004 
01005     tcpEV << this << ": OPEN: "
01006         << inetSockPair.localM.ipAddrM << ":" << inetSockPair.localM.portM << " --> "
01007         << inetSockPair.remoteM.ipAddrM << ":" << inetSockPair.remoteM.portM << "\n";
01008 
01009     // insert to map:
01010     uint32_t nscRemoteAddr = mapRemote2Nsc(inetSockPair.remoteM.ipAddrM);
01011 
01012     ASSERT(pStackM);
01013 
01014     nscSockPair.localM.portM = inetSockPair.localM.portM;
01015     if (nscSockPair.localM.portM == -1)
01016         nscSockPair.localM.portM = 0; // NSC uses 0 to mean "not specified"
01017     nscSockPair.remoteM.ipAddrM.set(nscRemoteAddr);
01018     nscSockPair.remoteM.portM = inetSockPair.remoteM.portM;
01019 
01020     changeAddresses(connP, inetSockPair, nscSockPair);
01021 
01022     ASSERT(!curConnM);
01023     curConnM = &connP;
01024     connP.connect(*pStackM, inetSockPair, nscSockPair);
01025     curConnM = NULL;
01026 
01027     // and add to map:
01028     // TODO sendToIp already set the addresses.
01029     //changeAddresses(connP, inetSockPair, nscSockPair);
01030 
01031     delete tcpCommandP;
01032     delete msgP;
01033 }
01034 
01035 void TCP_NSC::process_OPEN_PASSIVE(TCP_NSC_Connection& connP, TCPCommand *tcpCommandP, cMessage *msgP)
01036 {
01037     ASSERT(pStackM);
01038 
01039     TCPOpenCommand *openCmd = check_and_cast<TCPOpenCommand *>(tcpCommandP);
01040 
01041     ASSERT(openCmd->getFork()==true);
01042 
01043     TCP_NSC_Connection::SockPair inetSockPair, nscSockPair;
01044     inetSockPair.localM.ipAddrM = openCmd->getLocalAddr();
01045     inetSockPair.remoteM.ipAddrM = openCmd->getRemoteAddr();
01046     inetSockPair.localM.portM = openCmd->getLocalPort();
01047     inetSockPair.remoteM.portM = openCmd->getRemotePort();
01048 
01049     uint32_t nscRemoteAddr = inetSockPair.remoteM.ipAddrM.isUnspecified()
01050         ? ntohl(INADDR_ANY)
01051         : mapRemote2Nsc(inetSockPair.remoteM.ipAddrM); // Don't remove! It's insert remoteAddr into MAP.
01052     (void)nscRemoteAddr; // Eliminate "unused variable" warning.
01053 
01054     if (inetSockPair.localM.portM == -1)
01055         opp_error("Error processing command OPEN_PASSIVE: local port must be specified");
01056 
01057     tcpEV << this << "Starting to listen on: " << inetSockPair.localM.ipAddrM << ":" << inetSockPair.localM.portM << "\n";
01058 
01059     /*
01060     ...
01061     NSC: process passive open request
01062     ...
01063     */
01064     nscSockPair.localM.portM = inetSockPair.localM.portM;
01065 
01066     changeAddresses(connP, inetSockPair, nscSockPair);
01067 
01068     ASSERT(!curConnM);
01069     curConnM = &connP;
01070     connP.listen(*pStackM, inetSockPair, nscSockPair);
01071     curConnM = NULL;
01072 
01073     changeAddresses(connP, inetSockPair, nscSockPair);
01074 
01075     delete openCmd;
01076     delete msgP;
01077 }
01078 
01079 void TCP_NSC::process_SEND(TCP_NSC_Connection& connP, TCPCommand *tcpCommandP, cPacket *msgP)
01080 {
01081     TCPSendCommand *sendCommand = check_and_cast<TCPSendCommand *>(tcpCommandP);
01082     delete sendCommand;
01083 
01084     connP.send(msgP);
01085 
01086     connP.do_SEND();
01087 }
01088 
01089 void TCP_NSC::do_SEND_all()
01090 {
01091     TcpAppConnMap::iterator j = tcpAppConnMapM.begin();
01092     for(; j != tcpAppConnMapM.end(); ++j)
01093     {
01094         TCP_NSC_Connection& conn = j->second;
01095         conn.do_SEND();
01096     }
01097 }
01098 
01099 void TCP_NSC::process_CLOSE(TCP_NSC_Connection& connP, TCPCommand *tcpCommandP, cMessage *msgP)
01100 {
01101     tcpEV << this << ": process_CLOSE()\n";
01102 
01103     delete tcpCommandP;
01104     delete msgP;
01105 
01106     connP.close();
01107 }
01108 
01109 void TCP_NSC::process_ABORT(TCP_NSC_Connection& connP, TCPCommand *tcpCommandP, cMessage *msgP)
01110 {
01111     tcpEV << this << ": process_ABORT()\n";
01112 
01113     delete tcpCommandP;
01114     delete msgP;
01115 
01116     connP.abort();
01117 }
01118 
01119 void TCP_NSC::process_STATUS(TCP_NSC_Connection& connP, TCPCommand *tcpCommandP, cMessage *msgP)
01120 {
01121     delete tcpCommandP; // but we'll reuse msg for reply
01122 
01123     TCPStatusInfo *statusInfo = new TCPStatusInfo();
01124 
01125     /*
01126     ...
01127     NSC: fill in status if possible
01128 
01129          Still more work to do here. Some of this needs to be implemented on
01130          the NSC side, which is fairly trivial, just updating the get_var
01131          function for each stack.
01132     ...
01133     */
01134 
01135     char result[512];
01136 
01137     ASSERT(connP.pNscSocketM);
01138 
01139     connP.pNscSocketM->get_var("cwnd_", result, sizeof(result));
01140     statusInfo->setSnd_wnd(atoi(result));
01141 
01142     //connP.pNscSocketM->get_var("ssthresh_", result, sizeof(result));
01143     //connP.pNscSocketM->get_var("rxtcur_", result, sizeof(result));
01144 
01145 
01146 /* other TCP model:
01147     statusInfo->setState(fsm.getState());
01148     statusInfo->setStateName(stateName(fsm.getState()));
01149 
01150     statusInfo->setLocalAddr(localAddr);
01151     statusInfo->setRemoteAddr(remoteAddr);
01152     statusInfo->setLocalPort(localPort);
01153     statusInfo->setRemotePort(remotePort);
01154 
01155     statusInfo->setSnd_mss(state->snd_mss);
01156     statusInfo->setSnd_una(state->snd_una);
01157     statusInfo->setSnd_nxt(state->snd_nxt);
01158     statusInfo->setSnd_max(state->snd_max);
01159     statusInfo->setSnd_wnd(state->snd_wnd);
01160     statusInfo->setSnd_up(state->snd_up);
01161     statusInfo->setSnd_wl1(state->snd_wl1);
01162     statusInfo->setSnd_wl2(state->snd_wl2);
01163     statusInfo->setIss(state->iss);
01164     statusInfo->setRcv_nxt(state->rcv_nxt);
01165     statusInfo->setRcv_wnd(state->rcv_wnd);
01166     statusInfo->setRcv_up(state->rcv_up);
01167     statusInfo->setIrs(state->irs);
01168     statusInfo->setFin_ack_rcvd(state->fin_ack_rcvd);
01169 */
01170 
01171     msgP->setControlInfo(statusInfo);
01172     send(msgP, "appOut", connP.appGateIndexM);
01173 }
01174 
01175 #endif // WITH_TCP_NSC