public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Michael Brown" <mcb30@ipxe.org>
To: devel@edk2.groups.io, "RichardHo [何明忠]" <richardho@ami.com>
Subject: Re: [edk2-devel] [PATCH 1/3] UsbNetworkPkg/UsbRndis: Add USB RNDIS devices support
Date: Wed, 11 Jan 2023 01:11:22 +0000	[thread overview]
Message-ID: <010201859e61b891-f355ea1c-08c2-4a5f-8568-f47097af6994-000000@eu-west-1.amazonses.com> (raw)
In-Reply-To: <53d2211e-d8ad-fafe-38ad-814ed77d19cf@ipxe.org>

On 09/01/2023 23:50, Michael Brown wrote:
> Coincidentally, I have just implemented a fix for this.  It works by 
> implementing a simple credit-based rate limiter.  Calls to 
> UsbEthReceive() are limited to 10 per second while the receive datapath 
> is idle.  No limiting takes place while the receive datapath is active.
> 
> Richard Ho: please consider using this rate limiting approach (or 
> something very similar).

I have updated the patch to run the timer callback at TPL_NOTIFY.  This 
seems to be required to avoid a long delay when the timer is disabled. 
(I have not investigated the root cause of this delay, but it is 100% 
reproducible.)

With this updated patch, I get almost no noticeable slowdown of the 
system and I am still able to receive data at around 100Mbps (which is 
about as good as it's likely to get, given the fundamental design flaws 
in EFI_USB_IO_PROTOCOL).

Updated patch:



diff --git a/UsbNetworkPkg/Include/Protocol/EdkIIUsbEthernetProtocol.h 
b/UsbNetworkPkg/Include/Protocol/EdkIIUsbEthernetProtocol.h
index df6ebc64ef..d0e2048114 100644
--- a/UsbNetworkPkg/Include/Protocol/EdkIIUsbEthernetProtocol.h
+++ b/UsbNetworkPkg/Include/Protocol/EdkIIUsbEthernetProtocol.h
@@ -160,6 +160,8 @@ typedef struct {
    UINT8                          CurrentNodeAddress[PXE_MAC_LENGTH];
    UINT8                          BroadcastNodeAddress[PXE_MAC_LENGTH];
    EFI_USB_DEVICE_REQUEST         Request;
+  EFI_EVENT                      RateLimiter;
+  UINTN                          RateLimitCredit;
  } NIC_DATA;

  #define NIC_DATA_SIGNATURE  SIGNATURE_32('n', 'i', 'c', 'd')
diff --git a/UsbNetworkPkg/NetworkCommon/DriverBinding.h 
b/UsbNetworkPkg/NetworkCommon/DriverBinding.h
index 946727ffc9..ae1d3c201e 100644
--- a/UsbNetworkPkg/NetworkCommon/DriverBinding.h
+++ b/UsbNetworkPkg/NetworkCommon/DriverBinding.h
@@ -25,6 +25,8 @@
  #define RX_BUFFER_COUNT                  32
  #define TX_BUFFER_COUNT                  32
  #define MEMORY_REQUIRE                   0
+#define RATE_LIMITER_INTERVAL            1000000  // 10Hz
+#define RATE_LIMITER_BURST               10

  #define UNDI_DEV_SIGNATURE  SIGNATURE_32('u','n','d','i')
  #define UNDI_DEV_FROM_THIS(a)  CR(a, NIC_DEVICE, NiiProtocol, 
UNDI_DEV_SIGNATURE)
diff --git a/UsbNetworkPkg/NetworkCommon/PxeFunction.c 
b/UsbNetworkPkg/NetworkCommon/PxeFunction.c
index fd53a215a4..e02402dc57 100644
--- a/UsbNetworkPkg/NetworkCommon/PxeFunction.c
+++ b/UsbNetworkPkg/NetworkCommon/PxeFunction.c
@@ -29,6 +29,21 @@ API_FUNC  gUndiApiTable[] = {
    UndiReceive
  };

+STATIC
+VOID
+EFIAPI
+UndiRateLimiterCallback (
+  IN  EFI_EVENT Event,
+  IN  VOID      *Context
+  )
+{
+  NIC_DATA *Nic = Context;
+
+  if (Nic->RateLimitCredit < RATE_LIMITER_BURST) {
+    Nic->RateLimitCredit++;
+  }
+}
+
  /**
    This command is used to determine the operational state of the UNDI.

@@ -100,9 +115,6 @@ UndiStart (
      Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
      Cdb->StatCode  = PXE_STATCODE_INVALID_CDB;
      return;
-  } else {
-    Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE;
-    Cdb->StatCode  = PXE_STATCODE_SUCCESS;
    }

    if (Nic->State != PXE_STATFLAGS_GET_STATE_STOPPED) {
@@ -120,14 +132,46 @@ UndiStart (
    Nic->PxeStart.UnMap_Mem = 0;
    Nic->PxeStart.Sync_Mem  = Cpb->Sync_Mem;
    Nic->PxeStart.Unique_ID = Cpb->Unique_ID;
-  Nic->State              = PXE_STATFLAGS_GET_STATE_STARTED;
+
+  Status = gBS->CreateEvent (
+    EVT_TIMER | EVT_NOTIFY_SIGNAL,
+    TPL_NOTIFY,
+    UndiRateLimiterCallback,
+    Nic,
+    &Nic->RateLimiter
+    );
+  if (EFI_ERROR (Status)) {
+    goto ErrorCreateEvent;
+  }
+
+  Status = gBS->SetTimer (
+    Nic->RateLimiter,
+    TimerPeriodic,
+    RATE_LIMITER_INTERVAL
+    );
+  if (EFI_ERROR (Status)) {
+    goto ErrorSetTimer;
+  }

    if (Nic->UsbEth->UsbEthUndi.UsbEthUndiStart != NULL) {
      Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiStart (Cdb, Nic);
      if (EFI_ERROR (Status)) {
-      Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
+      goto ErrorUndiStart;
      }
    }
+
+  Nic->State     = PXE_STATFLAGS_GET_STATE_STARTED;
+  Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE;
+  Cdb->StatCode  = PXE_STATCODE_SUCCESS;
+  return;
+
+ ErrorUndiStart:
+  gBS->SetTimer (&Nic->RateLimiter, TimerCancel, 0);
+ ErrorSetTimer:
+  gBS->CloseEvent (&Nic->RateLimiter);
+ ErrorCreateEvent:
+  Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
+  Cdb->StatCode  = PXE_STATCODE_DEVICE_FAILURE;
  }

  /**
@@ -183,6 +227,10 @@ UndiStop (
    Nic->PxeStart.Sync_Mem  = 0;
    Nic->State              = PXE_STATFLAGS_GET_STATE_STOPPED;

+  gBS->SetTimer (&Nic->RateLimiter, TimerCancel, 0);
+
+  gBS->CloseEvent (&Nic->RateLimiter);
+
    if (Nic->UsbEth->UsbEthUndi.UsbEthUndiStop != NULL) {
      Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiStop (Cdb, Nic);
      if (EFI_ERROR (Status)) {
@@ -1483,6 +1531,7 @@ Receive (
    )
  {
    EFI_STATUS       Status;
+  EFI_TPL          OriginalTpl;
    UINTN            Index;
    UINT16           StatCode;
    PXE_FRAME_TYPE   FrameType;
@@ -1506,8 +1555,15 @@ Receive (
    }

    while (1) {
+    if (Nic->RateLimitCredit == 0) {
+      break;
+    }
+
      Status = Nic->UsbEth->UsbEthReceive (Cdb, Nic->UsbEth, (VOID 
*)BulkInData, &DataLength);
      if (EFI_ERROR (Status)) {
+      OriginalTpl = gBS->RaiseTPL (TPL_NOTIFY);
+      Nic->RateLimitCredit--;
+      gBS->RestoreTPL (OriginalTpl);
        break;
      }



Thanks,

Michael


  parent reply	other threads:[~2023-01-11  1:11 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-12-08  3:44 [PATCH 1/3] UsbNetworkPkg/UsbRndis: Add USB RNDIS devices support RichardHo [何明忠]
2022-12-08  4:41 ` [edk2-devel] " Rebecca Cran
2022-12-08  4:57 ` Rebecca Cran
2022-12-12  5:48   ` RichardHo [何明忠]
2023-01-08 10:41     ` tinhnguyen
2023-01-09 23:50       ` Michael Brown
2023-01-12  8:36         ` RichardHo [何明忠]
2023-01-20 21:36           ` Rebecca Cran
2023-02-05  8:04           ` Tinh Nguyen
2023-02-05 10:26             ` Michael Brown
2023-01-10  5:07       ` Rebecca Cran
2023-01-11  7:34         ` tinhnguyen
2023-01-11  9:55           ` Michael Brown
2023-01-11 10:56             ` Tinh Nguyen
     [not found]       ` <53d2211e-d8ad-fafe-38ad-814ed77d19cf@ipxe.org>
2023-01-11  1:11         ` Michael Brown [this message]
2023-01-11  1:17 ` Michael Brown
2023-01-11  9:47   ` RichardHo [何明忠]
  -- strict thread matches above, loose matches on Subject: below --
2022-10-03  9:26 RichardHo [何明忠]
2022-12-01 15:46 ` [edk2-devel] " Rebecca Cran
2022-12-02 10:42   ` RichardHo [何明忠]
2022-12-02 10:09 ` Michael Brown
2022-12-02 10:42   ` RichardHo [何明忠]
2022-12-02 11:49   ` Chang, Abner
2022-12-02 23:27 ` Rebecca Cran

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=010201859e61b891-f355ea1c-08c2-4a5f-8568-f47097af6994-000000@eu-west-1.amazonses.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox