[haiku-commits] Change in haiku[master]: usb_rndis: accept incoming USB transfers up to 0x4000 size

  • From: Gerrit <review@xxxxxxxxxxxxxxxxxxx>
  • To: waddlesplash <waddlesplash@xxxxxxxxx>, haiku-commits@xxxxxxxxxxxxx
  • Date: Sat, 14 May 2022 10:55:56 +0000

From Adrien Destugues <pulkomandy@xxxxxxxxx>:

Adrien Destugues has uploaded this change for review. ( 
https://review.haiku-os.org/c/haiku/+/5312 ;)


Change subject: usb_rndis: accept incoming USB transfers up to 0x4000 size
......................................................................

usb_rndis: accept incoming USB transfers up to 0x4000 size

As required by the spec. Then split them into multiple ethernet frames
as needed.
---
M src/add-ons/kernel/drivers/network/ether/usb_rndis/RNDISDevice.cpp
M src/add-ons/kernel/drivers/network/ether/usb_rndis/RNDISDevice.h
2 files changed, 50 insertions(+), 44 deletions(-)



  git pull ssh://git.haiku-os.org:22/haiku refs/changes/12/5312/1

diff --git a/src/add-ons/kernel/drivers/network/ether/usb_rndis/RNDISDevice.cpp 
b/src/add-ons/kernel/drivers/network/ether/usb_rndis/RNDISDevice.cpp
index 23e07ed..44a30b0 100644
--- a/src/add-ons/kernel/drivers/network/ether/usb_rndis/RNDISDevice.cpp
+++ b/src/add-ons/kernel/drivers/network/ether/usb_rndis/RNDISDevice.cpp
@@ -74,6 +74,7 @@
                fNotifyReadSem(-1),
                fNotifyWriteSem(-1),
                fNotifyControlSem(-1),
+               fReadHeader(NULL),
                fLinkStateChangeSem(-1),
                fMediaConnectState(MEDIA_STATE_UNKNOWN),
                fDownstreamSpeed(0)
@@ -243,72 +244,75 @@
                return B_DEVICE_NOT_FOUND;
        }

-       iovec vec[2];
-       uint32 header[11] = { 0 };
-
-       vec[0].iov_base = &header;
-       vec[0].iov_len = sizeof(header);
-
-       vec[1].iov_base = buffer;
-       vec[1].iov_len = *numBytes;
-
-       status_t result = gUSBModule->queue_bulk_v(fReadEndpoint, vec, 2,
-               _ReadCallback, this);
-       if (result != B_OK) {
-               *numBytes = 0;
-               return result;
-       }
-
-       result = acquire_sem_etc(fNotifyReadSem, 1, B_CAN_INTERRUPT, 0);
-       if (result < B_OK) {
-               *numBytes = 0;
-               return result;
-       }
-
-       if (fStatusRead != B_OK && fStatusRead != B_CANCELED && !fRemoved) {
-               TRACE_ALWAYS("device status error 0x%08" B_PRIx32 "\n", 
fStatusRead);
-               result = gUSBModule->clear_feature(fReadEndpoint,
-                       USB_FEATURE_ENDPOINT_HALT);
+       // The read funcion can return only one packet at a time, but we can 
receive multiple ones in
+       // a single USB transfer. So we need to buffer them, and check if we 
have something in our
+       // buffer for each Read() call before scheduling a new USB transfer. 
This would be more
+       // efficient if the network stack had a way to read multiple frames at 
once.
+       if (fReadHeader == NULL) {
+               status_t result = gUSBModule->queue_bulk(fReadEndpoint, 
fReadBuffer, sizeof(fReadBuffer),
+                       _ReadCallback, this);
                if (result != B_OK) {
-                       TRACE_ALWAYS("failed to clear halt state on read\n");
                        *numBytes = 0;
                        return result;
                }
+
+               result = acquire_sem_etc(fNotifyReadSem, 1, B_CAN_INTERRUPT, 0);
+               if (result < B_OK) {
+                       *numBytes = 0;
+                       return result;
+               }
+
+               if (fStatusRead != B_OK && fStatusRead != B_CANCELED && 
!fRemoved) {
+                       TRACE_ALWAYS("device status error 0x%08" B_PRIx32 "\n", 
fStatusRead);
+                       result = gUSBModule->clear_feature(fReadEndpoint,
+                               USB_FEATURE_ENDPOINT_HALT);
+                       if (result != B_OK) {
+                               TRACE_ALWAYS("failed to clear halt state on 
read\n");
+                               *numBytes = 0;
+                               return result;
+                       }
+               }
+               fReadHeader = (uint32*)fReadBuffer;
        }

-       // TODO buffering is needed if we receive multiple packets, OOB data, 
etc since each Read
-       // call can only return one packet? (which isn't great and could be 
improved on network stack
-       // side to reduce syscalls if we had a readmmsg device call or 
something similar...)
-
-       if (header[0] != REMOTE_NDIS_PACKET_MSG) {
-               TRACE_ALWAYS("Received unexpected packet type %08" B_PRIx32 " 
on data link\n", header[0]);
+       if (fReadHeader[0] != REMOTE_NDIS_PACKET_MSG) {
+               TRACE_ALWAYS("Received unexpected packet type %08" B_PRIx32 " 
on data link\n",
+                       fReadHeader[0]);
                *numBytes = 0;
+               fReadHeader = NULL;
                return B_BAD_VALUE;
        }

-       if (header[1] != fActualLengthRead) {
-               TRACE_ALWAYS("Received frame length %08" B_PRIx32 " but USB 
transfer length is %08"
-                       B_PRIx32 "\n", header[1], fActualLengthRead);
+       if (fReadHeader[1] + ((uint8*)fReadHeader - fReadBuffer) > 
fActualLengthRead) {
+               TRACE_ALWAYS("Received frame at %ld length %08" B_PRIx32 " out 
of bounds of receive buffer"
+                       "%08" B_PRIx32 "\n", (uint8*) fReadHeader - 
fReadBuffer, fReadHeader[1],
+                       fActualLengthRead);
        }

-       if (header[4] != 0 || header[5] != 0 || header[6] != 0) {
+       if (fReadHeader[4] != 0 || fReadHeader[5] != 0 || fReadHeader[6] != 0) {
                TRACE_ALWAYS("Received frame has out of bound data: off %08" 
B_PRIx32 " len %08" B_PRIx32
-                       " count %08" B_PRIx32 "\n", header[4], header[5], 
header[6]);
+                       " count %08" B_PRIx32 "\n", fReadHeader[4], 
fReadHeader[5], fReadHeader[6]);
        }

-       if (header[7] != 0 || header[8] != 0) {
+       if (fReadHeader[7] != 0 || fReadHeader[8] != 0) {
                TRACE_ALWAYS("Received frame has per-packet info: off %08" 
B_PRIx32 " len %08" B_PRIx32
-                       "\n", header[7], header[8]);
+                       "\n", fReadHeader[7], fReadHeader[8]);
        }

-       if (header[9] != 0) {
-               TRACE_ALWAYS("Received frame has non-0 reserved fied %08x\n", 
header[9]);
+       if (fReadHeader[9] != 0) {
+               TRACE_ALWAYS("Received frame has non-0 reserved fied %08x\n", 
fReadHeader[9]);
        }

-       *numBytes = header[3];
+       *numBytes = fReadHeader[3];
+       memcpy(buffer, fReadHeader + 11, fReadHeader[3]);

        TRACE("Received data packet len %08x data [off %08x len %08x]\n",
-               header[1], header[2], header[3]);
+               fReadHeader[1], fReceivHeader[2], fReadHeader[3]);
+
+       // Advance to next packet
+       fReadHeader += fReadHeader[1];
+       if ((uint8*)fReadHeader - fReadBuffer >= fActualLengthRead)
+               fReadHeader = NULL;

        return B_OK;
 }
diff --git a/src/add-ons/kernel/drivers/network/ether/usb_rndis/RNDISDevice.h 
b/src/add-ons/kernel/drivers/network/ether/usb_rndis/RNDISDevice.h
index fa36282..60a2365 100644
--- a/src/add-ons/kernel/drivers/network/ether/usb_rndis/RNDISDevice.h
+++ b/src/add-ons/kernel/drivers/network/ether/usb_rndis/RNDISDevice.h
@@ -79,6 +79,8 @@
                sem_id                          fNotifyControlSem;

                uint8                           fNotifyBuffer[8];
+               uint8                           fReadBuffer[0x4000];
+               uint32*                         fReadHeader;

                // connection data
                sem_id                          fLinkStateChangeSem;

--
To view, visit https://review.haiku-os.org/c/haiku/+/5312
To unsubscribe, or for help writing mail filters, visit 
https://review.haiku-os.org/settings

Gerrit-Project: haiku
Gerrit-Branch: master
Gerrit-Change-Id: I71ebff0fe1fc5c8a342d6d06b26eda8e87115e04
Gerrit-Change-Number: 5312
Gerrit-PatchSet: 1
Gerrit-Owner: Adrien Destugues <pulkomandy@xxxxxxxxx>
Gerrit-MessageType: newchange

Other related posts:

  • » [haiku-commits] Change in haiku[master]: usb_rndis: accept incoming USB transfers up to 0x4000 size - Gerrit