]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[netdevice] Allow per-device receive queue processing to be frozen
authorMichael Brown <mcb30@ipxe.org>
Sat, 20 Nov 2010 04:56:25 +0000 (04:56 +0000)
committerMichael Brown <mcb30@ipxe.org>
Sat, 20 Nov 2010 15:46:00 +0000 (15:46 +0000)
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>
src/include/ipxe/netdevice.h
src/net/netdevice.c

index 4649377a678d10bedc329bd34b7f52b2338f35c1..26e2ab8978a2bb6b207a4b6f9cd9362560a0ed44 100644 (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 */
index c6c377b52aef396ea46397245f82b272b11dc0df..90dab8fbeabebe187bbd2617e183c0daf6094345 100644 (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 ),