Forum Discussion
Altera_Forum
Honored Contributor
13 years agoHello,
we used the lwIP port in our project, and experienced problems when there is heavy traffic. After some research, two bugs were fixed, related to concurrency (variable names are renamed w.r.t. the original sources): - function low_level_input in alteraTseEthernetif: critical section needs to be extended (next_packet must be assigned within critical section; otherwise, when the ISR would be called in the mean time, it may result in the current packet being overwritten by the new one):
// start the critical section by disabling IRQs
const alt_irq_context cpu_sr = alt_irq_disable_all();
// decrement packet counter
--tse_info->mRxCount;
// assign current packet from lwIP packet buffer as the new data
*data = tse_info->mRxBuffer;
// assign next packet instead and move forward in buffer
tse_info->mRxBuffer = (void*)next_packet;
if (++tse_info->mRxIndex >= TSE_RX_BUFFER)
{
tse_info->mRxIndex = UINT32_L(0);
}
// stop the critical section by enabling IRQs
alt_irq_enable_all(cpu_sr);
- function tse_mac_recv in lwip_tse_mac.c: (mRxCount > TSE_RX_BUFFER) ==> (mRxCount >= (TSE_RX_BUFFER - 1)); may otherwise result in packets being overwritten
// check if contents of memory are valid
if ((IORD_ALTERA_TSE_SGDMA_DESC_STATUS(&tse_info->mSgdmaDescriptor) & (ALTERA_AVALON_SGDMA_DESCRIPTOR_STATUS_E_CRC_MSK | ALTERA_AVALON_SGDMA_DESCRIPTOR_STATUS_E_PARITY_MSK | ALTERA_AVALON_SGDMA_DESCRIPTOR_STATUS_E_OVERFLOW_MSK |ALTERA_AVALON_SGDMA_DESCRIPTOR_STATUS_E_SYNC_MSK | ALTERA_AVALON_SGDMA_DESCRIPTOR_STATUS_E_UEOP_MSK | ALTERA_AVALON_SGDMA_DESCRIPTOR_STATUS_E_MEOP_MSK | ALTERA_AVALON_SGDMA_DESCRIPTOR_STATUS_E_MSOP_MSK )) == 0)
{
// contents are valid
// check if there is place for the next packet
// this function always prepares for the next DMA transfer, so at least one packet must be available for that
if (tse_info->mRxCount >= (TSE_RX_BUFFER - UINT32_L(1)))
{
// there is no place
// drop this packet
LINK_STATS_INC(link.drop);
}
else
{
// there is place
// allow this packet
++tse_info->mRxCount;
if (++tse_info->mRxIndexIsr >= TSE_RX_BUFFER)
{
tse_info->mRxIndexIsr = UINT32_L(0);
}
}
}
else
{
// contents are invalid
// drop this packet
LINK_STATS_INC(link.drop);
}
greetings, Stephan Orban