Browse Source

[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>
tags/v1.20.1
Michael Brown 13 years ago
parent
commit
4576c2da58
2 changed files with 57 additions and 6 deletions
  1. 37
    2
      src/include/ipxe/netdevice.h
  2. 20
    4
      src/net/netdevice.c

+ 37
- 2
src/include/ipxe/netdevice.h View File

@@ -343,6 +343,9 @@ struct net_device {
343 343
 /** Network device interrupts are enabled */
344 344
 #define NETDEV_IRQ_ENABLED 0x0002
345 345
 
346
+/** Network device receive queue processing is frozen */
347
+#define NETDEV_RX_FROZEN 0x0004
348
+
346 349
 /** Link-layer protocol table */
347 350
 #define LL_PROTOCOLS __table ( struct ll_protocol, "ll_protocols" )
348 351
 
@@ -505,7 +508,7 @@ netdev_link_ok ( struct net_device *netdev ) {
505 508
  * Check whether or not network device is open
506 509
  *
507 510
  * @v netdev		Network device
508
- * @v is_open		Network device is open
511
+ * @ret is_open		Network device is open
509 512
  */
510 513
 static inline __attribute__ (( always_inline )) int
511 514
 netdev_is_open ( struct net_device *netdev ) {
@@ -516,13 +519,24 @@ netdev_is_open ( struct net_device *netdev ) {
516 519
  * Check whether or not network device interrupts are currently enabled
517 520
  *
518 521
  * @v netdev		Network device
519
- * @v irq_enabled	Network device interrupts are enabled
522
+ * @ret irq_enabled	Network device interrupts are enabled
520 523
  */
521 524
 static inline __attribute__ (( always_inline )) int
522 525
 netdev_irq_enabled ( struct net_device *netdev ) {
523 526
 	return ( netdev->state & NETDEV_IRQ_ENABLED );
524 527
 }
525 528
 
529
+/**
530
+ * Check whether or not network device receive queue processing is frozen
531
+ *
532
+ * @v netdev		Network device
533
+ * @ret rx_frozen	Network device receive queue processing is frozen
534
+ */
535
+static inline __attribute__ (( always_inline )) int
536
+netdev_rx_frozen ( struct net_device *netdev ) {
537
+	return ( netdev->state & NETDEV_RX_FROZEN );
538
+}
539
+
526 540
 extern void netdev_link_err ( struct net_device *netdev, int rc );
527 541
 extern void netdev_link_down ( struct net_device *netdev );
528 542
 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,
550 564
 extern int net_rx ( struct io_buffer *iobuf, struct net_device *netdev,
551 565
 		    uint16_t net_proto, const void *ll_dest,
552 566
 		    const void *ll_source );
567
+extern void net_poll ( void );
553 568
 
554 569
 /**
555 570
  * Complete network transmission
@@ -585,4 +600,24 @@ netdev_link_up ( struct net_device *netdev ) {
585 600
 	netdev_link_err ( netdev, 0 );
586 601
 }
587 602
 
603
+/**
604
+ * Freeze network device receive queue processing
605
+ *
606
+ * @v netdev		Network device
607
+ */
608
+static inline __attribute__ (( always_inline )) void
609
+netdev_rx_freeze ( struct net_device *netdev ) {
610
+	netdev->state |= NETDEV_RX_FROZEN;
611
+}
612
+
613
+/**
614
+ * Unfreeze network device receive queue processing
615
+ *
616
+ * @v netdev		Network device
617
+ */
618
+static inline __attribute__ (( always_inline )) void
619
+netdev_rx_unfreeze ( struct net_device *netdev ) {
620
+	netdev->state &= ~NETDEV_RX_FROZEN;
621
+}
622
+
588 623
 #endif /* _IPXE_NETDEVICE_H */

+ 20
- 4
src/net/netdevice.c View File

@@ -669,14 +669,12 @@ int net_rx ( struct io_buffer *iobuf, struct net_device *netdev,
669 669
 }
670 670
 
671 671
 /**
672
- * Single-step the network stack
673
- *
674
- * @v process		Network stack process
672
+ * Poll the network stack
675 673
  *
676 674
  * This polls all interfaces for received packets, and processes
677 675
  * packets from the RX queue.
678 676
  */
679
-static void net_step ( struct process *process __unused ) {
677
+void net_poll ( void ) {
680 678
 	struct net_device *netdev;
681 679
 	struct io_buffer *iobuf;
682 680
 	struct ll_protocol *ll_protocol;
@@ -691,6 +689,15 @@ static void net_step ( struct process *process __unused ) {
691 689
 		/* Poll for new packets */
692 690
 		netdev_poll ( netdev );
693 691
 
692
+		/* Leave received packets on the queue if receive
693
+		 * queue processing is currently frozen.  This will
694
+		 * happen when the raw packets are to be manually
695
+		 * dequeued using netdev_rx_dequeue(), rather than
696
+		 * processed via the usual networking stack.
697
+		 */
698
+		if ( netdev_rx_frozen ( netdev ) )
699
+			continue;
700
+
694 701
 		/* Process at most one received packet.  Give priority
695 702
 		 * to getting packets out of the NIC over processing
696 703
 		 * the received packets, because we advertise a window
@@ -723,6 +730,15 @@ static void net_step ( struct process *process __unused ) {
723 730
 	}
724 731
 }
725 732
 
733
+/**
734
+ * Single-step the network stack
735
+ *
736
+ * @v process		Network stack process
737
+ */
738
+static void net_step ( struct process *process __unused ) {
739
+	net_poll();
740
+}
741
+
726 742
 /** Networking stack process */
727 743
 struct process net_process __permanent_process = {
728 744
 	.list = LIST_HEAD_INIT ( net_process.list ),

Loading…
Cancel
Save