RedfishPkg: RedfishDiscoverDxe: Optimize the Redfish Discover flow

BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=4602

Filter out the network interfaces which are not supported by
Redfish Host Interface.

Cc: Abner Chang <abner.chang@amd.com>
Cc: Nickle Wang <nicklew@nvidia.com>
Cc: Mike Maslenkin <mike.maslenkin@gmail.com>
Signed-off-by: Igor Kulchytskyy <igork@ami.com>
Acked-by: Leif Lindholm <quic_llindhol@quicinc.com>
diff --git a/RedfishPkg/RedfishDiscoverDxe/RedfishDiscoverDxe.c b/RedfishPkg/RedfishDiscoverDxe/RedfishDiscoverDxe.c
index 0f622e0..28ba2d3 100644
--- a/RedfishPkg/RedfishDiscoverDxe/RedfishDiscoverDxe.c
+++ b/RedfishPkg/RedfishDiscoverDxe/RedfishDiscoverDxe.c
@@ -40,7 +40,7 @@
   IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL  *Instance

   );

 

-static REDFISH_DISCOVER_REQUIRED_PROTOCOL  gRequiredProtocol[] = {

+static REDFISH_DISCOVER_REQUIRED_PROTOCOL  mRequiredProtocol[] = {

   {

     ProtocolTypeTcp4,

     L"TCP4 Service Binding Protocol",

@@ -322,9 +322,16 @@
 {

   EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL  *ThisNetworkInterface;

 

+  if (IsListEmpty (&mEfiRedfishDiscoverNetworkInterface)) {

+    return NULL;

+  }

+

   ThisNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface);

   while (TRUE) {

-    if (CompareMem ((VOID *)&ThisNetworkInterface->MacAddress, &TargetNetworkInterface->MacAddress, ThisNetworkInterface->HwAddressSize) == 0) {

+    if ((MAC_COMPARE (ThisNetworkInterface, TargetNetworkInterface)) &&

+        (VALID_TCP6 (TargetNetworkInterface, ThisNetworkInterface) ||

+         VALID_TCP4 (TargetNetworkInterface, ThisNetworkInterface)))

+    {

       return ThisNetworkInterface;

     }

 

@@ -354,6 +361,10 @@
 {

   EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL  *ThisNetworkInterface;

 

+  if (IsListEmpty (&mEfiRedfishDiscoverNetworkInterface)) {

+    return NULL;

+  }

+

   ThisNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface);

   while (TRUE) {

     if (ThisNetworkInterface->OpenDriverControllerHandle == ControllerHandle) {

@@ -399,7 +410,7 @@
 

   ThisNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface);

   while (TRUE) {

-    if (CompareMem ((VOID *)&ThisNetworkInterface->MacAddress, &TargetNetworkInterface->MacAddress, ThisNetworkInterface->HwAddressSize) == 0) {

+    if (MAC_COMPARE (ThisNetworkInterface, TargetNetworkInterface)) {

       break;

     }

 

@@ -477,6 +488,67 @@
 }

 

 /**

+  This function returns the  IP type supported by the Host Interface.

+

+  @retval 00h is Unknown

+          01h is Ipv4

+          02h is Ipv6

+

+**/

+STATIC

+UINT8

+GetHiIpProtocolType (

+  VOID

+  )

+{

+  EFI_STATUS                     Status;

+  REDFISH_OVER_IP_PROTOCOL_DATA  *Data;

+  REDFISH_INTERFACE_DATA         *DeviceDescriptor;

+

+  Data             = NULL;

+  DeviceDescriptor = NULL;

+  if (mSmbios == NULL) {

+    Status = gBS->LocateProtocol (&gEfiSmbiosProtocolGuid, NULL, (VOID **)&mSmbios);

+    if (EFI_ERROR (Status)) {

+      return REDFISH_HOST_INTERFACE_HOST_IP_ADDRESS_FORMAT_UNKNOWN;

+    }

+  }

+

+  Status = RedfishGetHostInterfaceProtocolData (mSmbios, &DeviceDescriptor, &Data); // Search for SMBIOS type 42h

+  if (!EFI_ERROR (Status) && (Data != NULL) &&

+      (Data->HostIpAssignmentType == RedfishHostIpAssignmentStatic))

+  {

+    return Data->HostIpAddressFormat;

+  }

+

+  return REDFISH_HOST_INTERFACE_HOST_IP_ADDRESS_FORMAT_UNKNOWN;

+}

+

+/**

+  Check if Network Protocol Type matches with SMBIOS Type 42 IP Address Type.

+

+  @param[in]  NetworkProtocolType  The Network Protocol Type to check with.

+  @param[in]  IpType               The Host IP Address Type from SMBIOS Type 42.

+**/

+STATIC

+BOOLEAN

+FilterProtocol (

+  IN UINT32  NetworkProtocolType,

+  IN UINT8   IpType

+  )

+{

+  if (NetworkProtocolType == ProtocolTypeTcp4) {

+    return IpType != REDFISH_HOST_INTERFACE_HOST_IP_ADDRESS_FORMAT_IP4;

+  }

+

+  if (NetworkProtocolType == ProtocolTypeTcp6) {

+    return IpType != REDFISH_HOST_INTERFACE_HOST_IP_ADDRESS_FORMAT_IP6;

+  }

+

+  return FALSE;

+}

+

+/**

   This function discover Redfish service through SMBIOS host interface.

 

   @param[in]    Instance     EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE

@@ -512,6 +584,11 @@
 

   Status = RedfishGetHostInterfaceProtocolData (mSmbios, &DeviceDescriptor, &Data); // Search for SMBIOS type 42h

   if (!EFI_ERROR (Status) && (Data != NULL) && (DeviceDescriptor != NULL)) {

+    // Check IP Type and skip an unnecessary network protocol if does not match

+    if (FilterProtocol (Instance->NetworkInterface->NetworkProtocolType, Data->HostIpAddressFormat)) {

+      return EFI_UNSUPPORTED;

+    }

+

     //

     // Check if we can reach out Redfish service using this network interface.

     // Check with MAC address using Device Descriptor Data Device Type 04 and Type 05.

@@ -1000,8 +1077,8 @@
   }

 

   ProtocolType = Instance->NetworkProtocolType;

-  if ((gRequiredProtocol[ProtocolType].GetSubnetInfo != NULL) && (Instance->GotSubnetInfo == FALSE)) {

-    Status = gRequiredProtocol[ProtocolType].GetSubnetInfo (

+  if ((mRequiredProtocol[ProtocolType].GetSubnetInfo != NULL) && (Instance->GotSubnetInfo == FALSE)) {

+    Status = mRequiredProtocol[ProtocolType].GetSubnetInfo (

                                                ImageHandle,

                                                Instance

                                                );

@@ -1102,6 +1179,7 @@
   OUT EFI_REDFISH_DISCOVER_NETWORK_INTERFACE  **NetworkIntfInstances

   )

 {

+  EFI_STATUS                                       Status;

   EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL  *ThisNetworkInterfaceIntn;

   EFI_REDFISH_DISCOVER_NETWORK_INTERFACE           *ThisNetworkInterface;

   EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_INTERNAL   *RestExInstance;

@@ -1141,13 +1219,23 @@
 

   ThisNetworkInterfaceIntn = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface);

   while (TRUE) {

+    // If Get Subnet Info failed then skip this interface

+    Status = NetworkInterfaceGetSubnetInfo (ThisNetworkInterfaceIntn, ImageHandle); // Get subnet info

+    if (EFI_ERROR (Status)) {

+      if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInterfaceIntn->Entry)) {

+        break;

+      }

+

+      ThisNetworkInterfaceIntn = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetNextNode (&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInterfaceIntn->Entry);

+      continue;

+    }

+

     ThisNetworkInterface->IsIpv6 = FALSE;

     if (CheckIsIpVersion6 (ThisNetworkInterfaceIntn)) {

       ThisNetworkInterface->IsIpv6 = TRUE;

     }

 

     CopyMem ((VOID *)&ThisNetworkInterface->MacAddress, &ThisNetworkInterfaceIntn->MacAddress, ThisNetworkInterfaceIntn->HwAddressSize);

-    NetworkInterfaceGetSubnetInfo (ThisNetworkInterfaceIntn, ImageHandle); // Get subnet info.

     if (!ThisNetworkInterface->IsIpv6) {

       IP4_COPY_ADDRESS (&ThisNetworkInterface->SubnetId.v4, &ThisNetworkInterfaceIntn->SubnetAddr.v4); // IPv4 subnet information.

     } else {

@@ -1230,7 +1318,12 @@
 

   if (TargetNetworkInterface != NULL) {

     TargetNetworkInterfaceInternal = GetTargetNetworkInterfaceInternal (TargetNetworkInterface);

-    NumNetworkInterfaces           = 1;

+    if (TargetNetworkInterfaceInternal == NULL) {

+      DEBUG ((DEBUG_ERROR, "%a:No network interface on platform.\n", __func__));

+      return EFI_UNSUPPORTED;

+    }

+

+    NumNetworkInterfaces = 1;

   } else {

     TargetNetworkInterfaceInternal = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface);

     NumNetworkInterfaces           = NumberOfNetworkInterface ();

@@ -1260,7 +1353,13 @@
       // Get subnet information in case subnet information is not set because

       // RedfishServiceGetNetworkInterfaces hasn't been called yet.

       //

-      NetworkInterfaceGetSubnetInfo (TargetNetworkInterfaceInternal, ImageHandle);

+      Status1 = NetworkInterfaceGetSubnetInfo (TargetNetworkInterfaceInternal, ImageHandle);

+      if (EFI_ERROR (Status1)) {

+        DEBUG ((DEBUG_ERROR, "%a: Get subnet information fail.\n", __func__));

+        FreePool (Instance);

+        continue;

+      }

+

       NewInstance = TRUE;

     }

 

@@ -1506,7 +1605,7 @@
 

   Status = gBS->UninstallProtocolInterface (

                   ThisNetworkInterface->OpenDriverControllerHandle,

-                  gRequiredProtocol[ThisNetworkInterface->NetworkProtocolType].DiscoveredProtocolGuid,

+                  mRequiredProtocol[ThisNetworkInterface->NetworkProtocolType].DiscoveredProtocolGuid,

                   &ThisNetworkInterface->NetworkInterfaceProtocolInfo.ProtocolDiscoverId

                   );

   RemoveEntryList (&ThisNetworkInterface->Entry);

@@ -1537,11 +1636,11 @@
   EFI_STATUS  Status;

   UINTN       ListCount;

 

-  ListCount = (sizeof (gRequiredProtocol) / sizeof (REDFISH_DISCOVER_REQUIRED_PROTOCOL));

+  ListCount = (sizeof (mRequiredProtocol) / sizeof (REDFISH_DISCOVER_REQUIRED_PROTOCOL));

   for (Index = 0; Index < ListCount; Index++) {

     Status = gBS->OpenProtocol (

                     ControllerHandle,

-                    gRequiredProtocol[Index].RequiredServiceBindingProtocolGuid,

+                    mRequiredProtocol[Index].RequiredServiceBindingProtocolGuid,

                     NULL,

                     This->DriverBindingHandle,

                     ControllerHandle,

@@ -1553,7 +1652,7 @@
 

     Status = gBS->OpenProtocol (

                     ControllerHandle,

-                    gRequiredProtocol[Index].DiscoveredProtocolGuid,

+                    mRequiredProtocol[Index].DiscoveredProtocolGuid,

                     (VOID **)&Id,

                     This->DriverBindingHandle,

                     ControllerHandle,

@@ -1601,58 +1700,60 @@
   EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_INTERNAL   *RestExInstance;

   EFI_TPL                                          OldTpl;

   BOOLEAN                                          NewNetworkInterfaceInstalled;

+  UINT8                                            IpType;

+  UINTN                                            ListCount;

 

+  ListCount                    = (sizeof (mRequiredProtocol) / sizeof (REDFISH_DISCOVER_REQUIRED_PROTOCOL));

   NewNetworkInterfaceInstalled = FALSE;

   Index                        = 0;

-  do {

+

+  // Get IP Type to filter out unnecessary network protocol if possible

+  IpType = GetHiIpProtocolType ();

+

+  for (Index = 0; Index < ListCount; Index++) {

+    // Check IP Type and skip an unnecessary network protocol if does not match

+    if (FilterProtocol (mRequiredProtocol[Index].ProtocolType, IpType)) {

+      continue;

+    }

+

     Status = gBS->OpenProtocol (

                     // Already in list?

                     ControllerHandle,

-                    gRequiredProtocol[Index].DiscoveredProtocolGuid,

+                    mRequiredProtocol[Index].DiscoveredProtocolGuid,

                     (VOID **)&Id,

                     This->DriverBindingHandle,

                     ControllerHandle,

                     EFI_OPEN_PROTOCOL_GET_PROTOCOL

                     );

     if (!EFI_ERROR (Status)) {

-      Index++;

-      if (Index == (sizeof (gRequiredProtocol) / sizeof (REDFISH_DISCOVER_REQUIRED_PROTOCOL))) {

-        break;

-      }

-

       continue;

     }

 

     Status = gBS->OpenProtocol (

                     ControllerHandle,

-                    gRequiredProtocol[Index].RequiredServiceBindingProtocolGuid,

+                    mRequiredProtocol[Index].RequiredServiceBindingProtocolGuid,

                     &TempInterface,

                     This->DriverBindingHandle,

                     ControllerHandle,

                     EFI_OPEN_PROTOCOL_GET_PROTOCOL

                     );

     if (EFI_ERROR (Status)) {

-      Index++;

-      if (Index == (sizeof (gRequiredProtocol) / sizeof (REDFISH_DISCOVER_REQUIRED_PROTOCOL))) {

-        break;

-      }

-

       continue;

     }

 

-    if (gRequiredProtocol[Index].ProtocolType != ProtocolTypeRestEx) {

+    if (mRequiredProtocol[Index].ProtocolType != ProtocolTypeRestEx) {

       OldTpl = gBS->RaiseTPL (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_TPL);

-      Status = CreateRedfishDiscoverNetworkInterface (ControllerHandle, gRequiredProtocol[Index].ProtocolType, &IsNew, &NetworkInterface);

+      Status = CreateRedfishDiscoverNetworkInterface (ControllerHandle, mRequiredProtocol[Index].ProtocolType, &IsNew, &NetworkInterface);

       if (EFI_ERROR (Status)) {

         gBS->RestoreTPL (OldTpl);

         return Status;

       }

 

-      NetworkInterface->NetworkProtocolType        = gRequiredProtocol[Index].ProtocolType;

+      NetworkInterface->NetworkProtocolType        = mRequiredProtocol[Index].ProtocolType;

       NetworkInterface->OpenDriverAgentHandle      = This->DriverBindingHandle;

       NetworkInterface->OpenDriverControllerHandle = ControllerHandle;

-      CopyGuid (&NetworkInterface->NetworkInterfaceProtocolInfo.ProtocolGuid, gRequiredProtocol[Index].RequiredProtocolGuid);

-      CopyGuid (&NetworkInterface->NetworkInterfaceProtocolInfo.ProtocolServiceGuid, gRequiredProtocol[Index].RequiredServiceBindingProtocolGuid);

+      CopyGuid (&NetworkInterface->NetworkInterfaceProtocolInfo.ProtocolGuid, mRequiredProtocol[Index].RequiredProtocolGuid);

+      CopyGuid (&NetworkInterface->NetworkInterfaceProtocolInfo.ProtocolServiceGuid, mRequiredProtocol[Index].RequiredServiceBindingProtocolGuid);

       ProtocolDiscoverIdPtr        = &NetworkInterface->NetworkInterfaceProtocolInfo.ProtocolDiscoverId;

       OpenDriverAgentHandle        = NetworkInterface->OpenDriverAgentHandle;

       OpenDriverControllerHandle   = NetworkInterface->OpenDriverControllerHandle;

@@ -1690,16 +1791,11 @@
 

     Status = gBS->InstallProtocolInterface (

                     &ControllerHandle,

-                    gRequiredProtocol[Index].DiscoveredProtocolGuid,

+                    mRequiredProtocol[Index].DiscoveredProtocolGuid,

                     EFI_NATIVE_INTERFACE,

                     ProtocolDiscoverIdPtr

                     );

     if (EFI_ERROR (Status)) {

-      Index++;

-      if (Index == (sizeof (gRequiredProtocol) / sizeof (REDFISH_DISCOVER_REQUIRED_PROTOCOL))) {

-        break;

-      }

-

       continue;

     }

 

@@ -1709,20 +1805,20 @@
     Status = NetLibCreateServiceChild (

                ControllerHandle,

                This->ImageHandle,

-               gRequiredProtocol[Index].RequiredServiceBindingProtocolGuid,

+               mRequiredProtocol[Index].RequiredServiceBindingProtocolGuid,

                HandleOfProtocolInterfacePtr

                );

     if (!EFI_ERROR (Status)) {

       Status = gBS->OpenProtocol (

                       *HandleOfProtocolInterfacePtr,

-                      gRequiredProtocol[Index].RequiredProtocolGuid,

+                      mRequiredProtocol[Index].RequiredProtocolGuid,

                       Interface,

                       OpenDriverAgentHandle,

                       OpenDriverControllerHandle,

                       EFI_OPEN_PROTOCOL_BY_DRIVER

                       );

       if (!EFI_ERROR (Status)) {

-        if ((gRequiredProtocol[Index].ProtocolType == ProtocolTypeRestEx)) {

+        if ((mRequiredProtocol[Index].ProtocolType == ProtocolTypeRestEx)) {

           // Install Redfish Discover Protocol when EFI REST EX protocol is discovered.

           // This ensures EFI REST EX is ready while the consumer of EFI_REDFISH_DISCOVER_PROTOCOL

           // acquires Redfish service over network interface.

@@ -1756,25 +1852,13 @@
           }

         } else {

           DEBUG ((DEBUG_MANAGEABILITY, "%a: Not REST EX, continue with next\n", __func__));

-          Index++;

-          if (Index == (sizeof (gRequiredProtocol) / sizeof (REDFISH_DISCOVER_REQUIRED_PROTOCOL))) {

-            break;

-          }

-

           continue;

         }

       }

 

       return Status;

-    } else {

-      Index++;

-      if (Index == (sizeof (gRequiredProtocol) / sizeof (REDFISH_DISCOVER_REQUIRED_PROTOCOL))) {

-        break;

-      }

-

-      continue;

     }

-  } while (Index < (sizeof (gRequiredProtocol) / sizeof (REDFISH_DISCOVER_REQUIRED_PROTOCOL)));

+  }

 

   return EFI_DEVICE_ERROR;

 }

@@ -1849,14 +1933,14 @@
   EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_INTERNAL   *RestExInstance;

   EFI_REDFISH_DISCOVER_PROTOCOL                    *RedfishDiscoverProtocol;

 

-  for (Index = 0; Index < (sizeof (gRequiredProtocol) / sizeof (REDFISH_DISCOVER_REQUIRED_PROTOCOL)); Index++) {

+  for (Index = 0; Index < (sizeof (mRequiredProtocol) / sizeof (REDFISH_DISCOVER_REQUIRED_PROTOCOL)); Index++) {

     Status = gBS->HandleProtocol (

                     ControllerHandle,

-                    gRequiredProtocol[Index].RequiredProtocolGuid,

+                    mRequiredProtocol[Index].RequiredProtocolGuid,

                     (VOID **)&Interface

                     );

     if (!EFI_ERROR (Status)) {

-      if (gRequiredProtocol[Index].ProtocolType != ProtocolTypeRestEx) {

+      if (mRequiredProtocol[Index].ProtocolType != ProtocolTypeRestEx) {

         if (IsListEmpty (&mEfiRedfishDiscoverNetworkInterface)) {

           return EFI_NOT_FOUND;

         }

@@ -1872,7 +1956,7 @@
             Status = CloseProtocolService (

                        ThisBindingProtocol,

                        ControllerHandle,

-                       &gRequiredProtocol[Index],

+                       &mRequiredProtocol[Index],

                        ThisNetworkInterface->OpenDriverAgentHandle,

                        ThisNetworkInterface->OpenDriverControllerHandle

                        );

@@ -1935,7 +2019,7 @@
                        // Close REST_EX protocol.

                        ThisBindingProtocol,

                        ControllerHandle,

-                       &gRequiredProtocol[Index],

+                       &mRequiredProtocol[Index],

                        RestExInstance->OpenDriverAgentHandle,

                        RestExInstance->OpenDriverControllerHandle

                        );

diff --git a/RedfishPkg/RedfishDiscoverDxe/RedfishDiscoverInternal.h b/RedfishPkg/RedfishDiscoverDxe/RedfishDiscoverInternal.h
index 01454ac..e27cfa7 100644
--- a/RedfishPkg/RedfishDiscoverDxe/RedfishDiscoverInternal.h
+++ b/RedfishPkg/RedfishDiscoverDxe/RedfishDiscoverInternal.h
@@ -39,6 +39,10 @@
 #define REDFISH_DISCOVER_VERSION                    0x00010000

 #define EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_TPL  TPL_NOTIFY

 

+#define MAC_COMPARE(This, Target)  (CompareMem ((VOID *)&(This)->MacAddress, &(Target)->MacAddress, (This)->HwAddressSize) == 0)

+#define VALID_TCP6(Target, This)   ((Target)->IsIpv6 && ((This)->NetworkProtocolType == ProtocolTypeTcp6))

+#define VALID_TCP4(Target, This)   (!(Target)->IsIpv6 && ((This)->NetworkProtocolType == ProtocolTypeTcp4))

+

 //

 // GUID definitions

 //