* [edk2-devel] [edk2-redfish-client][PATCH] RedfishClientPkg: Add ETag PCD and revise Redfish ETag functions
@ 2024-01-03 7:53 Chang, Abner via groups.io
0 siblings, 0 replies; only message in thread
From: Chang, Abner via groups.io @ 2024-01-03 7:53 UTC (permalink / raw)
To: devel; +Cc: Nickle Wang, Igor Kulchytskyy, Mike Maslenkin
From: Abner Chang <abner.chang@amd.com>
Add PCD to disable ETag capability for the case Redfish
service doesn't support ETag.
Signed-off-by: Abner Chang <abner.chang@amd.com>
Cc: Nickle Wang <nicklew@nvidia.com>
Cc: Igor Kulchytskyy <igork@ami.com>
Cc: Mike Maslenkin <mike.maslenkin@gmail.com>
---
RedfishClientPkg/RedfishClientPkg.dec | 2 +
.../RedfishFeatureUtilityLib.inf | 1 +
.../Library/RedfishFeatureUtilityLib.h | 46 +++-
.../RedfishFeatureUtilityLib.c | 212 ++++++++++++------
4 files changed, 180 insertions(+), 81 deletions(-)
diff --git a/RedfishClientPkg/RedfishClientPkg.dec b/RedfishClientPkg/RedfishClientPkg.dec
index 5f8a03501d..155eea9812 100644
--- a/RedfishClientPkg/RedfishClientPkg.dec
+++ b/RedfishClientPkg/RedfishClientPkg.dec
@@ -75,6 +75,8 @@
gEfiRedfishClientPkgTokenSpaceGuid.PcdDefaultRedfishVersion|L"v1"|VOID*|0x10000004
## The number of seconds that the firmware will wait before system reboot
gEfiRedfishClientPkgTokenSpaceGuid.PcdRedfishSystemRebootTimeout|5|UINT16|0x20000002
+ ## Default capability of Redfish service side ETAG support
+ gEfiRedfishClientPkgTokenSpaceGuid.PcdRedfishServiceEtagSupported|TRUE|BOOLEAN|0x10000005
[PcdsDynamicEx]
## The flag used to indicate that system reboot is required due to system configuration change
diff --git a/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib.inf b/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib.inf
index fd66b8ac34..681c121a13 100644
--- a/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib.inf
+++ b/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib.inf
@@ -53,6 +53,7 @@
[Pcd]
gEfiRedfishClientPkgTokenSpaceGuid.PcdRedfishSystemRebootRequired
+ gEfiRedfishClientPkgTokenSpaceGuid.PcdRedfishServiceEtagSupported
[Guids]
diff --git a/RedfishClientPkg/Include/Library/RedfishFeatureUtilityLib.h b/RedfishClientPkg/Include/Library/RedfishFeatureUtilityLib.h
index 24f0ad2447..2f0833632c 100644
--- a/RedfishClientPkg/Include/Library/RedfishFeatureUtilityLib.h
+++ b/RedfishClientPkg/Include/Library/RedfishFeatureUtilityLib.h
@@ -100,7 +100,7 @@ CopyConfiglanguageList (
/**
- Get number of node from the string. Node is seperated by '/'.
+ Get number of node from the string. Node is separated by '/'.
@param[in] NodeString The node string to parse.
@@ -578,6 +578,19 @@ GetEtagWithUri (
IN EFI_STRING Uri
);
+/**
+
+ This function returns a boolean of ETAG support on Redfish service side.
+
+ @retval TRUE ETAG is supported on Redfish service.
+ @retval FALSE ETAG is not supported on Redfish service.
+
+**/
+BOOLEAN
+CheckIsServerEtagSupported (
+ VOID
+ );
+
/**
Get @odata.id from give HTTP payload. It's call responsibility to release returned buffer.
@@ -950,22 +963,33 @@ CompareRedfishPropertyVagueValues (
);
/**
+ Find "ETag" from either HTTP header or Redfish response.
- Find "ETag" and "Location" from either HTTP header or Redfish response.
+ @param[in] Response HTTP response
+ @param[out] Etag String buffer to return ETag
- @param[in] Response HTTP response
- @param[out] Etag String buffer to return ETag
- @param[out] Location String buffer to return Location
+ @retval EFI_SUCCESS ETag is returned in Etag
+ @retval EFI_UNSUPPORTED ETag is unsupported
+ @retval EFI_INVALID_PARAMETER Response, Etag or both are NULL.
- @retval EFI_SUCCESS Data is found and returned.
- @retval Others Errors occur.
+**/
+EFI_STATUS
+GetHttpResponseEtag (
+ IN REDFISH_RESPONSE *Response,
+ OUT CHAR8 **Etag
+ );
+
+/**
+ Find "Location" from either HTTP header or Redfish response.
+
+ @param[in] Response HTTP response
+ @param[out] Location String buffer to return Location
**/
EFI_STATUS
-GetEtagAndLocation (
- IN REDFISH_RESPONSE *Response,
- OUT CHAR8 **Etag, OPTIONAL
- OUT EFI_STRING *Location OPTIONAL
+GetHttpResponseLocation (
+ IN REDFISH_RESPONSE *Response,
+ OUT EFI_STRING *Location
);
/**
diff --git a/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib.c b/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib.c
index 01c054ae3b..a77758d0a2 100644
--- a/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib.c
+++ b/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib.c
@@ -133,6 +133,11 @@ SetEtagFromUri (
REDFISH_RESPONSE Response;
EFI_STRING PendingSettingUri;
+ if (!CheckIsServerEtagSupported ()) {
+ DEBUG ((DEBUG_INFO, "%a: WARNING - ETAG is not supported\n", __func__));
+ return EFI_SUCCESS;
+ }
+
if ((RedfishService == NULL) || IS_EMPTY_STRING (Uri)) {
return EFI_INVALID_PARAMETER;
}
@@ -156,9 +161,9 @@ SetEtagFromUri (
//
// Find etag in HTTP response header
//
- Status = GetEtagAndLocation (&Response, &Etag, NULL);
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "%a: failed to get ETag from HTTP header\n", __func__));
+ Status = GetHttpResponseEtag (&Response, &Etag);
+ if (EFI_ERROR (Status) && (Status != EFI_UNSUPPORTED)) {
+ DEBUG ((DEBUG_ERROR, "%a: Failed to get ETag from HTTP header\n", __func__));
Status = EFI_NOT_FOUND;
goto ON_RELEASE;
}
@@ -240,6 +245,11 @@ SetEtagWithUri (
EFI_STATUS Status;
CHAR8 *AsciiUri;
+ if (!CheckIsServerEtagSupported ()) {
+ DEBUG ((DEBUG_INFO, "%a: WARNING - ETAG is not supported\n", __func__));
+ return EFI_SUCCESS;
+ }
+
if (IS_EMPTY_STRING (EtagStr) || IS_EMPTY_STRING (Uri)) {
return EFI_INVALID_PARAMETER;
}
@@ -285,6 +295,11 @@ GetEtagWithUri (
return NULL;
}
+ if (!CheckIsServerEtagSupported ()) {
+ DEBUG ((DEBUG_INFO, "%a: WARNING - ETAG is not supported\n", __func__));
+ return NULL;
+ }
+
Status = RedfishLocateProtocol ((VOID **)&mEtagProtocol, &gEdkIIRedfishETagProtocolGuid);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "%a: fail to locate gEdkIIRedfishETagProtocolGuid: %r\n", __func__, Status));
@@ -1785,44 +1800,39 @@ RedfishFeatureGetUnifiedArrayTypeConfigureLang (
}
/**
+ Find "ETag" from either HTTP header or Redfish response.
- Find "ETag" and "Location" from either HTTP header or Redfish response.
+ @param[in] Response HTTP response
+ @param[out] Etag String buffer to return ETag
- @param[in] Response HTTP response
- @param[out] Etag String buffer to return ETag
- @param[out] Location String buffer to return Location
-
- @retval EFI_SUCCESS Data is found and returned.
- @retval Others Errors occur.
+ @retval EFI_SUCCESS ETag is returned in Etag
+ @retval EFI_UNSUPPORTED ETag is unsupported
+ @retval EFI_INVALID_PARAMETER Response, Etag or both are NULL.
**/
EFI_STATUS
-GetEtagAndLocation (
- IN REDFISH_RESPONSE *Response,
- OUT CHAR8 **Etag, OPTIONAL
- OUT EFI_STRING *Location OPTIONAL
+GetHttpResponseEtag (
+ IN REDFISH_RESPONSE *Response,
+ OUT CHAR8 **Etag
)
{
+ EFI_STATUS Status;
EDKII_JSON_VALUE JsonValue;
EDKII_JSON_VALUE OdataValue;
CHAR8 *OdataString;
- CHAR8 *AsciiLocation;
EFI_HTTP_HEADER *Header;
- EFI_STATUS Status;
- if (Response == NULL) {
+ if ((Response == NULL) || (Etag == NULL)) {
return EFI_INVALID_PARAMETER;
}
- if ((Etag == NULL) && (Location == NULL)) {
- return EFI_SUCCESS;
- }
-
Status = EFI_SUCCESS;
-
- if (Etag != NULL) {
- *Etag = NULL;
-
+ *Etag = NULL;
+ if (!CheckIsServerEtagSupported ()) {
+ // Don't look for ETAG header or property in this case.
+ DEBUG ((DEBUG_INFO, "%a: WARNING - No ETag support on Redfish service.\n", __func__));
+ return EFI_UNSUPPORTED;
+ } else {
if (*(Response->StatusCode) == HTTP_STATUS_200_OK) {
Header = HttpFindHeader (Response->HeaderCount, Response->Headers, HTTP_HEADER_ETAG);
if (Header != NULL) {
@@ -1852,51 +1862,94 @@ GetEtagAndLocation (
if (*Etag == NULL) {
Status = EFI_NOT_FOUND;
+ DEBUG ((DEBUG_ERROR, "%a: Failed to retrieve ETag from HTTP response paylaod.\n", __func__));
}
}
- if (Location != NULL) {
- *Location = NULL;
- AsciiLocation = NULL;
+ return Status;
+}
- if (*(Response->StatusCode) == HTTP_STATUS_200_OK) {
- Header = HttpFindHeader (Response->HeaderCount, Response->Headers, HTTP_HEADER_LOCATION);
- if (Header != NULL) {
- AsciiLocation = AllocateCopyPool (AsciiStrSize (Header->FieldValue), Header->FieldValue);
- ASSERT (AsciiLocation != NULL);
- }
+/**
+ Find "Location" from either HTTP header or Redfish response.
+
+ @param[in] Response HTTP response
+ @param[out] Location String buffer to return Location
+
+**/
+EFI_STATUS
+GetHttpResponseLocation (
+ IN REDFISH_RESPONSE *Response,
+ OUT EFI_STRING *Location
+ )
+{
+ EFI_STATUS Status;
+ EDKII_JSON_VALUE JsonValue;
+ EDKII_JSON_VALUE OdataValue;
+ CHAR8 *OdataString;
+ CHAR8 *AsciiLocation;
+ EFI_HTTP_HEADER *Header;
+
+ if ((Response == NULL) || (Location == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = EFI_SUCCESS;
+ *Location = NULL;
+ AsciiLocation = NULL;
+ if (*(Response->StatusCode) == HTTP_STATUS_200_OK) {
+ Header = HttpFindHeader (Response->HeaderCount, Response->Headers, HTTP_HEADER_LOCATION);
+ if (Header != NULL) {
+ AsciiLocation = AllocateCopyPool (AsciiStrSize (Header->FieldValue), Header->FieldValue);
+ ASSERT (AsciiLocation != NULL);
}
+ }
- //
- // No header is returned. Search payload for location.
- //
- if ((*Location == NULL) && (Response->Payload != NULL)) {
- JsonValue = RedfishJsonInPayload (Response->Payload);
- if (JsonValue != NULL) {
- OdataValue = JsonObjectGetValue (JsonValueGetObject (JsonValue), "@odata.id");
- if (OdataValue != NULL) {
- OdataString = (CHAR8 *)JsonValueGetAsciiString (OdataValue);
- if (OdataString != NULL) {
- AsciiLocation = AllocateCopyPool (AsciiStrSize (OdataString), OdataString);
- ASSERT (AsciiLocation != NULL);
- }
+ //
+ // No header is returned. Search payload for location.
+ //
+ if ((*Location == NULL) && (Response->Payload != NULL)) {
+ JsonValue = RedfishJsonInPayload (Response->Payload);
+ if (JsonValue != NULL) {
+ OdataValue = JsonObjectGetValue (JsonValueGetObject (JsonValue), "@odata.id");
+ if (OdataValue != NULL) {
+ OdataString = (CHAR8 *)JsonValueGetAsciiString (OdataValue);
+ if (OdataString != NULL) {
+ AsciiLocation = AllocateCopyPool (AsciiStrSize (OdataString), OdataString);
+ ASSERT (AsciiLocation != NULL);
}
-
- JsonValueFree (JsonValue);
}
- }
- if (AsciiLocation != NULL) {
- *Location = StrAsciiToUnicode (AsciiLocation);
- FreePool (AsciiLocation);
- } else {
- Status = EFI_NOT_FOUND;
+ JsonValueFree (JsonValue);
}
}
+ if (AsciiLocation != NULL) {
+ *Location = StrAsciiToUnicode (AsciiLocation);
+ FreePool (AsciiLocation);
+ } else {
+ Status = EFI_NOT_FOUND;
+ DEBUG ((DEBUG_ERROR, "%a: Failed to retrieve Location from HTTP response paylaod.\n", __func__));
+ }
+
return Status;
}
+/**
+
+ This function returns a boolean of ETAG support on Redfish service side.
+
+ @retval TRUE ETAG is supported on Redfish service.
+ @retval FALSE ETAG is not supported on Redfish service.
+
+**/
+BOOLEAN
+CheckIsServerEtagSupported (
+ VOID
+ )
+{
+ return FixedPcdGetBool (PcdRedfishServiceEtagSupported);
+}
+
/**
Create HTTP payload and send them to redfish service with PATCH method.
@@ -1915,15 +1968,15 @@ CreatePayloadToPatchResource (
IN REDFISH_SERVICE *Service,
IN REDFISH_PAYLOAD *TargetPayload,
IN CHAR8 *Json,
- OUT CHAR8 **Etag
+ OUT CHAR8 **Etag OPTIONAL
)
{
REDFISH_PAYLOAD Payload;
EDKII_JSON_VALUE ResourceJsonValue;
- REDFISH_RESPONSE PostResponse;
+ REDFISH_RESPONSE PatchResponse;
EFI_STATUS Status;
- if ((Service == NULL) || (TargetPayload == NULL) || IS_EMPTY_STRING (Json) || (Etag == NULL)) {
+ if ((Service == NULL) || (TargetPayload == NULL) || IS_EMPTY_STRING (Json)) {
return EFI_INVALID_PARAMETER;
}
@@ -1935,8 +1988,8 @@ CreatePayloadToPatchResource (
goto EXIT_FREE_JSON_VALUE;
}
- ZeroMem (&PostResponse, sizeof (REDFISH_RESPONSE));
- Status = RedfishPatchToPayload (TargetPayload, Payload, &PostResponse);
+ ZeroMem (&PatchResponse, sizeof (REDFISH_RESPONSE));
+ Status = RedfishPatchToPayload (TargetPayload, Payload, &PatchResponse);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "%a:%d Failed to PATCH payload to Redfish service.\n", __func__, __LINE__));
@@ -1944,7 +1997,7 @@ CreatePayloadToPatchResource (
DEBUG ((DEBUG_ERROR, "%a: Request:\n", __func__));
DumpRedfishPayload (DEBUG_ERROR, Payload);
DEBUG ((DEBUG_ERROR, "%a: Response:\n", __func__));
- DumpRedfishResponse (__func__, DEBUG_ERROR, &PostResponse);
+ DumpRedfishResponse (__func__, DEBUG_ERROR, &PatchResponse);
DEBUG_CODE_END ();
goto EXIT_FREE_JSON_VALUE;
}
@@ -1952,16 +2005,20 @@ CreatePayloadToPatchResource (
//
// Find ETag
//
- Status = GetEtagAndLocation (&PostResponse, Etag, NULL);
- if (EFI_ERROR (Status)) {
+ Status = GetHttpResponseEtag (&PatchResponse, Etag);
+ if (Status == EFI_UNSUPPORTED) {
+ Status = EFI_SUCCESS;
+ DEBUG ((DEBUG_INFO, "%a: WARNING - ETAG is not supported on Redfish service.\n", __func__));
+ } else {
Status = EFI_DEVICE_ERROR;
+ DEBUG ((DEBUG_ERROR, "%a: Fail to get Location header nor proerty from HTTP response payload.\n", __func__));
}
RedfishFreeResponse (
- PostResponse.StatusCode,
- PostResponse.HeaderCount,
- PostResponse.Headers,
- PostResponse.Payload
+ PatchResponse.StatusCode,
+ PatchResponse.HeaderCount,
+ PatchResponse.Headers,
+ PatchResponse.Payload
);
EXIT_FREE_JSON_VALUE:
@@ -1994,7 +2051,7 @@ CreatePayloadToPostResource (
IN REDFISH_PAYLOAD *TargetPayload,
IN CHAR8 *Json,
OUT EFI_STRING *Location,
- OUT CHAR8 **Etag
+ OUT CHAR8 **Etag OPTIONAL
)
{
REDFISH_PAYLOAD Payload;
@@ -2002,7 +2059,7 @@ CreatePayloadToPostResource (
REDFISH_RESPONSE PostResponse;
EFI_STATUS Status;
- if ((Service == NULL) || (TargetPayload == NULL) || IS_EMPTY_STRING (Json) || (Location == NULL) || (Etag == NULL)) {
+ if ((Service == NULL) || (TargetPayload == NULL) || IS_EMPTY_STRING (Json) || (Location == NULL)) {
return EFI_INVALID_PARAMETER;
}
@@ -2029,12 +2086,22 @@ CreatePayloadToPostResource (
goto EXIT_FREE_JSON_VALUE;
}
+ Status = GetHttpResponseEtag (&PostResponse, Etag);
+ if (Status == EFI_UNSUPPORTED) {
+ Status = EFI_SUCCESS;
+ DEBUG ((DEBUG_INFO, "%a: WARNING - ETAG is not supported on Redfish service.\n", __func__));
+ } else if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ DEBUG ((DEBUG_ERROR, "%a: Fail to get ETAG header nor ETAG propertyfrom HTTP response payload.\n", __func__));
+ }
+
//
// per Redfish spec. the URL of new resource will be returned in "Location" header.
//
- Status = GetEtagAndLocation (&PostResponse, Etag, Location);
+ Status = GetHttpResponseLocation (&PostResponse, Location);
if (EFI_ERROR (Status)) {
Status = EFI_DEVICE_ERROR;
+ DEBUG ((DEBUG_ERROR, "%a: Fail to get Location header nor proerty from HTTP response payload.\n", __func__));
}
RedfishFreeResponse (
@@ -3176,6 +3243,11 @@ CheckEtag (
{
CHAR8 *EtagInDb;
+ if (!CheckIsServerEtagSupported ()) {
+ DEBUG ((DEBUG_INFO, "%a: WARNING - ETAG is not supported, always returns FALSE to consume resource (Performance would be reduced).\n", __func__));
+ return FALSE;
+ }
+
if (IS_EMPTY_STRING (Uri)) {
return FALSE;
}
--
2.37.1.windows.1
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#113059): https://edk2.groups.io/g/devel/message/113059
Mute This Topic: https://groups.io/mt/103498331/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2024-01-03 7:54 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-01-03 7:53 [edk2-devel] [edk2-redfish-client][PATCH] RedfishClientPkg: Add ETag PCD and revise Redfish ETag functions Chang, Abner via groups.io
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox