INET Framework for OMNeT++/OMNEST
inet::tcp::TcpLwip Class Reference

Module for using the LwIP TCP stack. More...

#include <TcpLwip.h>

Inheritance diagram for inet::tcp::TcpLwip:
inet::tcp::LwipTcpStackIf inet::LifecycleUnsupported inet::ILifecycle

Public Member Functions

 TcpLwip ()
 
virtual ~TcpLwip ()
 
- Public Member Functions inherited from inet::tcp::LwipTcpStackIf
virtual ~LwipTcpStackIf ()
 
- Public Member Functions inherited from inet::LifecycleUnsupported
virtual bool handleOperationStage (LifecycleOperation *operation, IDoneCallback *doneCallback) override
 Perform one stage of a lifecycle operation. More...
 
- Public Member Functions inherited from inet::ILifecycle
virtual ~ILifecycle ()
 

Protected Member Functions

cSimpleModule redefinitions
virtual void initialize (int stage) override
 
virtual int numInitStages () const override
 
virtual void handleMessage (cMessage *msgP) override
 
virtual void finish () override
 
virtual void refreshDisplay () const override
 
LwipTcpStackIf functions
virtual void ip_output (LwipTcpLayer::tcp_pcb *pcb, L3Address const &src, L3Address const &dest, void *tcpseg, int len) override
 TCP layer send a packet to IP layer. More...
 
virtual err_t lwip_tcp_event (void *arg, LwipTcpLayer::tcp_pcb *pcb, LwipTcpLayer::lwip_event event, struct pbuf *p, u16_t size, err_t err) override
 TCP layer events. More...
 
virtual void lwip_free_pcb_event (LwipTcpLayer::tcp_pcb *pcb) override
 TCP layer event called before LWIP freeing a pcb. More...
 
virtual netifip_route (L3Address const &ipAddr) override
 Get the network interface. More...
 
virtual void notifyAboutIncomingSegmentProcessing (LwipTcpLayer::tcp_pcb *pcb, uint32_t seqNo, const void *dataptr, int len) override
 
internal event functions
err_t tcp_event_accept (TcpLwipConnection &conn, LwipTcpLayer::tcp_pcb *pcb, err_t err)
 
err_t tcp_event_sent (TcpLwipConnection &conn, u16_t size)
 
err_t tcp_event_recv (TcpLwipConnection &conn, struct pbuf *p, err_t err)
 
err_t tcp_event_conn (TcpLwipConnection &conn, err_t err)
 
err_t tcp_event_poll (TcpLwipConnection &conn)
 
err_t tcp_event_err (TcpLwipConnection &conn, err_t err)
 

internal utility functions

typedef std::map< int, TcpLwipConnection * > TcpAppConnMap
 
TcpAppConnMap tcpAppConnMapM
 
cMessage * pLwipFastTimerM = nullptr
 
struct netif netIf
 
LwipTcpLayer * pLwipTcpLayerM = nullptr
 
bool isAliveM = false
 
PacketpCurTcpSegM = nullptr
 
CrcMode crcMode = CRC_MODE_UNDEFINED
 
LwipTcpLayer * getLwipTcpLayer ()
 
virtual TcpLwipSendQueuecreateSendQueue ()
 To be called from TcpLwipConnection: create a new send queue. More...
 
virtual TcpLwipReceiveQueuecreateReceiveQueue ()
 To be called from TcpLwipConnection: create a new receive queue. More...
 
TcpLwipConnectionfindAppConn (int connIdP)
 
TcpLwipConnectionfindConnByPcb (LwipTcpLayer::tcp_pcb *pcb)
 
void removeConnection (TcpLwipConnection &conn)
 
void printConnBrief (TcpLwipConnection &connP)
 
void handleUpperCommand (cMessage *msgP)
 
void handleLowerPacket (Packet *packet)
 

Detailed Description

Module for using the LwIP TCP stack.

Member Typedef Documentation

◆ TcpAppConnMap

typedef std::map<int, TcpLwipConnection *> inet::tcp::TcpLwip::TcpAppConnMap
protected

Constructor & Destructor Documentation

◆ TcpLwip()

inet::tcp::TcpLwip::TcpLwip ( )
41 {
42  netIf.gw.addr = L3Address();
43  netIf.flags = 0;
44  netIf.input = nullptr;
45  netIf.ip_addr.addr = L3Address();
46  netIf.linkoutput = nullptr;
47  netIf.mtu = 1500;
48  netIf.name[0] = 'T';
49  netIf.name[1] = 'C';
50  netIf.netmask.addr = L3Address();
51  netIf.next = nullptr;
52  netIf.num = 0;
53  netIf.output = nullptr;
54  netIf.state = nullptr;
55 }

◆ ~TcpLwip()

inet::tcp::TcpLwip::~TcpLwip ( )
virtual
115 {
116  EV_TRACE << this << ": destructor\n";
117  isAliveM = false;
118 
119  while (!tcpAppConnMapM.empty()) {
120  auto i = tcpAppConnMapM.begin();
121  tcpAppConnMapM.erase(i);
122  }
123 
124  if (pLwipFastTimerM)
125  cancelAndDelete(pLwipFastTimerM);
126 
127  if (pLwipTcpLayerM)
128  delete pLwipTcpLayerM;
129 }

Member Function Documentation

◆ createReceiveQueue()

TcpLwipReceiveQueue * inet::tcp::TcpLwip::createReceiveQueue ( )
virtual

To be called from TcpLwipConnection: create a new receive queue.

651 {
652  return new TcpLwipReceiveQueue();
653 }

Referenced by inet::tcp::TcpLwipConnection::initConnection().

◆ createSendQueue()

TcpLwipSendQueue * inet::tcp::TcpLwip::createSendQueue ( )
virtual

To be called from TcpLwipConnection: create a new send queue.

646 {
647  return new TcpLwipSendQueue();
648 }

Referenced by inet::tcp::TcpLwipConnection::initConnection().

◆ findAppConn()

TcpLwipConnection * inet::tcp::TcpLwip::findAppConn ( int  connIdP)
protected
570 {
571  auto i = tcpAppConnMapM.find(connIdP);
572  return i == tcpAppConnMapM.end() ? nullptr : (i->second);
573 }

Referenced by handleUpperCommand().

◆ findConnByPcb()

TcpLwipConnection* inet::tcp::TcpLwip::findConnByPcb ( LwipTcpLayer::tcp_pcb *  pcb)
protected

◆ finish()

void inet::tcp::TcpLwip::finish ( )
overrideprotectedvirtual
576 {
577  isAliveM = false;
578 }

◆ getLwipTcpLayer()

◆ handleLowerPacket()

void inet::tcp::TcpLwip::handleLowerPacket ( Packet packet)
protected
132 {
133  L3Address srcAddr, destAddr;
134  int interfaceId = -1;
135 
136  auto tcpsegP = packet->peekAtFront<TcpHeader>();
137  srcAddr = packet->getTag<L3AddressInd>()->getSrcAddress();
138  destAddr = packet->getTag<L3AddressInd>()->getDestAddress();
139  interfaceId = (packet->getTag<InterfaceInd>())->getInterfaceId();
140 
141  switch (tcpsegP->getCrcMode()) {
143  EV_WARN << "CRC error, packet dropped\n";
144  delete packet;
145  return;
146  case CRC_DECLARED_CORRECT: {
147  // modify to calculated, for serializing
148  packet->trimFront();
149  const auto& newTcpsegP = packet->removeAtFront<TcpHeader>();
150  newTcpsegP->setCrcMode(CRC_COMPUTED);
151  newTcpsegP->setCrc(0);
152  packet->insertAtFront(newTcpsegP);
153  tcpsegP = newTcpsegP;
154  break;
155  }
156  default:
157  break;
158  }
159 
160  // process segment
161  size_t ipHdrLen = sizeof(ip_hdr);
162  size_t const maxBufferSize = 4096;
163  char *data = new char[maxBufferSize];
164  memset(data, 0, maxBufferSize);
165 
166  ip_hdr *ih = (ip_hdr *)(data);
167 
168  // set the modified lwip IP header:
169  ih->_hl = ipHdrLen / 4;
170  ASSERT((ih->_hl) * 4 == ipHdrLen);
171  ih->_chksum = 0;
172  ih->src.addr = srcAddr;
173  ih->dest.addr = destAddr;
174 
175  size_t totalTcpLen = maxBufferSize - ipHdrLen;
176 
177  const auto& bytes = packet->peekDataAsBytes();
178  totalTcpLen = bytes->copyToBuffer((uint8_t *)data + ipHdrLen, totalTcpLen);
179 
180  size_t totalIpLen = ipHdrLen + totalTcpLen;
181  ih->_chksum = 0;
182 
183  // search unfilled local addr in pcb-s for this connection.
184  L3Address laddr = ih->dest.addr;
185  L3Address raddr = ih->src.addr;
186  u16_t lport = tcpsegP->getDestPort();
187  u16_t rport = tcpsegP->getSrcPort();
188 
189  if (tcpsegP->getSynBit() && tcpsegP->getAckBit()) {
190  for (auto& elem : tcpAppConnMapM) {
191  LwipTcpLayer::tcp_pcb *pcb = elem.second->pcbM;
192  if (pcb) {
193  if ((pcb->state == LwipTcpLayer::SYN_SENT)
194  && (pcb->local_ip.addr.isUnspecified())
195  && (pcb->local_port == lport)
196  && (pcb->remote_ip.addr == raddr)
197  && (pcb->remote_port == rport)
198  )
199  {
200  pcb->local_ip.addr = laddr;
201  }
202  }
203  }
204  }
205 
206  ASSERT(pCurTcpSegM == nullptr);
207  pCurTcpSegM = packet;
208  // receive msg from network
209  pLwipTcpLayerM->if_receive_packet(interfaceId, data, totalIpLen);
210  // lwip call back the notifyAboutIncomingSegmentProcessing() for store incoming messages
211  pCurTcpSegM = nullptr;
212 
213  // LwipTcpLayer will call the tcp_event_recv() / tcp_event_err() and/or send a packet to sender
214 
215  delete[] data;
216  delete packet;
217 }

Referenced by handleMessage().

◆ handleMessage()

void inet::tcp::TcpLwip::handleMessage ( cMessage *  msgP)
overrideprotectedvirtual
428 {
429  if (msgP->isSelfMessage()) {
430  // timer expired
431  if (msgP == pLwipFastTimerM) { // lwip fast timer
432  EV_TRACE << "Call tcp_fasttmr()\n";
433  pLwipTcpLayerM->tcp_fasttmr();
434  if (simTime() == roundTime(simTime(), 2)) {
435  EV_TRACE << "Call tcp_slowtmr()\n";
436  pLwipTcpLayerM->tcp_slowtmr();
437  }
438  }
439  else {
440  throw cRuntimeError("Unknown self message");
441  }
442  }
443  else if (msgP->arrivedOn("ipIn")) {
444  // must be a Packet
445  Packet *pk = check_and_cast<Packet *>(msgP);
446  auto protocol = pk->getTag<PacketProtocolTag>()->getProtocol();
447  if (protocol == &Protocol::tcp) {
448  EV_TRACE << this << ": handle tcp segment: " << msgP->getName() << "\n";
449  handleLowerPacket(pk);
450  }
451  else if (protocol == &Protocol::icmpv4 || protocol == &Protocol::icmpv6) {
452  EV_WARN << "ICMP error received -- discarding\n"; // FIXME can ICMP packets really make it up to TCP???
453  delete msgP;
454  }
455  else
456  throw cRuntimeError("Unknown protocol: %s(%d)", protocol->getName(), protocol->getId());
457  }
458  else { // must be from app
459  EV_TRACE << this << ": handle msg: " << msgP->getName() << "\n";
460  handleUpperCommand(msgP);
461  }
462 
463  if (!pLwipFastTimerM->isScheduled()) { // lwip fast timer
464  if (nullptr != pLwipTcpLayerM->tcp_active_pcbs || nullptr != pLwipTcpLayerM->tcp_tw_pcbs)
465  scheduleAfter(roundTime(simTime() + 0.250, 4) - simTime(), pLwipFastTimerM);
466  }
467 }

◆ handleUpperCommand()

void inet::tcp::TcpLwip::handleUpperCommand ( cMessage *  msgP)
protected
391 {
392  auto& tags = check_and_cast<ITaggedObject *>(msgP)->getTags();
393  int connId = tags.getTag<SocketReq>()->getSocketId();
394 
395  TcpLwipConnection *conn = findAppConn(connId);
396 
397  if (!conn) {
398  // add into appConnMap
399 
400  auto moduleType = cModuleType::get("inet.transportlayer.tcp_lwip.TcpLwipConnection");
401  char submoduleName[24];
402  sprintf(submoduleName, "conn-%d", connId);
403  conn = check_and_cast<TcpLwipConnection *>(moduleType->create(submoduleName, this));
404  conn->finalizeParameters();
405  conn->buildInside();
406  conn->initConnection(*this, connId);
407  conn->callInitialize();
408 
409  tcpAppConnMapM[connId] = conn;
410 
411  EV_INFO << this << ": TCP connection created for " << msgP << "\n";
412  }
413 
414  printConnBrief(*conn);
415  conn->processAppCommand(msgP);
416 }

Referenced by handleMessage().

◆ initialize()

void inet::tcp::TcpLwip::initialize ( int  stage)
overrideprotectedvirtual
58 {
59  cSimpleModule::initialize(stage);
60 
61  EV_TRACE << this << ": initialize stage " << stage << endl;
62 
63  if (stage == INITSTAGE_LOCAL) {
64  const char *q;
65  q = par("sendQueueClass");
66  if (*q != '\0')
67  throw cRuntimeError("Don't use obsolete sendQueueClass = \"%s\" parameter", q);
68 
69  q = par("receiveQueueClass");
70  if (*q != '\0')
71  throw cRuntimeError("Don't use obsolete receiveQueueClass = \"%s\" parameter", q);
72 
73  const char *crcModeString = par("crcMode");
74  crcMode = parseCrcMode(crcModeString, false);
75 
76  WATCH_MAP(tcpAppConnMapM);
77 
78  pLwipTcpLayerM = new LwipTcpLayer(*this);
79  pLwipFastTimerM = new cMessage("lwip_fast_timer");
80  EV_INFO << "TcpLwip " << this << " has stack " << pLwipTcpLayerM << "\n";
81  }
82  else if (stage == INITSTAGE_TRANSPORT_LAYER) {
83  cModule *node = findContainingNode(this);
84  NodeStatus *nodeStatus = node ? check_and_cast_nullable<NodeStatus *>(node->getSubmodule("status")) : nullptr;
85  bool isOperational = (!nodeStatus) || nodeStatus->getState() == NodeStatus::UP;
86  if (!isOperational)
87  throw cRuntimeError("This module doesn't support starting in node DOWN state");
88  registerService(Protocol::tcp, gate("appIn"), gate("appOut"));
89  registerProtocol(Protocol::tcp, gate("ipOut"), gate("ipIn"));
90 
91  if (crcMode == CRC_COMPUTED) {
92  cModuleType *moduleType = cModuleType::get("inet.transportlayer.tcp_common.TcpCrcInsertionHook");
93  auto *crcInsertion = check_and_cast<TcpCrcInsertionHook *>(moduleType->create("crcInsertion", this));
94  crcInsertion->finalizeParameters();
95  crcInsertion->callInitialize();
96 
97 #ifdef INET_WITH_IPv4
98  auto ipv4 = dynamic_cast<INetfilter *>(findModuleByPath("^.ipv4.ip"));
99  if (ipv4 != nullptr)
100  ipv4->registerHook(0, crcInsertion);
101 #endif
102 #ifdef INET_WITH_IPv6
103  auto ipv6 = dynamic_cast<INetfilter *>(findModuleByPath("^.ipv6.ipv6"));
104  if (ipv6 != nullptr)
105  ipv6->registerHook(0, crcInsertion);
106 #endif
107  }
108  }
109  else if (stage == INITSTAGE_LAST) {
110  isAliveM = true;
111  }
112 }

◆ ip_output()

void inet::tcp::TcpLwip::ip_output ( LwipTcpLayer::tcp_pcb *  pcb,
L3Address const &  src,
L3Address const &  dest,
void *  tcpseg,
int  len 
)
overrideprotectedvirtual

TCP layer send a packet to IP layer.

Parameters
pcbthe lwip pcb or nullptr (tipically when send a RESET )
srcthe source IP addr
destthe destination IP addr
tcpsegpointer to TCP segment (message)
lenlength of tcpseg

Implements inet::tcp::LwipTcpStackIf.

586 {
587  TcpLwipConnection *conn = (pcb != nullptr) ? static_cast<TcpLwipConnection *>(pcb->callback_arg) : nullptr;
588 
589  Packet *packet = nullptr;
590 
591  if (conn) {
592  packet = conn->sendQueueM->createSegmentWithBytes(dataP, lenP);
593  }
594  else {
595  const auto& bytes = makeShared<BytesChunk>((const uint8_t *)dataP, lenP);
596  packet = new Packet(nullptr, bytes);
597  const auto& tcpHdr = packet->popAtFront<TcpHeader>();
598  packet->trimFront();
599  int64_t numBytes = packet->getByteLength();
600  ASSERT(numBytes == 0);
601  packet->insertAtFront(tcpHdr);
602  }
603 
604  ASSERT(packet);
605 
606  auto tcpHdr = packet->removeAtFront<TcpHeader>();
607  tcpHdr->setCrc(0);
608  tcpHdr->setCrcMode(crcMode);
610 
611  EV_TRACE << this << ": Sending: conn=" << conn << ", data: " << dataP << " of len " << lenP
612  << " from " << srcP << " to " << destP << "\n";
613 
614  IL3AddressType *addressType = destP.getAddressType();
615 
616  packet->addTag<DispatchProtocolReq>()->setProtocol(addressType->getNetworkProtocol());
617  auto addresses = packet->addTag<L3AddressReq>();
618  addresses->setSrcAddress(srcP);
619  addresses->setDestAddress(destP);
620  if (conn) {
621  conn->notifyAboutSending(*tcpHdr);
622  }
623 
624  EV_INFO << this << ": Send segment:";
625  if (conn)
626  EV_INFO << "conn ID=" << conn->connIdM;
627  EV_INFO << " from " << srcP << " to " << destP << " SEQ=" << tcpHdr->getSequenceNo();
628  if (tcpHdr->getSynBit())
629  EV_INFO << " SYN";
630  if (tcpHdr->getAckBit())
631  EV_INFO << " ACK=" << tcpHdr->getAckNo();
632  if (tcpHdr->getFinBit())
633  EV_INFO << " FIN";
634  if (tcpHdr->getRstBit())
635  EV_INFO << " RST";
636  if (tcpHdr->getPshBit())
637  EV_INFO << " PSH";
638  if (tcpHdr->getUrgBit())
639  EV_INFO << " URG";
640  EV_INFO << " len=" << B(packet->getDataLength()) - tcpHdr->getHeaderLength() << "\n";
641 
642  send(packet, "ipOut");
643 }

◆ ip_route()

struct netif * inet::tcp::TcpLwip::ip_route ( L3Address const &  ipAddr)
overrideprotectedvirtual

Get the network interface.

Implements inet::tcp::LwipTcpStackIf.

386 {
387  return &netIf;
388 }

◆ lwip_free_pcb_event()

void inet::tcp::TcpLwip::lwip_free_pcb_event ( LwipTcpLayer::tcp_pcb *  pcb)
overrideprotectedvirtual

TCP layer event called before LWIP freeing a pcb.

Parameters
pcbpointer to pcb

Implements inet::tcp::LwipTcpStackIf.

236 {
237  TcpLwipConnection *conn = static_cast<TcpLwipConnection *>(pcb->callback_arg);
238  if (conn != nullptr && conn->pcbM == pcb) {
239 // conn->sendIndicationToApp(TCP_I_????); // TODO send some indication when need
240  removeConnection(*conn);
241  }
242 }

◆ lwip_tcp_event()

err_t inet::tcp::TcpLwip::lwip_tcp_event ( void *  arg,
LwipTcpLayer::tcp_pcb *  pcb,
LwipTcpLayer::lwip_event  ,
struct pbuf p,
u16_t  size,
err_t  err 
)
overrideprotectedvirtual

TCP layer events.

Implements inet::tcp::LwipTcpStackIf.

246 {
247  TcpLwipConnection *conn = static_cast<TcpLwipConnection *>(arg);
248  ASSERT(conn != nullptr);
249 
250  switch (event) {
251  case LwipTcpLayer::LWIP_EVENT_ACCEPT:
252  err = tcp_event_accept(*conn, pcb, err);
253  break;
254 
255  case LwipTcpLayer::LWIP_EVENT_SENT:
256  ASSERT(conn->pcbM == pcb);
257  err = tcp_event_sent(*conn, size);
258  break;
259 
260  case LwipTcpLayer::LWIP_EVENT_RECV:
261  ASSERT(conn->pcbM == pcb);
262  err = tcp_event_recv(*conn, p, err);
263  break;
264 
265  case LwipTcpLayer::LWIP_EVENT_CONNECTED:
266  ASSERT(conn->pcbM == pcb);
267  err = tcp_event_conn(*conn, err);
268  break;
269 
270  case LwipTcpLayer::LWIP_EVENT_POLL:
271  // it's called also when conn->pcbM point to a LISTEN pcb, and pcb point to a SYN_RCVD
272  if (conn->pcbM == pcb)
273  err = tcp_event_poll(*conn);
274  break;
275 
276  case LwipTcpLayer::LWIP_EVENT_ERR:
277  err = tcp_event_err(*conn, err);
278  break;
279 
280  default:
281  throw cRuntimeError("Invalid lwip_event: %d", event);
282  break;
283  }
284 
285  return err;
286 }

◆ notifyAboutIncomingSegmentProcessing()

void inet::tcp::TcpLwip::notifyAboutIncomingSegmentProcessing ( LwipTcpLayer::tcp_pcb *  pcb,
uint32_t  seqNo,
const void *  dataptr,
int  len 
)
overrideprotectedvirtual

Implements inet::tcp::LwipTcpStackIf.

221 {
222  TcpLwipConnection *conn = (pcb != nullptr) ? static_cast<TcpLwipConnection *>(pcb->callback_arg) : nullptr;
223  if (conn) {
224  conn->receiveQueueM->notifyAboutIncomingSegmentProcessing(pCurTcpSegM, seqNo, dataptr, len);
225  }
226  else {
227  const auto& tcpHdr = pCurTcpSegM->peekAtFront<TcpHeader>();
228  if (B(pCurTcpSegM->getByteLength()) > tcpHdr->getHeaderLength())
229  throw cRuntimeError("conn is null, and received packet has data");
230 
231  EV_WARN << "notifyAboutIncomingSegmentProcessing: conn is null\n";
232  }
233 }

◆ numInitStages()

virtual int inet::tcp::TcpLwip::numInitStages ( ) const
inlineoverrideprotectedvirtual
43 { return NUM_INIT_STAGES; }

◆ printConnBrief()

void inet::tcp::TcpLwip::printConnBrief ( TcpLwipConnection connP)
protected
581 {
582  EV_TRACE << this << ": connId=" << connP.connIdM;
583 }

Referenced by handleUpperCommand().

◆ refreshDisplay()

void inet::tcp::TcpLwip::refreshDisplay ( ) const
overrideprotectedvirtual
470 {
471  if (getEnvir()->isExpressMode()) {
472  // in express mode, we don't bother to update the display
473  // (std::map's iteration is not very fast if map is large)
474  getDisplayString().setTagArg("t", 0, "");
475  return;
476  }
477 
478  int numINIT = 0, numCLOSED = 0, numLISTEN = 0, numSYN_SENT = 0, numSYN_RCVD = 0,
479  numESTABLISHED = 0, numCLOSE_WAIT = 0, numLAST_ACK = 0, numFIN_WAIT_1 = 0,
480  numFIN_WAIT_2 = 0, numCLOSING = 0, numTIME_WAIT = 0;
481 
482  for (auto& elem : tcpAppConnMapM) {
483  LwipTcpLayer::tcp_pcb *pcb = (elem).second->pcbM;
484 
485  if (nullptr == pcb) {
486  numINIT++;
487  }
488  else {
489  enum LwipTcpLayer::tcp_state state = pcb->state;
490 
491  switch (state) {
492  case LwipTcpLayer::CLOSED:
493  numCLOSED++;
494  break;
495 
496  case LwipTcpLayer::LISTEN:
497  numLISTEN++;
498  break;
499 
500  case LwipTcpLayer::SYN_SENT:
501  numSYN_SENT++;
502  break;
503 
504  case LwipTcpLayer::SYN_RCVD:
505  numSYN_RCVD++;
506  break;
507 
508  case LwipTcpLayer::ESTABLISHED:
509  numESTABLISHED++;
510  break;
511 
512  case LwipTcpLayer::CLOSE_WAIT:
513  numCLOSE_WAIT++;
514  break;
515 
516  case LwipTcpLayer::LAST_ACK:
517  numLAST_ACK++;
518  break;
519 
520  case LwipTcpLayer::FIN_WAIT_1:
521  numFIN_WAIT_1++;
522  break;
523 
524  case LwipTcpLayer::FIN_WAIT_2:
525  numFIN_WAIT_2++;
526  break;
527 
528  case LwipTcpLayer::CLOSING:
529  numCLOSING++;
530  break;
531 
532  case LwipTcpLayer::TIME_WAIT:
533  numTIME_WAIT++;
534  break;
535  }
536  }
537  }
538 
539  char buf2[200];
540  buf2[0] = '\0';
541  if (numINIT > 0)
542  sprintf(buf2 + strlen(buf2), "init:%d ", numINIT);
543  if (numCLOSED > 0)
544  sprintf(buf2 + strlen(buf2), "closed:%d ", numCLOSED);
545  if (numLISTEN > 0)
546  sprintf(buf2 + strlen(buf2), "listen:%d ", numLISTEN);
547  if (numSYN_SENT > 0)
548  sprintf(buf2 + strlen(buf2), "syn_sent:%d ", numSYN_SENT);
549  if (numSYN_RCVD > 0)
550  sprintf(buf2 + strlen(buf2), "syn_rcvd:%d ", numSYN_RCVD);
551  if (numESTABLISHED > 0)
552  sprintf(buf2 + strlen(buf2), "estab:%d ", numESTABLISHED);
553  if (numCLOSE_WAIT > 0)
554  sprintf(buf2 + strlen(buf2), "close_wait:%d ", numCLOSE_WAIT);
555  if (numLAST_ACK > 0)
556  sprintf(buf2 + strlen(buf2), "last_ack:%d ", numLAST_ACK);
557  if (numFIN_WAIT_1 > 0)
558  sprintf(buf2 + strlen(buf2), "fin_wait_1:%d ", numFIN_WAIT_1);
559  if (numFIN_WAIT_2 > 0)
560  sprintf(buf2 + strlen(buf2), "fin_wait_2:%d ", numFIN_WAIT_2);
561  if (numCLOSING > 0)
562  sprintf(buf2 + strlen(buf2), "closing:%d ", numCLOSING);
563  if (numTIME_WAIT > 0)
564  sprintf(buf2 + strlen(buf2), "time_wait:%d ", numTIME_WAIT);
565 
566  getDisplayString().setTagArg("t", 0, buf2);
567 }

◆ removeConnection()

void inet::tcp::TcpLwip::removeConnection ( TcpLwipConnection conn)
protected
350 {
351  conn.pcbM->callback_arg = nullptr;
352  conn.pcbM = nullptr;
353  tcpAppConnMapM.erase(conn.connIdM);
354  conn.deleteModule();
355 }

Referenced by lwip_free_pcb_event(), and tcp_event_err().

◆ tcp_event_accept()

err_t inet::tcp::TcpLwip::tcp_event_accept ( TcpLwipConnection conn,
LwipTcpLayer::tcp_pcb *  pcb,
err_t  err 
)
protected
289 {
290  int newConnId = getEnvir()->getUniqueNumber();
291 
292  auto moduleType = cModuleType::get("inet.transportlayer.tcp_lwip.TcpLwipConnection");
293  char submoduleName[24];
294  sprintf(submoduleName, "conn-%d", newConnId);
295  auto newConn = check_and_cast<TcpLwipConnection *>(moduleType->create(submoduleName, this));
296  newConn->finalizeParameters();
297  newConn->buildInside();
298  newConn->initConnection(conn, newConnId, pcb);
299  newConn->callInitialize();
300 
301  // add into appConnMap
302  tcpAppConnMapM[newConnId] = newConn;
303 
304  newConn->sendAvailableIndicationToApp(conn.connIdM);
305 
306  EV_DETAIL << this << ": TcpLwip: got accept!\n";
307  return err;
308 }

Referenced by lwip_tcp_event().

◆ tcp_event_conn()

err_t inet::tcp::TcpLwip::tcp_event_conn ( TcpLwipConnection conn,
err_t  err 
)
protected
343 {
344  conn.sendEstablishedMsg();
345  conn.do_SEND();
346  return err;
347 }

Referenced by lwip_tcp_event().

◆ tcp_event_err()

err_t inet::tcp::TcpLwip::tcp_event_err ( TcpLwipConnection conn,
err_t  err 
)
protected
358 {
359  switch (err) {
360  case ERR_ABRT:
361  EV_INFO << "Connection " << conn.connIdM << " aborted, closed\n";
362  conn.sendIndicationToApp(TCP_I_CLOSED);
363  removeConnection(conn);
364  break;
365 
366  case ERR_RST:
367  EV_INFO << "Connection " << conn.connIdM << " reset\n";
368  conn.sendIndicationToApp(TCP_I_CONNECTION_RESET);
369  removeConnection(conn);
370  break;
371 
372  default:
373  throw cRuntimeError("Invalid LWIP error code: %d", err);
374  }
375 
376  return err;
377 }

Referenced by lwip_tcp_event().

◆ tcp_event_poll()

err_t inet::tcp::TcpLwip::tcp_event_poll ( TcpLwipConnection conn)
protected
380 {
381  conn.do_SEND();
382  return ERR_OK;
383 }

Referenced by lwip_tcp_event().

◆ tcp_event_recv()

err_t inet::tcp::TcpLwip::tcp_event_recv ( TcpLwipConnection conn,
struct pbuf p,
err_t  err 
)
protected
317 {
318  if (p == nullptr) {
319  // Received FIN:
320  EV_DETAIL << this << ": tcp_event_recv(" << conn.connIdM
321  << ", pbuf[nullptr], " << (int)err << "):FIN\n";
322  TcpStatusInd ind = (conn.pcbM->state == LwipTcpLayer::TIME_WAIT) ? TCP_I_CLOSED : TCP_I_PEER_CLOSED;
323  EV_INFO << "Connection " << conn.connIdM << ((ind == TCP_I_CLOSED) ? " closed" : "closed by peer") << endl;
324  conn.sendIndicationToApp(ind);
325  // TODO is it good?
326  pLwipTcpLayerM->tcp_recved(conn.pcbM, 0);
327  }
328  else {
329  EV_DETAIL << this << ": tcp_event_recv(" << conn.connIdM << ", pbuf[" << p->len << ", "
330  << p->tot_len << "], " << (int)err << ")\n";
331  for (auto c = p; c; c = c->next)
332  conn.receiveQueueM->enqueueTcpLayerData(c->payload, c->len);
333  pLwipTcpLayerM->tcp_recved(conn.pcbM, p->tot_len);
334  pbuf_free(p);
335  }
336 
337  conn.sendUpData();
338  conn.do_SEND();
339  return err;
340 }

Referenced by lwip_tcp_event().

◆ tcp_event_sent()

err_t inet::tcp::TcpLwip::tcp_event_sent ( TcpLwipConnection conn,
u16_t  size 
)
protected
311 {
312  conn.do_SEND();
313  return ERR_OK;
314 }

Referenced by lwip_tcp_event().

Member Data Documentation

◆ crcMode

CrcMode inet::tcp::TcpLwip::crcMode = CRC_MODE_UNDEFINED
protected

Referenced by initialize(), and ip_output().

◆ isAliveM

bool inet::tcp::TcpLwip::isAliveM = false
protected

Referenced by finish(), initialize(), and ~TcpLwip().

◆ netIf

struct netif inet::tcp::TcpLwip::netIf
protected

Referenced by ip_route(), and TcpLwip().

◆ pCurTcpSegM

Packet* inet::tcp::TcpLwip::pCurTcpSegM = nullptr
protected

◆ pLwipFastTimerM

cMessage* inet::tcp::TcpLwip::pLwipFastTimerM = nullptr
protected

Referenced by handleMessage(), initialize(), and ~TcpLwip().

◆ pLwipTcpLayerM

LwipTcpLayer* inet::tcp::TcpLwip::pLwipTcpLayerM = nullptr
protected

◆ tcpAppConnMapM


The documentation for this class was generated from the following files:
inet::tcp::TcpLwip::tcp_event_conn
err_t tcp_event_conn(TcpLwipConnection &conn, err_t err)
Definition: TcpLwip.cc:342
inet::findContainingNode
cModule * findContainingNode(const cModule *from)
Find the node containing the given module.
Definition: ModuleAccess.cc:31
inet::tcp::TcpLwip::netIf
struct netif netIf
Definition: TcpLwip.h:115
inet::tcp::TcpLwip::isAliveM
bool isAliveM
Definition: TcpLwip.h:119
inet::INITSTAGE_LAST
INET_API InitStage INITSTAGE_LAST
Operations that no other initializations can depend on, e.g.
inet::units::constants::c
const value< double, compose< units::m, pow< units::s, -1 > > > c(299792458)
inet::tcp::netif::output
err_t(* output)(struct netif *netif, struct pbuf *p, struct ip_addr *ipaddr)
This function is called by the IP module when it wants to send a packet on the interface.
Definition: netif.h:108
inet::tcp::netif::mtu
u16_t mtu
maximum transfer unit (in bytes)
Definition: netif.h:140
inet::tcp::TcpLwip::pCurTcpSegM
Packet * pCurTcpSegM
Definition: TcpLwip.h:120
inet::TCP_I_CLOSED
@ TCP_I_CLOSED
Definition: TcpCommand_m.h:130
protocol
removed DscpReq Ipv4ControlInfo Ipv6ControlInfo up L3AddressInd DispatchProtocolReq L4PortInd Ipv4ControlInfo Ipv6ControlInfo down protocol
Definition: IUdp-gates.txt:25
inet::tcp::netif::flags
u8_t flags
flags (see NETIF_FLAG_ above)
Definition: netif.h:146
inet::tcp::netif::ip_addr
struct ip_addr ip_addr
IP address configuration in network byte order.
Definition: netif.h:98
inet::Protocol::tcp
static const Protocol tcp
Definition: Protocol.h:112
inet::TCP_I_PEER_CLOSED
@ TCP_I_PEER_CLOSED
Definition: TcpCommand_m.h:129
inet::tcp::TcpLwip::pLwipFastTimerM
cMessage * pLwipFastTimerM
Definition: TcpLwip.h:112
inet::Packet::peekAtFront
const Ptr< const Chunk > peekAtFront(b length=b(-1), int flags=0) const
Returns the designated part from the beginning of the data part of the packet as an immutable chunk i...
Definition: Packet.h:245
inet::Protocol::icmpv4
static const Protocol icmpv4
Definition: Protocol.h:71
inet::CRC_COMPUTED
@ CRC_COMPUTED
Definition: CrcMode_m.h:59
inet::tcp::netif::netmask
struct ip_addr netmask
Definition: netif.h:99
DispatchProtocolReq
removed DscpReq Ipv4ControlInfo Ipv6ControlInfo up L3AddressInd DispatchProtocolReq L4PortInd Ipv4ControlInfo Ipv6ControlInfo down DispatchProtocolReq
Definition: IUdp-gates.txt:25
L3AddressInd
removed DscpReq Ipv4ControlInfo Ipv6ControlInfo up L3AddressInd L3AddressInd
Definition: IUdp-gates.txt:20
inet::parseCrcMode
CrcMode parseCrcMode(const char *crcModeString, bool allowDisable)
Definition: CrcMode.cc:14
connId
az accept haszálja pcb új connId
Definition: lwip_tcp.txt:42
inet::tcp::netif::input
err_t(* input)(struct pbuf *p, struct netif *inp)
This function is called by the network device driver to pass a packet up the TCP/IP stack.
Definition: netif.h:104
inet::TCP_I_CONNECTION_RESET
@ TCP_I_CONNECTION_RESET
Definition: TcpCommand_m.h:132
inet::tcp::ip_addr::addr
L3Address addr
Definition: ip_addr.h:50
inet::registerService
void registerService(const Protocol &protocol, cGate *gate, ServicePrimitive servicePrimitive)
Registers a service primitive (SDU processing) at the given gate.
Definition: IProtocolRegistrationListener.cc:14
ERR_ABRT
#define ERR_ABRT
Definition: err.h:64
PacketProtocolTag
removed DscpReq Ipv4ControlInfo Ipv6ControlInfo up L3AddressInd DispatchProtocolReq L4PortInd Ipv4ControlInfo Ipv6ControlInfo down PacketProtocolTag
Definition: IUdp-gates.txt:25
ip_hdr
Definition: ip.h.txt:84
inet::tcp::netif::next
struct netif * next
pointer to next in linked list
Definition: netif.h:95
inet::tcp::TcpLwip::printConnBrief
void printConnBrief(TcpLwipConnection &connP)
Definition: TcpLwip.cc:580
inet::units::units::B
intscale< b, 1, 8 > B
Definition: Units.h:1168
if
if(cwndVector) cwndVector -> record(state->snd_cwnd)
inet::insertTransportProtocolHeader
void insertTransportProtocolHeader(Packet *packet, const Protocol &protocol, const Ptr< TransportHeaderBase > &header)
Definition: L4Tools.cc:77
inet::tcp::netif::gw
struct ip_addr gw
Definition: netif.h:100
inet::tcp::netif::linkoutput
err_t(* linkoutput)(struct netif *netif, struct pbuf *p)
This function is called by the ARP module when it wants to send a packet on the interface.
Definition: netif.h:113
inet::INITSTAGE_TRANSPORT_LAYER
INET_API InitStage INITSTAGE_TRANSPORT_LAYER
Initialization of transport-layer protocols.
inet::tcp::TcpLwip::pLwipTcpLayerM
LwipTcpLayer * pLwipTcpLayerM
Definition: TcpLwip.h:118
ERR_RST
#define ERR_RST
Definition: err.h:65
inet::tcp::TcpLwip::tcp_event_accept
err_t tcp_event_accept(TcpLwipConnection &conn, LwipTcpLayer::tcp_pcb *pcb, err_t err)
Definition: TcpLwip.cc:288
inet::INITSTAGE_LOCAL
INET_API InitStage INITSTAGE_LOCAL
Initialization of local state that don't use or affect other modules includes:
NUM_INIT_STAGES
#define NUM_INIT_STAGES
Definition: InitStageRegistry.h:73
inet::tcp::TcpLwip::tcp_event_poll
err_t tcp_event_poll(TcpLwipConnection &conn)
Definition: TcpLwip.cc:379
inet::CRC_DECLARED_CORRECT
@ CRC_DECLARED_CORRECT
Definition: CrcMode_m.h:57
inet::tcp::TcpLwip::handleUpperCommand
void handleUpperCommand(cMessage *msgP)
Definition: TcpLwip.cc:390
inet::Protocol::icmpv6
static const Protocol icmpv6
Definition: Protocol.h:72
inet::tcp::TcpLwip::tcpAppConnMapM
TcpAppConnMap tcpAppConnMapM
Definition: TcpLwip.h:109
inet::CRC_DECLARED_INCORRECT
@ CRC_DECLARED_INCORRECT
Definition: CrcMode_m.h:58
inet::tcp::netif::num
u8_t num
number of this interface
Definition: netif.h:150
inet::NodeStatus::UP
@ UP
Definition: NodeStatus.h:28
ip_hdr::dest
struct ip_addr src dest
Definition: ip.h.txt:96
inet::tcp::TcpLwip::findAppConn
TcpLwipConnection * findAppConn(int connIdP)
Definition: TcpLwip.cc:569
tags
* tags
Definition: IUdp-gates.txt:3
inet::tcp::roundTime
simtime_t roundTime(const simtime_t &timeP, int secSlicesP)
Definition: TcpLwip.cc:418
inet::tcp::TcpLwip::tcp_event_recv
err_t tcp_event_recv(TcpLwipConnection &conn, struct pbuf *p, err_t err)
Definition: TcpLwip.cc:316
inet::tcp::netif::name
char name[2]
descriptive abbreviation
Definition: netif.h:148
inet::tcp::u16_t
uint16_t u16_t
Definition: cc.h:34
inet::tcp::TcpLwip::tcp_event_err
err_t tcp_event_err(TcpLwipConnection &conn, err_t err)
Definition: TcpLwip.cc:357
inet::tcp::netif::state
void * state
This field can be set by the device driver and could point to state information for the device.
Definition: netif.h:126
inet::tcp::TcpLwip::handleLowerPacket
void handleLowerPacket(Packet *packet)
Definition: TcpLwip.cc:131
inet::tcp::TcpLwip::tcp_event_sent
err_t tcp_event_sent(TcpLwipConnection &conn, u16_t size)
Definition: TcpLwip.cc:310
inet::registerProtocol
void registerProtocol(const Protocol &protocol, cGate *gate, ServicePrimitive servicePrimitive)
Registers a protocol primitive (PDU processing) at the given gate.
Definition: IProtocolRegistrationListener.cc:83
inet::tcp::TcpLwip::crcMode
CrcMode crcMode
Definition: TcpLwip.h:121
inet::TcpStatusInd
TcpStatusInd
Enum generated from inet/transportlayer/contract/tcp/TcpCommand.msg:41 by opp_msgtool.
Definition: TcpCommand_m.h:124
inet::tcp::pbuf_free
u8_t pbuf_free(struct pbuf *p)
Dereference a pbuf chain or queue and deallocate any no-longer-used pbufs at the head of this chain o...
Definition: pbuf.cc:559
ERR_OK
#define ERR_OK
Definition: err.h:56
inet::tcp::TcpLwip::removeConnection
void removeConnection(TcpLwipConnection &conn)
Definition: TcpLwip.cc:349