Built-in IP stack: is it normal / accepted to have asynchronous sending?

I am trying to implement a very small IP stack for 8-bit AVR MCUs. I do not want it to support TCP because it is really too big and I do not need it, but rather UDP (and, of course, ARP and ICMP).

I want the stack code to fit in 16 kilobytes of ROM and 1 kilobyte of RAM, of course, allowing as much space as possible for the application. I use an ENC28J60 based board for PHY / MAC control, which has an internal 8KB RX / TX circular buffer. When packets arrive on this chip, it writes them one by one to the RX buffer, but does not overwrite the oldest one. The oldest pointer indicates the pointer that needs to be updated to indicate the next package when the user has read it. It also sends an interrupt to one of its contacts when a new package arrives.

For the RX part, I want to work in the same way as lwIP: to signal that a new packet is ready when we receive an interrupt (save its address and size), but continue it only when the user calls our IP stack function. This should work fine; if the user does not call our function often enough, new arriving packets will be discarded and what it will be. The user provides a stack with a UDP callback.

Now the problem is in TX. Let's say I want to send a UDP packet to some IP address, for which I do not know the link address. An ARP request must be sent before sending my package. What if UDP packet comes before ARP reply? It should be handled by my UDP callback, but what if I want to send some of this callback? I'm still waiting for a response from ARP here. Surely this locking mechanism is wrong.

My question is: Is it good / accepted to have asynchronous sending? Thus, if I want to send something, I provide a send function with a callback and is called when a UDP packet can be sent. Thus, everything is event driven.

+4
source share
2 answers

As for the β€œacceptable” for asynchronous sending, I can’t imagine why this would be a problem if you can implement this in your code size requirements.

As for the best way to implement such a scheme, I don’t know how large the packet size you want to support (I guess much less than the theoretical maximum of 64K), but I would allocate a ring of send buffers, and whenever the process responsible for the actual sending to the hardware providing, executing its loop / interrupt / independently, it checked each live buffer for its ARP status (has an ARP record, ARP request, ARP request timeout, ARP record or request outstanding data) and take appropriate actions (with Responsibly: click on the equipment with the corresponding MAC address, skip this time, refuse, send an ARP request). You can run this send procedure every time the ARP table is updated so that you can meet any required requirements in real time (although some people have argued that Ethernet is not and never will be a real-time capable system, but this is a topic for another forum that is not against flamewars).

+2
source

Do you have two callbacks (mostly async paths), one for receiving from the IP layer and one for sending to IP?

Also, if you implement layers, I think the IP send / route function should take care of the ARP response at that level.

+1
source

All Articles