]> git.proxmox.com Git - mirror_edk2.git/blobdiff - StdLib/EfiSocketLib/Socket.c
Modify UDP and IP to transmit on all network adapters instead of just the first netwo...
[mirror_edk2.git] / StdLib / EfiSocketLib / Socket.c
index 9c2d2f684421273894b71333a9b6b5677f91b6dd..e718e9bdf857d24a7dc4c0b86ec9378b7ee973de 100644 (file)
@@ -481,6 +481,14 @@ CONST ESL_SOCKET_BINDING cEslSocketBinding[] = {
     4,    //  RX buffers\r
     4,    //  TX buffers\r
     4 },  //  TX Oob buffers\r
+  { L"Tcp6",\r
+    &gEfiTcp6ServiceBindingProtocolGuid,\r
+    &gEfiTcp6ProtocolGuid,\r
+    &mEslTcp6ServiceGuid,\r
+    OFFSET_OF ( ESL_LAYER, pTcp6List ),\r
+    4,    //  RX buffers\r
+    4,    //  TX buffers\r
+    4 },  //  TX Oob buffers\r
   { L"Udp4",\r
     &gEfiUdp4ServiceBindingProtocolGuid,\r
     &gEfiUdp4ProtocolGuid,\r
@@ -488,6 +496,14 @@ CONST ESL_SOCKET_BINDING cEslSocketBinding[] = {
     OFFSET_OF ( ESL_LAYER, pUdp4List ),\r
     4,    //  RX buffers\r
     4,    //  TX buffers\r
+    0 },  //  TX Oob buffers\r
+  { L"Udp6",\r
+    &gEfiUdp6ServiceBindingProtocolGuid,\r
+    &gEfiUdp6ProtocolGuid,\r
+    &mEslUdp6ServiceGuid,\r
+    OFFSET_OF ( ESL_LAYER, pUdp6List ),\r
+    4,    //  RX buffers\r
+    4,    //  TX buffers\r
     0 }   //  TX Oob buffers\r
 };\r
 \r
@@ -516,11 +532,11 @@ CONST int cEslAfInetApiSize = DIM ( cEslAfInetApi );
 **/\r
 CONST ESL_PROTOCOL_API * cEslAfInet6Api[] = {\r
   NULL,             //  0\r
-  NULL,             //  SOCK_STREAM\r
-  NULL,             //  SOCK_DGRAM\r
+  &cEslTcp6Api,     //  SOCK_STREAM\r
+  &cEslUdp6Api,     //  SOCK_DGRAM\r
   NULL,             //  SOCK_RAW\r
   NULL,             //  SOCK_RDM\r
-  NULL              //  SOCK_SEQPACKET\r
+  &cEslTcp6Api      //  SOCK_SEQPACKET\r
 };\r
 \r
 /**\r
@@ -603,6 +619,7 @@ EslSocket (
     //  Validate the domain value\r
     //\r
     if (( AF_INET != domain )\r
+      && ( AF_INET6 != domain )\r
       && ( AF_LOCAL != domain )) {\r
       DEBUG (( DEBUG_ERROR | DEBUG_SOCKET,\r
                 "ERROR - Invalid domain value\r\n" ));\r
@@ -1242,7 +1259,10 @@ EslSocketBind (
       //\r
       //  Verify that at least one network connection was found\r
       //\r
-      if ( NULL == pSocket->pPortList ) {\r
+      if ( NULL != pSocket->pPortList ) {\r
+        Status = EFI_SUCCESS;\r
+      }\r
+      else {\r
         if ( EADDRNOTAVAIL == pSocket->errno ) {\r
           DEBUG (( DEBUG_BIND | DEBUG_POOL | DEBUG_INIT,\r
                     "ERROR - Socket address is not available!\r\n" ));\r
@@ -1789,6 +1809,11 @@ EslSocketConnect (
           if ( EFI_NOT_READY != Status ) {\r
             if ( !EFI_ERROR ( Status )) {\r
               pSocket->State = SOCKET_STATE_CONNECTED;\r
+\r
+              //\r
+              //  Start the receive operations\r
+              //\r
+              EslSocketRxStart ( pSocket->pPortList );\r
             }\r
             else {\r
               pSocket->State = SOCKET_STATE_BOUND;\r
@@ -1971,69 +1996,60 @@ EslSocketGetLocalAddress (
     //\r
     //  Verify the socket state\r
     //\r
-    Status = EslSocketIsConfigured ( pSocket );\r
-    if ( !EFI_ERROR ( Status )) {\r
+    EslSocketIsConfigured ( pSocket );\r
+    if ( pSocket->bAddressSet ) {\r
       //\r
       //  Verify the address buffer and length address\r
       //\r
       if (( NULL != pAddress ) && ( NULL != pAddressLength )) {\r
         //\r
-        //  Verify the socket state\r
+        //  Verify the API\r
         //\r
-        if ( SOCKET_STATE_CONNECTED == pSocket->State ) {\r
+        if ( NULL == pSocket->pApi->pfnLocalAddrGet ) {\r
+          Status = EFI_UNSUPPORTED;\r
+          pSocket->errno = ENOTSUP;\r
+        }\r
+        else {\r
           //\r
-          //  Verify the API\r
+          //  Synchronize with the socket layer\r
           //\r
-          if ( NULL == pSocket->pApi->pfnLocalAddrGet ) {\r
-            Status = EFI_UNSUPPORTED;\r
-            pSocket->errno = ENOTSUP;\r
-          }\r
-          else {\r
-            //\r
-            //  Synchronize with the socket layer\r
-            //\r
-            RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
+          RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
 \r
+          //\r
+          //  Verify that there is just a single connection\r
+          //\r
+          pPort = pSocket->pPortList;\r
+          if ( NULL != pPort ) {\r
             //\r
-            //  Verify that there is just a single connection\r
+            //  Verify the address length\r
             //\r
-            pPort = pSocket->pPortList;\r
-            if (( NULL != pPort ) && ( NULL == pPort->pLinkSocket )) {\r
+            LengthInBytes = pSocket->pApi->AddressLength;\r
+            if (( LengthInBytes <= *pAddressLength ) \r
+              && ( 255 >= LengthInBytes )) {\r
               //\r
-              //  Verify the address length\r
+              //  Return the local address and address length\r
               //\r
-              LengthInBytes = pSocket->pApi->AddressLength;\r
-              if (( LengthInBytes <= *pAddressLength ) \r
-                && ( 255 >= LengthInBytes )) {\r
-                //\r
-                //  Return the local address and address length\r
-                //\r
-                ZeroMem ( pAddress, LengthInBytes );\r
-                pAddress->sa_len = (uint8_t)LengthInBytes;\r
-                *pAddressLength = pAddress->sa_len;\r
-                pSocket->pApi->pfnLocalAddrGet ( pPort, pAddress );\r
-                pSocket->errno = 0;\r
-                Status = EFI_SUCCESS;\r
-              }\r
-              else {\r
-                pSocket->errno = EINVAL;\r
-                Status = EFI_INVALID_PARAMETER;\r
-              }\r
+              ZeroMem ( pAddress, LengthInBytes );\r
+              pAddress->sa_len = (uint8_t)LengthInBytes;\r
+              *pAddressLength = pAddress->sa_len;\r
+              pSocket->pApi->pfnLocalAddrGet ( pPort, pAddress );\r
+              pSocket->errno = 0;\r
+              Status = EFI_SUCCESS;\r
             }\r
             else {\r
-              pSocket->errno = ENOTCONN;\r
-              Status = EFI_NOT_STARTED;\r
+              pSocket->errno = EINVAL;\r
+              Status = EFI_INVALID_PARAMETER;\r
             }\r
-            \r
-            //\r
-            //  Release the socket layer synchronization\r
-            //\r
-            RESTORE_TPL ( TplPrevious );\r
           }\r
-        }\r
-        else {\r
-          pSocket->errno = ENOTCONN;\r
-          Status = EFI_NOT_STARTED;\r
+          else {\r
+            pSocket->errno = ENOTCONN;\r
+            Status = EFI_NOT_STARTED;\r
+          }\r
+          \r
+          //\r
+          //  Release the socket layer synchronization\r
+          //\r
+          RESTORE_TPL ( TplPrevious );\r
         }\r
       }\r
       else {\r
@@ -2041,6 +2057,13 @@ EslSocketGetLocalAddress (
         Status = EFI_INVALID_PARAMETER;\r
       }\r
     }\r
+    else {\r
+      //\r
+      //  Address not set\r
+      //\r
+      Status = EFI_NOT_STARTED;\r
+      pSocket->errno = EADDRNOTAVAIL;\r
+    }\r
   }\r
   \r
   //\r
@@ -2544,7 +2567,7 @@ EslSocketListen (
         //  Create the event for SocketAccept completion\r
         //\r
         Status = gBS->CreateEvent ( 0,\r
-                                    TplPrevious,\r
+                                    TPL_SOCKETS,\r
                                     NULL,\r
                                     NULL,\r
                                     &pSocket->WaitAccept );\r
@@ -2785,6 +2808,14 @@ EslSocketOptionGet (
         LengthInBytes = sizeof ( pSocket->MaxRxBuf );\r
         break;\r
 \r
+      case SO_REUSEADDR:\r
+        //\r
+        //  Return the address reuse flag\r
+        //\r
+        pOptionData = (UINT8 *)&pSocket->bReUseAddr;\r
+        LengthInBytes = sizeof ( pSocket->bReUseAddr );\r
+        break;\r
+      \r
       case SO_SNDBUF:\r
         //\r
         //  Return the maximum transmit buffer size\r
@@ -3009,6 +3040,14 @@ EslSocketOptionSet (
           LengthInBytes = sizeof ( pSocket->MaxRxBuf );\r
           break;\r
 \r
+        case SO_REUSEADDR:\r
+          //\r
+          //  Return the address reuse flag\r
+          //\r
+          pOptionData = (UINT8 *)&pSocket->bReUseAddr;\r
+          LengthInBytes = sizeof ( pSocket->bReUseAddr );\r
+          break;\r
+\r
         case SO_SNDBUF:\r
           //\r
           //  Send buffer size\r
@@ -3096,7 +3135,7 @@ EslSocketPacketAllocate (
                                LengthInBytes,\r
                                (VOID **)&pPacket );\r
   if ( !EFI_ERROR ( Status )) {\r
-    DEBUG (( DebugFlags | DEBUG_POOL | DEBUG_INIT,\r
+    DEBUG (( DebugFlags | DEBUG_POOL,\r
               "0x%08x: Allocate pPacket, %d bytes\r\n",\r
               pPacket,\r
               LengthInBytes ));\r
@@ -3152,7 +3191,7 @@ EslSocketPacketFree (
   DBG_ENTER ( );\r
 \r
   //\r
-  //  Allocate a packet structure\r
+  //  Free a packet structure\r
   //\r
   LengthInBytes = pPacket->PacketSize;\r
   Status = gBS->FreePool ( pPacket );\r
@@ -3210,6 +3249,7 @@ EslSocketPoll (
   short DetectedEvents;\r
   ESL_SOCKET * pSocket;\r
   EFI_STATUS Status;\r
+  EFI_TPL TplPrevious;\r
   short ValidEvents;\r
 \r
   DEBUG (( DEBUG_POLL, "Entering SocketPoll\r\n" ));\r
@@ -3247,6 +3287,22 @@ EslSocketPoll (
                 Events & ( ~ValidEvents )));\r
     }\r
     else {\r
+      //\r
+      //  Synchronize with the socket layer\r
+      //\r
+      RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
+      \r
+      //\r
+      //  Increase the network performance by extending the\r
+      //  polling (idle) loop down into the LAN driver\r
+      //\r
+      EslSocketRxPoll ( pSocket );\r
+      \r
+      //\r
+      //  Release the socket layer synchronization\r
+      //\r
+      RESTORE_TPL ( TplPrevious );\r
+\r
       //\r
       //  Check for pending connections\r
       //\r
@@ -4366,6 +4422,11 @@ EslSocketReceive (
               //  Verify that the socket is connected\r
               //\r
               if ( SOCKET_STATE_CONNECTED == pSocket->State ) {\r
+                //\r
+                //  Poll the network to increase performance\r
+                //\r
+                EslSocketRxPoll ( pSocket );\r
+\r
                 //\r
                 //  Locate the port\r
                 //\r
@@ -4847,6 +4908,49 @@ EslSocketRxComplete (
 }\r
 \r
 \r
+/**\r
+  Poll a socket for pending receive activity.\r
+\r
+  This routine is called at elivated TPL and extends the idle\r
+  loop which polls a socket down into the LAN driver layer to\r
+  determine if there is any receive activity.\r
+\r
+  The ::EslSocketPoll, ::EslSocketReceive and ::EslSocketTransmit\r
+  routines call this routine when there is nothing to do.\r
+\r
+  @param [in] pSocket   Address of an ::EFI_SOCKET structure.\r
+\r
+ **/\r
+VOID\r
+EslSocketRxPoll (\r
+  IN ESL_SOCKET * pSocket\r
+  )\r
+{\r
+  ESL_PORT * pPort;\r
+\r
+  DEBUG (( DEBUG_POLL, "Entering EslSocketRxPoll\r\n" ));\r
+\r
+  //\r
+  //  Increase the network performance by extending the\r
+  //  polling (idle) loop down into the LAN driver\r
+  //\r
+  pPort = pSocket->pPortList;\r
+  while ( NULL != pPort ) {\r
+    //\r
+    //  Poll the LAN adapter\r
+    //\r
+    pPort->pfnRxPoll ( pPort->pProtocol.v );\r
+\r
+    //\r
+    //  Locate the next LAN adapter\r
+    //\r
+    pPort = pPort->pLinkSocket;\r
+  }\r
+\r
+  DEBUG (( DEBUG_POLL, "Exiting EslSocketRxPoll\r\n" ));\r
+}\r
+\r
+\r
 /**\r
   Start a receive operation\r
 \r
@@ -5291,6 +5395,11 @@ EslSocketTransmit (
                 //\r
                 RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
 \r
+                //\r
+                //  Poll the network to increase performance\r
+                //\r
+                EslSocketRxPoll ( pSocket );\r
+\r
                 //\r
                 //  Attempt to buffer the packet for transmission\r
                 //\r