Skip to content

Commit

Permalink
netdev/upper: Delay replied packets to prevent TX quota become negated
Browse files Browse the repository at this point in the history
When our netstack is replying packets when processing RX, the replied
packets will be sent without considering of TX quota because we don't
want to drop them. Now we may delay them by pushing them to a queue and
send them later, which can always keep quota working.

Signed-off-by: Zhe Weng <[email protected]>
  • Loading branch information
wengzhe authored and anchao committed Aug 19, 2024
1 parent 9b253ee commit 4b5585a
Showing 1 changed file with 110 additions and 6 deletions.
116 changes: 110 additions & 6 deletions drivers/net/netdev_upperhalf.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,12 @@ struct netdev_upperhalf_s
#else
struct work_s work;
#endif

/* TX queue for re-queueing replies */

#if CONFIG_IOB_NCHAINS > 0
struct iob_queue_s txq;
#endif
};

/****************************************************************************
Expand Down Expand Up @@ -279,7 +285,7 @@ static inline bool netdev_upper_can_tx(FAR struct netdev_upperhalf_s *upper)
*
* Returned Value:
* Negated errno value - Error number that occurs.
* OK - Driver can send more, continue the poll.
* NETDEV_TX_CONTINUE - Driver can send more, continue the poll.
*
* Assumptions:
* Called with the network locked.
Expand Down Expand Up @@ -329,6 +335,44 @@ static int netdev_upper_txpoll(FAR struct net_driver_s *dev)
return NETDEV_TX_CONTINUE;
}

/****************************************************************************
* Name: netdev_upper_tx
*
* Description:
* Do the actual transmission of packets, including pre-queued packets and
* packets from the network stack.
*
* Input Parameters:
* dev - Reference to the NuttX driver state structure
*
* Returned Value:
* Negated errno value - Error number that occurs.
* NETDEV_TX_CONTINUE - Driver can send more, continue the poll.
*
* Assumptions:
* Called with the network locked.
*
****************************************************************************/

static int netdev_upper_tx(FAR struct net_driver_s *dev)
{
#if CONFIG_IOB_NCHAINS > 0
FAR struct netdev_upperhalf_s *upper = dev->d_private;

if (!IOB_QEMPTY(&upper->txq))
{
/* Put the packet back to the device */

netdev_iob_replace(dev, iob_remove_queue(&upper->txq));
return netdev_upper_txpoll(dev);
}
#endif

/* No more TX packets in queue, poll the net stack to get more packets */

return devif_poll(dev, netdev_upper_txpoll);
}

/****************************************************************************
* Name: netdev_upper_txavail_work
*
Expand All @@ -353,10 +397,62 @@ static void netdev_upper_txavail_work(FAR struct netdev_upperhalf_s *upper)
{
DEBUGASSERT(dev->d_buf == NULL); /* Make sure: IOB only. */
while (netdev_upper_can_tx(upper) &&
devif_poll(dev, netdev_upper_txpoll) == NETDEV_TX_CONTINUE);
netdev_upper_tx(dev) == NETDEV_TX_CONTINUE);
}
}

/****************************************************************************
* Name: netdev_upper_queue_tx
*
* Description:
* Queue a TX packet to the upper half for sending later.
*
* Input Parameters:
* dev - Reference to the NuttX driver state structure
*
* Assumptions:
* Called with the network locked.
*
****************************************************************************/

#if defined(CONFIG_NET_LOOPBACK) || defined(CONFIG_NET_ETHERNET) || \
defined(CONFIG_DRIVERS_IEEE80211) || defined(CONFIG_NET_MBIM)
static void netdev_upper_queue_tx(FAR struct net_driver_s *dev)
{
#if CONFIG_IOB_NCHAINS > 0
FAR struct netdev_upperhalf_s *upper = dev->d_private;
int ret;

if ((ret = iob_tryadd_queue(dev->d_iob, &upper->txq)) >= 0)
{
netdev_iob_clear(dev);
}
else
{
nwarn("WARNING: Failed to queue TX packet, dropping: %d\n", ret);
}
#else
/* Fall back to send the packet directly if we don't have IOB queue. */

netdev_upper_txpoll(dev);
#endif
}
#endif

/****************************************************************************
* Name: eth_input
*
* Description:
* Handle L2 packet input.
*
* Input Parameters:
* dev - Reference to the NuttX network driver state structure
*
* Assumptions:
* Called with the network locked.
*
****************************************************************************/

#if defined(CONFIG_NET_LOOPBACK) || defined(CONFIG_NET_ETHERNET) || \
defined(CONFIG_DRIVERS_IEEE80211)
static void eth_input(FAR struct net_driver_s *dev)
Expand Down Expand Up @@ -432,9 +528,11 @@ static void eth_input(FAR struct net_driver_s *dev)

if (dev->d_len > 0)
{
/* And send the packet */
/* And queue the packet for sending later.
* Note: RX is tried before TX, so we don't need to call txavail here.
*/

netdev_upper_txpoll(dev);
netdev_upper_queue_tx(dev);
}
}
#endif
Expand Down Expand Up @@ -495,9 +593,11 @@ static void ip_input(FAR struct net_driver_s *dev)

if (dev->d_len > 0)
{
/* And send the packet */
/* And queue the packet for sending later.
* Note: RX is tried before TX, so we don't need to call txavail here.
*/

netdev_upper_txpoll(dev);
netdev_upper_queue_tx(dev);
}
}
#endif
Expand Down Expand Up @@ -1149,6 +1249,10 @@ int netdev_lower_unregister(FAR struct netdev_lowerhalf_s *dev)
nxsem_destroy(&upper->sem_exit);
#endif

#if CONFIG_IOB_NCHAINS > 0
iob_free_queue(&upper->txq);
#endif

kmm_free(upper);
dev->netdev.d_private = NULL;

Expand Down

0 comments on commit 4b5585a

Please sign in to comment.