I'm using an TCP/IP stack called lwip. I have implemented a function below to send data packets, inspired from a similar callback function that receives data packets.
Each time a packet is received, I create a buffer using the pbuf_alloc
function. Then, I send the packet using udp_sendto
. Finally, I free the buffer using pbuf_free
. (See the code below.)
For some reason, pbuf_free
is not freeing the buffer. (I get a buffer overflow after n
packets, where n
is the pool size.) The lwip wiki warns that:
The network driver may also not assume that the pbuf memory is actually freed when it calls pbuf_free.
How can I force pbuf_free
to free my buffer? How is the buffer overflow avoided?
(My implementation below.)
static err_t IAP_tftp_send_data_packet(struct udp_pcb *upcb, struct ip_addr *to, int to_port, int block)
{
err_t err;
struct pbuf *pkt_buf;
char packet[TFTP_DATA_PKT_LEN_MAX];
int bytesRead;
int bytesToSend;
/* Specify that we are sending data. */
IAP_tftp_set_opcode(packet, TFTP_DATA);
/* Specify the block number that we are sending. */
IAP_tftp_set_block(packet, block);
bytesRead = IAP_tftp_set_data(packet, block);
if(bytesRead != 0) {
bytesToSend = TFTP_DATA_PKT_LEN_MAX - (512 - bytesRead + 1);
} else {
bytesToSend = TFTP_DATA_PKT_LEN_MAX - 512;
}
pkt_buf = pbuf_alloc(PBUF_TRANSPORT, bytesToSend, PBUF_POOL);
if (!pkt_buf)
{
print("(TFTP) Buffer overflow!\r\n");
}
/* Copy the file data onto pkt_buf. */
memcpy(pkt_buf->payload, packet, bytesToSend);
err = udp_sendto(upcb, pkt_buf, to, to_port);
/* free the buffer pbuf */
printf("%d\n\r", pbuf_free(pkt_buf));
return err;
}
What version of lwIP are you using? Depending on different versions the answers vary a lot.
The memp_malloc() allocation function called inside the pbuf_alloc() has failed or the pbufs chaining has failed.So, it returns NULL.
pbuf_alloc() will also return NULL, if the passed arguments also contains NULL.(due to NULL arguments check).
In newer versions, could you show what value the MEMP_OVERFLOW_CHECK macro contains? The lwIP shows a diferent behavior when the macro value >= 2.
And another cause might be if you are using multi-threading, the locking mechanisms inside the pbuf_alloc() fail, might cause it to return NULL.
Some versions require that you call pbuf_init(), before calling pbuf_alloc().
You can try this:
pkt_buf = NULL;//Use NULL, just incase the NULL is not 0 as per your compiler.
pkt_buf = pbuf_alloc(PBUF_TRANSPORT, bytesToSend, PBUF_REF);
if(pkt_buf == NULL)
{
printf("pbuf_alloc failed.\n");
}
else
{
/* Do something with the allocated pbufs and free it. */
}
PBUF_REF will allocate no buffer memory for pbuf. The pbuf should be used in a single thread only and if the pbuf gets queued, then pbuf_take should be called to copy the buffer.
You can also try PBUF_RAM which will allocate buffer in RAM.
For more informtaion, you can also browse the source files of the version of lwIP, that you are using.