lwip-users
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [lwip-users] lwip-users Digest, Vol 114, Issue 28


From: Ted Smith
Subject: Re: [lwip-users] lwip-users Digest, Vol 114, Issue 28
Date: Thu, 28 Feb 2013 16:10:36 +0000

Thank you for the quick reply Stephane.   Let me warn you that I'm not an LWIP 
expert.  I believe I am doing as you suggest.  Here is some more information:

>>>>This thread gets into tcpip_apimsg() and posts to the mbox.

>>If you're talking about your netif driver giving the packets to the stack, 
>>then I think this is wrong.
>>You should use tcpip_input().
>>This function will create a TCPIP_MSG_INPKT message and sys_mbox_trypost() it 
>>to the tcpip thread.

I've set up my netif in the following way:

err_t EthernetInit(struct netif * netifPtr)
{
   ...
         netifPtr->output = etharp_output;    <== is this correct??
         netifPtr->linkoutput = low_level_output;   <== I've implemented this 
one
    ...
}


void Initialize()
{
   if(   
      netif_add(  &lwipNetif,        // a pre-allocated netif structure
      &lwipIpaddr,       // IP address for the new netif
      &lwipNetMask,      // network mask for the new netif
      &lwipGateway,      // default gateway IP address for the new netif
      0,                 // opaque data passed to the new netif
      EthernetInit,      // callback function that initializes the interface
      tcpip_input ) == 0)// callback function that is called to pass ingress 
packets up in the protocol layer stack.
   {                                                             
      assert(0);
   }

   netif_set_default(&lwipNetif);
   // initialize lwip
   tcpip_init(0, 0);
}

And I do the following to feed raw packets into the stack:

   static void ReceiveEthernetPktsThread(void *)
   {
      struct pbuf * newPbuf = 0;

      while(1)
      {
         //create a new pbuf if needed (usual case)
         if( newPbuf == 0 )
         {
            newPbuf = pbuf_alloc(PBUF_RAW, XEL_MAX_FRAME_SIZE, PBUF_POOL);
            assert(newPbuf);
            assert(newPbuf->len >= XEL_MAX_FRAME_SIZE); //entire payload had 
better be in this pbuf!
         }

         EnterCritical();
         unsigned length = XEmacLite_Recv(&emacInstance, (unsigned char 
*)newPbuf->payload);
         ExitCritical();
         if(length)
         {
            struct eth_hdr * ethHdrPtr = (struct eth_hdr *)newPbuf->payload;
#if LINK_STATS
            lwip_stats.link.recv++;
#endif

            switch( htons( ethHdrPtr->type ) )
            {
            case ETHTYPE_IP:
            case ETHTYPE_ARP:
#if PPPOE_SUPPORT
               /* PPPoE packet? */
            case ETHTYPE_PPPOEDISC:
            case ETHTYPE_PPPOE:
#endif /* PPPOE_SUPPORT */
               /* full packet send to tcpip_thread to process */
               if (lwipNetif.input(newPbuf, &lwipNetif)!=ERR_OK)
               { 
                  printf("ethernetif_input: IP input error\n");
                  pbuf_free(newPbuf);
               }
               break;

            default:
               // unknown type
               pbuf_free( newPbuf );
               printf("unknown eth type rcvd\n");
               break;
            }
            LINK_STATS_INC(link.recv);

            newPbuf = 0; //indicate a new pbuf must be allocated
         }
         else
         {
            WaitForPacketReceivedSignal();
         }
      }
   }


My TCP write function is simple calling lwip_write(socket, payload, size).

All of my testing is with one client server connection.  I am trying to keep 
the tcp window full at all times as a torture test.  I intentionally vary the 
execution times of the requests so the outbound responses come in bursts.



>>>Now a context switch occurs back to the outbound thread which finally makes 
>>>it to the same sys_arch_sem_wait() call and blocks.
>>>Now context is switched to the tcpip_thread which finish the do_write() 
>>>execution and calls TCPIP_APIMSG_ACK().
>>>This should have unblocked the outbound thread however the first one to 
>>>block on that sem was the inbound thread (which still has it's message 
>>>posted in the mbox) so the inbound thread receives the signal.
>>>Now the tcpip_thread() grabs the inbound msg (which container was on 
>>>the inbound thread's stack which has been popped) and starts processing the 
>>>message.? That container can now be corrupted since the stack has been 
>>>popped.
>>>Bad things happen after this.....

>>Of course, and this is why LwIP does not support multiple threads using the 
>>same socket (without the core locking option)

I'm only using a single thread to write to the socket.  I'm using a different 
thread to read from the socket.   The race condition appeared to be from the 
tcp_input() side which is in a 3rd thread.   Do I need to write from the same 
thread that is feeding the stack using tcp_input()? 


Thank you for your help.   I'm not clear on the threading limitations of LWIP.  
 I greatly appreciate your direction.

Ted


-------------------------------------------------------  
CONFIDENTIALITY NOTICE:
This email and any attachments are confidential information of the sender and 
are for the exclusive use of the intended recipient. If you are not the 
intended recipient, be aware that any disclosure, copying, distribution, or use 
of this email or any attachment is prohibited. If you have received this email 
in error, please notify us immediately by returning it to the sender and delete 
this copy from your system. Thank you for your cooperation.




reply via email to

[Prev in Thread] Current Thread [Next in Thread]