david/ipxe
david
/
ipxe
Archived
1
0
Fork 0

[netdevice] Allow per-device receive queue processing to be frozen

Several use cases (e.g. the UNDI API and the EFI SNP API) require
access to the raw network device receive queue, and so currently use
manual calls to netdev_poll() on a specific network device in order to
prevent received packets from being processed by the network stack.

As an alternative, provide a flag that allows receive queue processing
to be frozen on a per-device basis.  When receive queue processing is
frozen, packets will be enqueued as normal, but will not be
automatically dequeued and passed up the network stack.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
Michael Brown 2010-11-20 04:56:25 +00:00
parent 006d9f1f60
commit 4576c2da58
2 changed files with 57 additions and 6 deletions

View File

@ -343,6 +343,9 @@ struct net_device {
/** Network device interrupts are enabled */
#define NETDEV_IRQ_ENABLED 0x0002
/** Network device receive queue processing is frozen */
#define NETDEV_RX_FROZEN 0x0004
/** Link-layer protocol table */
#define LL_PROTOCOLS __table ( struct ll_protocol, "ll_protocols" )
@ -505,7 +508,7 @@ netdev_link_ok ( struct net_device *netdev ) {
* Check whether or not network device is open
*
* @v netdev Network device
* @v is_open Network device is open
* @ret is_open Network device is open
*/
static inline __attribute__ (( always_inline )) int
netdev_is_open ( struct net_device *netdev ) {
@ -516,13 +519,24 @@ netdev_is_open ( struct net_device *netdev ) {
* Check whether or not network device interrupts are currently enabled
*
* @v netdev Network device
* @v irq_enabled Network device interrupts are enabled
* @ret irq_enabled Network device interrupts are enabled
*/
static inline __attribute__ (( always_inline )) int
netdev_irq_enabled ( struct net_device *netdev ) {
return ( netdev->state & NETDEV_IRQ_ENABLED );
}
/**
* Check whether or not network device receive queue processing is frozen
*
* @v netdev Network device
* @ret rx_frozen Network device receive queue processing is frozen
*/
static inline __attribute__ (( always_inline )) int
netdev_rx_frozen ( struct net_device *netdev ) {
return ( netdev->state & NETDEV_RX_FROZEN );
}
extern void netdev_link_err ( struct net_device *netdev, int rc );
extern void netdev_link_down ( struct net_device *netdev );
extern int netdev_tx ( struct net_device *netdev, struct io_buffer *iobuf );
@ -550,6 +564,7 @@ extern int net_tx ( struct io_buffer *iobuf, struct net_device *netdev,
extern int net_rx ( struct io_buffer *iobuf, struct net_device *netdev,
uint16_t net_proto, const void *ll_dest,
const void *ll_source );
extern void net_poll ( void );
/**
* Complete network transmission
@ -585,4 +600,24 @@ netdev_link_up ( struct net_device *netdev ) {
netdev_link_err ( netdev, 0 );
}
/**
* Freeze network device receive queue processing
*
* @v netdev Network device
*/
static inline __attribute__ (( always_inline )) void
netdev_rx_freeze ( struct net_device *netdev ) {
netdev->state |= NETDEV_RX_FROZEN;
}
/**
* Unfreeze network device receive queue processing
*
* @v netdev Network device
*/
static inline __attribute__ (( always_inline )) void
netdev_rx_unfreeze ( struct net_device *netdev ) {
netdev->state &= ~NETDEV_RX_FROZEN;
}
#endif /* _IPXE_NETDEVICE_H */

View File

@ -669,14 +669,12 @@ int net_rx ( struct io_buffer *iobuf, struct net_device *netdev,
}
/**
* Single-step the network stack
*
* @v process Network stack process
* Poll the network stack
*
* This polls all interfaces for received packets, and processes
* packets from the RX queue.
*/
static void net_step ( struct process *process __unused ) {
void net_poll ( void ) {
struct net_device *netdev;
struct io_buffer *iobuf;
struct ll_protocol *ll_protocol;
@ -691,6 +689,15 @@ static void net_step ( struct process *process __unused ) {
/* Poll for new packets */
netdev_poll ( netdev );
/* Leave received packets on the queue if receive
* queue processing is currently frozen. This will
* happen when the raw packets are to be manually
* dequeued using netdev_rx_dequeue(), rather than
* processed via the usual networking stack.
*/
if ( netdev_rx_frozen ( netdev ) )
continue;
/* Process at most one received packet. Give priority
* to getting packets out of the NIC over processing
* the received packets, because we advertise a window
@ -723,6 +730,15 @@ static void net_step ( struct process *process __unused ) {
}
}
/**
* Single-step the network stack
*
* @v process Network stack process
*/
static void net_step ( struct process *process __unused ) {
net_poll();
}
/** Networking stack process */
struct process net_process __permanent_process = {
.list = LIST_HEAD_INIT ( net_process.list ),