INET Framework for OMNeT++/OMNEST
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         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