All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH phosphor-host-ipmid v5] Implement Network Override
@ 2016-06-16 14:50 OpenBMC Patches
  2016-06-16 14:50 ` [PATCH phosphor-host-ipmid v5] Resolves openbmc/openbmc#267' OpenBMC Patches
  0 siblings, 1 reply; 5+ messages in thread
From: OpenBMC Patches @ 2016-06-16 14:50 UTC (permalink / raw)
  To: openbmc



<!-- Reviewable:start -->
This change is [<img src="https://reviewable.io/review_button.svg" height="35" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/openbmc/phosphor-host-ipmid/90)
<!-- Reviewable:end -->


https://github.com/openbmc/phosphor-host-ipmid/pull/90

ratagupt (1):
  Resolves openbmc/openbmc#267'

 chassishandler.C | 212 +++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 200 insertions(+), 12 deletions(-)

-- 
2.8.4

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH phosphor-host-ipmid v5] Resolves openbmc/openbmc#267'
  2016-06-16 14:50 [PATCH phosphor-host-ipmid v5] Implement Network Override OpenBMC Patches
@ 2016-06-16 14:50 ` OpenBMC Patches
  2016-06-17  5:47   ` Samuel Mendoza-Jonas
  0 siblings, 1 reply; 5+ messages in thread
From: OpenBMC Patches @ 2016-06-16 14:50 UTC (permalink / raw)
  To: openbmc; +Cc: ratagupt

From: ratagupt <ratagupt@in.ibm.com>

---
 chassishandler.C | 212 +++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 200 insertions(+), 12 deletions(-)

diff --git a/chassishandler.C b/chassishandler.C
index d5b3404..2cc0895 100644
--- a/chassishandler.C
+++ b/chassishandler.C
@@ -1,17 +1,25 @@
 #include "chassishandler.h"
 #include "ipmid-api.h"
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 #include <stdint.h>
-
-
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <string>
+#include <sstream>
+#include <array>
+using namespace std;
 //Defines
-#define SET_PARM_VERSION 1
-#define SET_PARM_BOOT_FLAGS_PERMANENT 0x40 //boot flags data1 7th bit on
+#define SET_PARM_VERSION                     0x01
+#define SET_PARM_BOOT_FLAGS_PERMANENT        0x40 //boot flags data1 7th bit on
 #define SET_PARM_BOOT_FLAGS_VALID_ONE_TIME   0x80 //boot flags data1 8th bit on
 #define SET_PARM_BOOT_FLAGS_VALID_PERMANENT  0xC0 //boot flags data1 7 & 8 bit on 
 
-
+#define SIZE_MAC                             18
+#define SIZE_HOST_NETWORK_DATA               26
+#define SIZE_BOOT_OPTION                     SIZE_HOST_NETWORK_DATA
+#define SIZE_PREFIX                          7
 
 // OpenBMC Chassis Manager dbus framework
 const char  *chassis_bus_name      =  "org.openbmc.control.Chassis";
@@ -233,14 +241,174 @@ struct get_sys_boot_options_t {
 struct get_sys_boot_options_response_t {
     uint8_t version;
     uint8_t parm;
-    uint8_t data[5];
+    uint8_t data[SIZE_BOOT_OPTION];
 }  __attribute__ ((packed));
 
 struct set_sys_boot_options_t {
     uint8_t parameter;
-    uint8_t data[8];
+    uint8_t data[SIZE_BOOT_OPTION];
 }  __attribute__ ((packed));
 
+struct host_network_config_t {
+     string ipaddress;
+     string prefix;
+     string gateway;
+     string macaddress;
+     string isDHCP;
+
+     host_network_config_t():ipaddress(),prefix(),gateway(),macaddress() {}
+};
+
+uint8_t getHostNetworkData(get_sys_boot_options_response_t *respptr)
+{
+    char *prop = NULL;
+
+    std::array<uint8_t, SIZE_BOOT_OPTION> respData{0x80,0x21, 0x70 ,0x62 ,0x21,0x00 ,0x01 ,0x06 ,0x04};
+
+    int rc = dbus_get_property("network_config",&prop);
+
+    if (rc < 0) {
+        fprintf(stderr, "Dbus get property(boot_flags) failed for get_sys_boot_options.\n");
+        return rc;
+    }
+
+    /* network_config property Value would be in the form of 
+     * ipaddress=1.1.1.1,prefix=16,gateway=2.2.2.2,mac=11:22:33:44:55:66,dhcp=0
+     */
+
+    /* Parsing the string and fill the hostconfig structure with the 
+     * values */
+
+    host_network_config_t host_config;
+    string delimiter = ",";
+
+    size_t pos = 0;
+    string token,name,value;
+    string conf_str(prop);
+    
+    printf ("Configuration String[%s]\n ",conf_str.c_str());
+
+    while ( conf_str.length() > 0) {
+
+        pos = conf_str.find(delimiter);
+
+        //This condition is to extract the last 
+        //Substring as we will not be having the delimeter 
+        //at end. std::string::npos is -1
+        
+        if ( pos == std::string::npos )
+        { 
+           pos = conf_str.length();
+        }
+        token = conf_str.substr(0, pos);
+        int pos1 = token.find("=");
+
+        name = token.substr(0,pos1);
+        value = token.substr(pos1+1,pos);
+
+        if ( name == "ipaddress" )
+            host_config.ipaddress = value;
+        else if ( name == "prefix")
+            host_config.prefix = value; 
+        else if ( name == "gateway" )
+            host_config.gateway = value;
+        else if ( name == "mac" )
+            host_config.macaddress = value;
+        else if ( name == "dhcp" )
+            host_config.isDHCP = value;
+        
+        conf_str.erase(0, pos + delimiter.length());
+    }
+
+    //Starting from index 9 as 9 bytes are prefilled.
+
+    pos = 0; 
+    delimiter = ":";
+    uint8_t resp_byte = 0;
+    uint8_t index = 9;
+    
+    while ((pos = host_config.macaddress.find(delimiter)) != std::string::npos) {
+
+        token = host_config.macaddress.substr(0, pos);
+        resp_byte = strtoul(token.c_str(), NULL, 16);
+        memcpy((void*)&respData[index], &resp_byte, 1);
+        host_config.macaddress.erase(0, pos + delimiter.length());
+        index++;
+    }
+
+    resp_byte = strtoul(host_config.macaddress.c_str(), NULL, 16);
+    memcpy((void*)&respData[index++], &resp_byte, 1);
+
+    //Conevrt the dhcp,ipaddress,mask and gateway as hex number
+    respData[index++]=0x00;
+    sscanf(host_config.isDHCP.c_str(),"%02X",&respData[index++]);
+
+    inet_pton(AF_INET,host_config.ipaddress.c_str(),(void *)&respData[index]);
+    index+=4;
+
+    sscanf(host_config.prefix.c_str(),"%02d",&respData[index++]);
+    inet_pton(AF_INET,host_config.gateway.c_str(),(void *)&respData[index]);
+    index+=4; 
+    
+    printf ("\n===Printing the IPMI Formatted Data========\n");
+
+    for (int j = 0;j<index;j++)
+        printf("%02x ", respData[j]);
+
+    memcpy(respptr->data,respData.data(),SIZE_BOOT_OPTION);
+    return 0;
+}
+
+uint8_t setHostNetworkData(set_sys_boot_options_t * reqptr)
+{
+    string host_network_config;
+    char mac[SIZE_MAC] = {0};
+    char ipAddress[INET_ADDRSTRLEN] = {0};
+    char gateway[INET_ADDRSTRLEN] = {0};
+    char dhcp[SIZE_PREFIX] = {0};
+    char prefix[SIZE_PREFIX] = {0};
+    uint32_t cookie = 0;
+
+    memcpy(&cookie,(char *)&(reqptr->data[1]),sizeof(cookie));
+    
+    uint8_t index = 9;  
+
+    if ( cookie) {
+     
+            snprintf(mac, SIZE_MAC, "%02x:%02x:%02x:%02x:%02x:%02x",
+            reqptr->data[index],
+            reqptr->data[index+1],
+            reqptr->data[index+2],
+            reqptr->data[index+3],
+            reqptr->data[index+4],
+            reqptr->data[index+5]);
+    
+        snprintf(dhcp,SIZE_PREFIX, "%d", reqptr->data[index+7]);
+
+        snprintf(ipAddress, INET_ADDRSTRLEN, "%d.%d.%d.%d",
+            reqptr->data[index+8], reqptr->data[index+9], reqptr->data[index+10], reqptr->data[index+11]);
+
+        snprintf(prefix,SIZE_PREFIX,"%d", reqptr->data[index+12]);
+
+        snprintf(gateway, INET_ADDRSTRLEN, "%d.%d.%d.%d",
+            reqptr->data[index+13], reqptr->data[index+14], reqptr->data[index+15], reqptr->data[index+16]);
+    }
+
+    host_network_config += "ipaddress="+string(ipAddress)+",prefix="+ \
+                       string(prefix)+",gateway="+string(gateway)+\
+                       ",mac="+string(mac)+",dhcp="+string(dhcp);
+
+    printf ("Network configuration changed: %s\n",host_network_config.c_str());
+
+    int r = dbus_set_property("network_config",host_network_config.c_str());
+
+    if (r < 0) {
+        fprintf(stderr, "Dbus set property(network_config) failed for set_sys_boot_options.\n");
+        r = IPMI_CC_UNSPECIFIED_ERROR;
+    }
+    return r;
+}
+
 ipmi_ret_t ipmi_chassis_wildcard(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 
                               ipmi_request_t request, ipmi_response_t response, 
                               ipmi_data_len_t data_len, ipmi_context_t context)
@@ -446,7 +614,18 @@ ipmi_ret_t ipmi_chassis_get_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
         }
 
 
-    } else {
+    } else if ( reqptr->parameter == 0x61 ) {
+       resp->parm      = 0x61;
+       int ret = getHostNetworkData(resp);
+       if (ret < 0) {
+           fprintf(stderr, "getHostNetworkData failed for get_sys_boot_options.\n");
+           rc = IPMI_CC_UNSPECIFIED_ERROR;
+
+       }else
+          rc = IPMI_CC_OK;
+    }
+
+    else {
         fprintf(stderr, "Unsupported parameter 0x%x\n", reqptr->parameter);
     }
 
@@ -464,11 +643,10 @@ ipmi_ret_t ipmi_chassis_set_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
 {
     ipmi_ret_t rc = IPMI_CC_OK;
     char *s;
-
-    printf("IPMI SET_SYS_BOOT_OPTIONS\n");
-
     set_sys_boot_options_t *reqptr = (set_sys_boot_options_t *) request;
 
+    printf("IPMI SET_SYS_BOOT_OPTIONS reqptr->parameter =[%d]\n",reqptr->parameter);
+
     // This IPMI command does not have any resposne data
     *data_len = 0;
 
@@ -476,6 +654,7 @@ ipmi_ret_t ipmi_chassis_set_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
      * Parameter #5 means boot flags. Please refer to 28.13 of ipmi doc.
      * This is the only parameter used by petitboot.
      */
+
     if (reqptr->parameter == 5) {
 
         s = get_boot_option_by_ipmi(((reqptr->data[1] & 0x3C) >> 2));
@@ -507,7 +686,16 @@ ipmi_ret_t ipmi_chassis_set_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
             rc = IPMI_CC_UNSPECIFIED_ERROR;
         }
 
-    } else {
+    }
+    else if ( reqptr->parameter == 0x61 ) {
+       printf("IPMI SET_SYS_BOOT_OPTIONS reqptr->parameter =[%d]\n",reqptr->parameter);
+       int ret = setHostNetworkData(reqptr);
+       if (ret < 0) {
+           fprintf(stderr, "setHostNetworkData failed for set_sys_boot_options.\n");
+           rc = IPMI_CC_UNSPECIFIED_ERROR;
+       }
+    }      
+    else {
         fprintf(stderr, "Unsupported parameter 0x%x\n", reqptr->parameter);
         rc = IPMI_CC_PARM_NOT_SUPPORTED;
     }
-- 
2.8.4

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH phosphor-host-ipmid v5] Resolves openbmc/openbmc#267'
  2016-06-16 14:50 ` [PATCH phosphor-host-ipmid v5] Resolves openbmc/openbmc#267' OpenBMC Patches
@ 2016-06-17  5:47   ` Samuel Mendoza-Jonas
  2016-06-17 11:48     ` Ratan K Gupta
  0 siblings, 1 reply; 5+ messages in thread
From: Samuel Mendoza-Jonas @ 2016-06-17  5:47 UTC (permalink / raw)
  To: OpenBMC Patches; +Cc: openbmc, ratagupt

Hi Ratan,

I have some notes below, but mainly I have these two questions:

- What is the purpose of the host_network_config struct, and why is the
  request parsed into a string before being stored? Why not just store
  the original request as is?
- Do you have tests to verify the correctness of the hex produced?

Cheers,
Sam

On Thu, Jun 16, 2016 at 09:50:40AM -0500, OpenBMC Patches wrote:
> From: ratagupt <ratagupt@in.ibm.com>
> 
> ---
>  chassishandler.C | 212 +++++++++++++++++++++++++++++++++++++++++++++++++++----
>  1 file changed, 200 insertions(+), 12 deletions(-)
> 
> diff --git a/chassishandler.C b/chassishandler.C
> index d5b3404..2cc0895 100644
> --- a/chassishandler.C
> +++ b/chassishandler.C
> @@ -1,17 +1,25 @@
>  #include "chassishandler.h"
>  #include "ipmid-api.h"
>  #include <stdio.h>
> +#include <stdlib.h>
>  #include <string.h>
>  #include <stdint.h>
> -
> -
> +#include <arpa/inet.h>
> +#include <netinet/in.h>
> +#include <string>
> +#include <sstream>
> +#include <array>
> +using namespace std;
>  //Defines
> -#define SET_PARM_VERSION 1
> -#define SET_PARM_BOOT_FLAGS_PERMANENT 0x40 //boot flags data1 7th bit on
> +#define SET_PARM_VERSION                     0x01
> +#define SET_PARM_BOOT_FLAGS_PERMANENT        0x40 //boot flags data1 7th bit on
>  #define SET_PARM_BOOT_FLAGS_VALID_ONE_TIME   0x80 //boot flags data1 8th bit on
>  #define SET_PARM_BOOT_FLAGS_VALID_PERMANENT  0xC0 //boot flags data1 7 & 8 bit on 
>  
> -
> +#define SIZE_MAC                             18
> +#define SIZE_HOST_NETWORK_DATA               26

How did you decide on the size for SIZE_HOST_NETWORK_DATA?

> +#define SIZE_BOOT_OPTION                     SIZE_HOST_NETWORK_DATA
> +#define SIZE_PREFIX                          7
>  
>  // OpenBMC Chassis Manager dbus framework
>  const char  *chassis_bus_name      =  "org.openbmc.control.Chassis";
> @@ -233,14 +241,174 @@ struct get_sys_boot_options_t {
>  struct get_sys_boot_options_response_t {
>      uint8_t version;
>      uint8_t parm;
> -    uint8_t data[5];
> +    uint8_t data[SIZE_BOOT_OPTION];
>  }  __attribute__ ((packed));
>  
>  struct set_sys_boot_options_t {
>      uint8_t parameter;
> -    uint8_t data[8];
> +    uint8_t data[SIZE_BOOT_OPTION];
>  }  __attribute__ ((packed));
>  
> +struct host_network_config_t {
> +     string ipaddress;
> +     string prefix;
> +     string gateway;
> +     string macaddress;
> +     string isDHCP;

Is there a need to have these all as strings?

> +
> +     host_network_config_t():ipaddress(),prefix(),gateway(),macaddress() {}
> +};
> +
> +uint8_t getHostNetworkData(get_sys_boot_options_response_t *respptr)
> +{
> +    char *prop = NULL;
> +
> +    std::array<uint8_t, SIZE_BOOT_OPTION> respData{0x80,0x21, 0x70 ,0x62 ,0x21,0x00 ,0x01 ,0x06 ,0x04};

The "0x21, 0x70 ,0x62 ,0x21" cookie is a magic value that Petitboot uses
to recognise an override message it can read. Using it unconditionally
here means that openbmc would be hard-coded to only support Petitboot,
is that what we, or other users would expect?

> +
> +    int rc = dbus_get_property("network_config",&prop);
> +
> +    if (rc < 0) {
> +        fprintf(stderr, "Dbus get property(boot_flags) failed for get_sys_boot_options.\n");
> +        return rc;
> +    }
> +
> +    /* network_config property Value would be in the form of 
> +     * ipaddress=1.1.1.1,prefix=16,gateway=2.2.2.2,mac=11:22:33:44:55:66,dhcp=0
> +     */
> +
> +    /* Parsing the string and fill the hostconfig structure with the 
> +     * values */

If I'm reading this right the host_config structure is filled in
according to the "network_config" string, and then each field is copied
into respData - would it be simpler to skip the structure and just
fill in respData?

> +
> +    host_network_config_t host_config;
> +    string delimiter = ",";
> +
> +    size_t pos = 0;
> +    string token,name,value;
> +    string conf_str(prop);
> +    
> +    printf ("Configuration String[%s]\n ",conf_str.c_str());

Should we print this all the time, or just on debug?

> +
> +    while ( conf_str.length() > 0) {
> +
> +        pos = conf_str.find(delimiter);
> +
> +        //This condition is to extract the last 
> +        //Substring as we will not be having the delimeter 
> +        //at end. std::string::npos is -1
> +        
> +        if ( pos == std::string::npos )
> +        { 
> +           pos = conf_str.length();
> +        }
> +        token = conf_str.substr(0, pos);
> +        int pos1 = token.find("=");
> +
> +        name = token.substr(0,pos1);
> +        value = token.substr(pos1+1,pos);
> +
> +        if ( name == "ipaddress" )
> +            host_config.ipaddress = value;
> +        else if ( name == "prefix")
> +            host_config.prefix = value; 
> +        else if ( name == "gateway" )
> +            host_config.gateway = value;
> +        else if ( name == "mac" )
> +            host_config.macaddress = value;
> +        else if ( name == "dhcp" )
> +            host_config.isDHCP = value;
> +        
> +        conf_str.erase(0, pos + delimiter.length());
> +    }
> +
> +    //Starting from index 9 as 9 bytes are prefilled.
> +
> +    pos = 0; 
> +    delimiter = ":";
> +    uint8_t resp_byte = 0;
> +    uint8_t index = 9;
> +    
> +    while ((pos = host_config.macaddress.find(delimiter)) != std::string::npos) {
> +
> +        token = host_config.macaddress.substr(0, pos);
> +        resp_byte = strtoul(token.c_str(), NULL, 16);

Would be a good idea to check strtoul for errors

> +        memcpy((void*)&respData[index], &resp_byte, 1);

Don't need to cast to (void*)

> +        host_config.macaddress.erase(0, pos + delimiter.length());
> +        index++;
> +    }
> +
> +    resp_byte = strtoul(host_config.macaddress.c_str(), NULL, 16);
> +    memcpy((void*)&respData[index++], &resp_byte, 1);

Same

> +
> +    //Conevrt the dhcp,ipaddress,mask and gateway as hex number

Typo, Conevrt/Convert

> +    respData[index++]=0x00;
> +    sscanf(host_config.isDHCP.c_str(),"%02X",&respData[index++]);
> +
> +    inet_pton(AF_INET,host_config.ipaddress.c_str(),(void *)&respData[index]);
> +    index+=4;
> +
> +    sscanf(host_config.prefix.c_str(),"%02d",&respData[index++]);
> +    inet_pton(AF_INET,host_config.gateway.c_str(),(void *)&respData[index]);
> +    index+=4; 
> +    
> +    printf ("\n===Printing the IPMI Formatted Data========\n");

As above, debug message?

> +
> +    for (int j = 0;j<index;j++)

Spacing it out like this is easier to read:

    for (int j = 0; j < index; j++)

> +        printf("%02x ", respData[j]);
> +
> +    memcpy(respptr->data,respData.data(),SIZE_BOOT_OPTION);
> +    return 0;
> +}
> +
> +uint8_t setHostNetworkData(set_sys_boot_options_t * reqptr)
> +{
> +    string host_network_config;
> +    char mac[SIZE_MAC] = {0};
> +    char ipAddress[INET_ADDRSTRLEN] = {0};
> +    char gateway[INET_ADDRSTRLEN] = {0};
> +    char dhcp[SIZE_PREFIX] = {0};
> +    char prefix[SIZE_PREFIX] = {0};
> +    uint32_t cookie = 0;
> +
> +    memcpy(&cookie,(char *)&(reqptr->data[1]),sizeof(cookie));
> +    
> +    uint8_t index = 9;  
> +
> +    if ( cookie) {
> +     
> +            snprintf(mac, SIZE_MAC, "%02x:%02x:%02x:%02x:%02x:%02x",
> +            reqptr->data[index],
> +            reqptr->data[index+1],
> +            reqptr->data[index+2],
> +            reqptr->data[index+3],
> +            reqptr->data[index+4],
> +            reqptr->data[index+5]);
> +    
> +        snprintf(dhcp,SIZE_PREFIX, "%d", reqptr->data[index+7]);

*If* this is following the format used by Petitboot, is the order of
fields here correct? It looks like the size fields have been skipped.

> +
> +        snprintf(ipAddress, INET_ADDRSTRLEN, "%d.%d.%d.%d",
> +            reqptr->data[index+8], reqptr->data[index+9], reqptr->data[index+10], reqptr->data[index+11]);
> +
> +        snprintf(prefix,SIZE_PREFIX,"%d", reqptr->data[index+12]);

What is the prefix? Is it meant to be the subnet mask?

> +
> +        snprintf(gateway, INET_ADDRSTRLEN, "%d.%d.%d.%d",
> +            reqptr->data[index+13], reqptr->data[index+14], reqptr->data[index+15], reqptr->data[index+16]);
> +    }
> +
> +    host_network_config += "ipaddress="+string(ipAddress)+",prefix="+ \
> +                       string(prefix)+",gateway="+string(gateway)+\
> +                       ",mac="+string(mac)+",dhcp="+string(dhcp);
> +
> +    printf ("Network configuration changed: %s\n",host_network_config.c_str());
> +
> +    int r = dbus_set_property("network_config",host_network_config.c_str());
> +
> +    if (r < 0) {
> +        fprintf(stderr, "Dbus set property(network_config) failed for set_sys_boot_options.\n");
> +        r = IPMI_CC_UNSPECIFIED_ERROR;
> +    }
> +    return r;
> +}
> +
>  ipmi_ret_t ipmi_chassis_wildcard(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 
>                                ipmi_request_t request, ipmi_response_t response, 
>                                ipmi_data_len_t data_len, ipmi_context_t context)
> @@ -446,7 +614,18 @@ ipmi_ret_t ipmi_chassis_get_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
>          }
>  
>  
> -    } else {
> +    } else if ( reqptr->parameter == 0x61 ) {
> +       resp->parm      = 0x61;
> +       int ret = getHostNetworkData(resp);
> +       if (ret < 0) {
> +           fprintf(stderr, "getHostNetworkData failed for get_sys_boot_options.\n");
> +           rc = IPMI_CC_UNSPECIFIED_ERROR;
> +
> +       }else
> +          rc = IPMI_CC_OK;
> +    }
> +
> +    else {
>          fprintf(stderr, "Unsupported parameter 0x%x\n", reqptr->parameter);
>      }
>  
> @@ -464,11 +643,10 @@ ipmi_ret_t ipmi_chassis_set_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
>  {
>      ipmi_ret_t rc = IPMI_CC_OK;
>      char *s;
> -
> -    printf("IPMI SET_SYS_BOOT_OPTIONS\n");
> -
>      set_sys_boot_options_t *reqptr = (set_sys_boot_options_t *) request;
>  
> +    printf("IPMI SET_SYS_BOOT_OPTIONS reqptr->parameter =[%d]\n",reqptr->parameter);
> +
>      // This IPMI command does not have any resposne data
>      *data_len = 0;
>  
> @@ -476,6 +654,7 @@ ipmi_ret_t ipmi_chassis_set_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
>       * Parameter #5 means boot flags. Please refer to 28.13 of ipmi doc.
>       * This is the only parameter used by petitboot.
>       */
> +

Extra line

>      if (reqptr->parameter == 5) {
>  
>          s = get_boot_option_by_ipmi(((reqptr->data[1] & 0x3C) >> 2));
> @@ -507,7 +686,16 @@ ipmi_ret_t ipmi_chassis_set_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
>              rc = IPMI_CC_UNSPECIFIED_ERROR;
>          }
>  
> -    } else {
> +    }
> +    else if ( reqptr->parameter == 0x61 ) {
> +       printf("IPMI SET_SYS_BOOT_OPTIONS reqptr->parameter =[%d]\n",reqptr->parameter);
> +       int ret = setHostNetworkData(reqptr);
> +       if (ret < 0) {
> +           fprintf(stderr, "setHostNetworkData failed for set_sys_boot_options.\n");
> +           rc = IPMI_CC_UNSPECIFIED_ERROR;
> +       }
> +    }      
> +    else {
>          fprintf(stderr, "Unsupported parameter 0x%x\n", reqptr->parameter);
>          rc = IPMI_CC_PARM_NOT_SUPPORTED;
>      }
> -- 
> 2.8.4
> 
> 
> _______________________________________________
> openbmc mailing list
> openbmc@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/openbmc

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH phosphor-host-ipmid v5] Resolves openbmc/openbmc#267'
  2016-06-17  5:47   ` Samuel Mendoza-Jonas
@ 2016-06-17 11:48     ` Ratan K Gupta
  2016-06-20  0:25       ` Samuel Mendoza-Jonas
  0 siblings, 1 reply; 5+ messages in thread
From: Ratan K Gupta @ 2016-06-17 11:48 UTC (permalink / raw)
  To: sam; +Cc: openbmc-patches, openbmc

[-- Attachment #1: Type: text/html, Size: 19447 bytes --]

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH phosphor-host-ipmid v5] Resolves openbmc/openbmc#267'
  2016-06-17 11:48     ` Ratan K Gupta
@ 2016-06-20  0:25       ` Samuel Mendoza-Jonas
  0 siblings, 0 replies; 5+ messages in thread
From: Samuel Mendoza-Jonas @ 2016-06-20  0:25 UTC (permalink / raw)
  To: Ratan K Gupta; +Cc: openbmc, openbmc-patches

On Fri, Jun 17, 2016 at 11:48:52AM +0000, Ratan K Gupta wrote:
> Hi Sam,
>  
> Thanks for looking at the code.
>  
> Please find the response inline.
>  
> - What is the purpose of the host_network_config struct, and why is the
>   request parsed into a string before being stored? Why not just store
>   the original request as is?
>  
>   RG>>>This host config data is configured through REST/HOST(IPMI
> Client),Through REST we are configuring the data in human readable string,It is
> cumbersome for the user to enter the data in correct format in Hexadecimal
> through REST.

Right, using the readable string for the REST interface is good, but in
getHostNetworkData() for example, it looks like you
	- Get the network_config property (the string)
	- Parse it into the host_network_config_t struct
	- Parse the struct into a hex string

What purpose does the host_network_config_t struct serve?

> 
> - Do you have tests to verify the correctness of the hex produced?
>   RG>>I verified it in my unit testing that it was working fine.I was setting
> the data through REST and getting it via IPMI and viceversa also.
>    
>      Is there a path where you think that Hex will not be correct? Please let
> me know so that I can look into it.

There was one part I wasn't sure about - please see the comments I made
inline orginally below:

>     
>  
>    Regards
>    Ratan Gupta
>  
>  
> 
>     ----- Original message -----
>     From: Samuel Mendoza-Jonas <sam@mendozajonas.com>
>     To: OpenBMC Patches <openbmc-patches@stwcx.xyz>
>     Cc: openbmc@lists.ozlabs.org, Ratan K Gupta/India/IBM@IBMIN
>     Subject: Re: [PATCH phosphor-host-ipmid v5] Resolves openbmc/openbmc#267'
>     Date: Fri, Jun 17, 2016 11:17 AM
>      
>     Hi Ratan,
> 
>     I have some notes below, but mainly I have these two questions:
> 
>     - What is the purpose of the host_network_config struct, and why is the
>       request parsed into a string before being stored? Why not just store
>       the original request as is?
>     - Do you have tests to verify the correctness of the hex produced?
> 
>     Cheers,
>     Sam
> 
>     On Thu, Jun 16, 2016 at 09:50:40AM -0500, OpenBMC Patches wrote:
>     > From: ratagupt <ratagupt@in.ibm.com>
>     >
>     > ---
>     >  chassishandler.C | 212
>     +++++++++++++++++++++++++++++++++++++++++++++++++++----
>     >  1 file changed, 200 insertions(+), 12 deletions(-)
>     >
>     > diff --git a/chassishandler.C b/chassishandler.C
>     > index d5b3404..2cc0895 100644
>     > --- a/chassishandler.C
>     > +++ b/chassishandler.C
>     > @@ -1,17 +1,25 @@
>     >  #include "chassishandler.h"
>     >  #include "ipmid-api.h"
>     >  #include <stdio.h>
>     > +#include <stdlib.h>
>     >  #include <string.h>
>     >  #include <stdint.h>
>     > -
>     > -
>     > +#include <arpa/inet.h>
>     > +#include <netinet/in.h>
>     > +#include <string>
>     > +#include <sstream>
>     > +#include <array>
>     > +using namespace std;
>     >  //Defines
>     > -#define SET_PARM_VERSION 1
>     > -#define SET_PARM_BOOT_FLAGS_PERMANENT 0x40 //boot flags data1 7th bit on
>     > +#define SET_PARM_VERSION                     0x01
>     > +#define SET_PARM_BOOT_FLAGS_PERMANENT        0x40 //boot flags data1 7th
>     bit on
>     >  #define SET_PARM_BOOT_FLAGS_VALID_ONE_TIME   0x80 //boot flags data1 8th
>     bit on
>     >  #define SET_PARM_BOOT_FLAGS_VALID_PERMANENT  0xC0 //boot flags data1 7 &
>     8 bit on
>     >  
>     > -
>     > +#define SIZE_MAC                             18
>     > +#define SIZE_HOST_NETWORK_DATA               26
> 
>     How did you decide on the size for SIZE_HOST_NETWORK_DATA?
> 
>     > +#define SIZE_BOOT_OPTION                     SIZE_HOST_NETWORK_DATA
>     > +#define SIZE_PREFIX                          7
>     >  
>     >  // OpenBMC Chassis Manager dbus framework
>     >  const char  *chassis_bus_name      =  "org.openbmc.control.Chassis";
>     > @@ -233,14 +241,174 @@ struct get_sys_boot_options_t {
>     >  struct get_sys_boot_options_response_t {
>     >      uint8_t version;
>     >      uint8_t parm;
>     > -    uint8_t data[5];
>     > +    uint8_t data[SIZE_BOOT_OPTION];
>     >  }  __attribute__ ((packed));
>     >  
>     >  struct set_sys_boot_options_t {
>     >      uint8_t parameter;
>     > -    uint8_t data[8];
>     > +    uint8_t data[SIZE_BOOT_OPTION];
>     >  }  __attribute__ ((packed));
>     >  
>     > +struct host_network_config_t {
>     > +     string ipaddress;
>     > +     string prefix;
>     > +     string gateway;
>     > +     string macaddress;
>     > +     string isDHCP;
> 
>     Is there a need to have these all as strings?
> 
>     > +
>     > +     host_network_config_t():ipaddress(),prefix(),gateway(),macaddress()
>     {}
>     > +};
>     > +
>     > +uint8_t getHostNetworkData(get_sys_boot_options_response_t *respptr)
>     > +{
>     > +    char *prop = NULL;
>     > +
>     > +    std::array<uint8_t, SIZE_BOOT_OPTION> respData{0x80,0x21, 0x70 ,0x62
>     ,0x21,0x00 ,0x01 ,0x06 ,0x04};
> 
>     The "0x21, 0x70 ,0x62 ,0x21" cookie is a magic value that Petitboot uses
>     to recognise an override message it can read. Using it unconditionally
>     here means that openbmc would be hard-coded to only support Petitboot,
>     is that what we, or other users would expect?
> 
>     > +
>     > +    int rc = dbus_get_property("network_config",&prop);
>     > +
>     > +    if (rc < 0) {
>     > +        fprintf(stderr, "Dbus get property(boot_flags) failed for
>     get_sys_boot_options.\n");
>     > +        return rc;
>     > +    }
>     > +
>     > +    /* network_config property Value would be in the form of
>     > +     * ipaddress=1.1.1.1,prefix=16,gateway=2.2.2.2,mac=
>     11:22:33:44:55:66,dhcp=0
>     > +     */
>     > +
>     > +    /* Parsing the string and fill the hostconfig structure with the
>     > +     * values */
> 
>     If I'm reading this right the host_config structure is filled in
>     according to the "network_config" string, and then each field is copied
>     into respData - would it be simpler to skip the structure and just
>     fill in respData?
> 
>     > +
>     > +    host_network_config_t host_config;
>     > +    string delimiter = ",";
>     > +
>     > +    size_t pos = 0;
>     > +    string token,name,value;
>     > +    string conf_str(prop);
>     > +    
>     > +    printf ("Configuration String[%s]\n ",conf_str.c_str());
> 
>     Should we print this all the time, or just on debug?
> 
>     > +
>     > +    while ( conf_str.length() > 0) {
>     > +
>     > +        pos = conf_str.find(delimiter);
>     > +
>     > +        //This condition is to extract the last
>     > +        //Substring as we will not be having the delimeter
>     > +        //at end. std::string::npos is -1
>     > +        
>     > +        if ( pos == std::string::npos )
>     > +        {
>     > +           pos = conf_str.length();
>     > +        }
>     > +        token = conf_str.substr(0, pos);
>     > +        int pos1 = token.find("=");
>     > +
>     > +        name = token.substr(0,pos1);
>     > +        value = token.substr(pos1+1,pos);
>     > +
>     > +        if ( name == "ipaddress" )
>     > +            host_config.ipaddress = value;
>     > +        else if ( name == "prefix")
>     > +            host_config.prefix = value;
>     > +        else if ( name == "gateway" )
>     > +            host_config.gateway = value;
>     > +        else if ( name == "mac" )
>     > +            host_config.macaddress = value;
>     > +        else if ( name == "dhcp" )
>     > +            host_config.isDHCP = value;
>     > +        
>     > +        conf_str.erase(0, pos + delimiter.length());
>     > +    }
>     > +
>     > +    //Starting from index 9 as 9 bytes are prefilled.
>     > +
>     > +    pos = 0;
>     > +    delimiter = ":";
>     > +    uint8_t resp_byte = 0;
>     > +    uint8_t index = 9;
>     > +    
>     > +    while ((pos = host_config.macaddress.find(delimiter)) !=
>     std::string::npos) {
>     > +
>     > +        token = host_config.macaddress.substr(0, pos);
>     > +        resp_byte = strtoul(token.c_str(), NULL, 16);
> 
>     Would be a good idea to check strtoul for errors
> 
>     > +        memcpy((void*)&respData[index], &resp_byte, 1);
> 
>     Don't need to cast to (void*)
> 
>     > +        host_config.macaddress.erase(0, pos + delimiter.length());
>     > +        index++;
>     > +    }
>     > +
>     > +    resp_byte = strtoul(host_config.macaddress.c_str(), NULL, 16);
>     > +    memcpy((void*)&respData[index++], &resp_byte, 1);
> 
>     Same
> 
>     > +
>     > +    //Conevrt the dhcp,ipaddress,mask and gateway as hex number
> 
>     Typo, Conevrt/Convert
> 
>     > +    respData[index++]=0x00;
>     > +    sscanf(host_config.isDHCP.c_str(),"%02X",&respData[index++]);
>     > +
>     > +    inet_pton(AF_INET,host_config.ipaddress.c_str(),(void *)&respData
>     [index]);
>     > +    index+=4;
>     > +
>     > +    sscanf(host_config.prefix.c_str(),"%02d",&respData[index++]);
>     > +    inet_pton(AF_INET,host_config.gateway.c_str(),(void *)&respData
>     [index]);
>     > +    index+=4;
>     > +    
>     > +    printf ("\n===Printing the IPMI Formatted Data========\n");
> 
>     As above, debug message?
> 
>     > +
>     > +    for (int j = 0;j<index;j++)
> 
>     Spacing it out like this is easier to read:
> 
>         for (int j = 0; j < index; j++)
> 
>     > +        printf("%02x ", respData[j]);
>     > +
>     > +    memcpy(respptr->data,respData.data(),SIZE_BOOT_OPTION);
>     > +    return 0;
>     > +}
>     > +
>     > +uint8_t setHostNetworkData(set_sys_boot_options_t * reqptr)
>     > +{
>     > +    string host_network_config;
>     > +    char mac[SIZE_MAC] = {0};
>     > +    char ipAddress[INET_ADDRSTRLEN] = {0};
>     > +    char gateway[INET_ADDRSTRLEN] = {0};
>     > +    char dhcp[SIZE_PREFIX] = {0};
>     > +    char prefix[SIZE_PREFIX] = {0};
>     > +    uint32_t cookie = 0;
>     > +
>     > +    memcpy(&cookie,(char *)&(reqptr->data[1]),sizeof(cookie));
>     > +    
>     > +    uint8_t index = 9;  
>     > +
>     > +    if ( cookie) {
>     > +    
>     > +            snprintf(mac, SIZE_MAC, "%02x:%02x:%02x:%02x:%02x:%02x",
>     > +            reqptr->data[index],
>     > +            reqptr->data[index+1],
>     > +            reqptr->data[index+2],
>     > +            reqptr->data[index+3],
>     > +            reqptr->data[index+4],
>     > +            reqptr->data[index+5]);
>     > +    
>     > +        snprintf(dhcp,SIZE_PREFIX, "%d", reqptr->data[index+7]);
> 
>     *If* this is following the format used by Petitboot, is the order of
>     fields here correct? It looks like the size fields have been skipped.
> 
>     > +
>     > +        snprintf(ipAddress, INET_ADDRSTRLEN, "%d.%d.%d.%d",
>     > +            reqptr->data[index+8], reqptr->data[index+9], reqptr->data
>     [index+10], reqptr->data[index+11]);
>     > +
>     > +        snprintf(prefix,SIZE_PREFIX,"%d", reqptr->data[index+12]);
> 
>     What is the prefix? Is it meant to be the subnet mask?
> 
>     > +
>     > +        snprintf(gateway, INET_ADDRSTRLEN, "%d.%d.%d.%d",
>     > +            reqptr->data[index+13], reqptr->data[index+14], reqptr->data
>     [index+15], reqptr->data[index+16]);
>     > +    }
>     > +
>     > +    host_network_config += "ipaddress="+string(ipAddress)+",prefix="+ \
>     > +                       string(prefix)+",gateway="+string(gateway)+\
>     > +                       ",mac="+string(mac)+",dhcp="+string(dhcp);
>     > +
>     > +    printf ("Network configuration changed: %s\
>     n",host_network_config.c_str());
>     > +
>     > +    int r = dbus_set_property("network_config",host_network_config.c_str
>     ());
>     > +
>     > +    if (r < 0) {
>     > +        fprintf(stderr, "Dbus set property(network_config) failed for
>     set_sys_boot_options.\n");
>     > +        r = IPMI_CC_UNSPECIFIED_ERROR;
>     > +    }
>     > +    return r;
>     > +}
>     > +
>     >  ipmi_ret_t ipmi_chassis_wildcard(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
>     >                                ipmi_request_t request, ipmi_response_t
>     response,
>     >                                ipmi_data_len_t data_len, ipmi_context_t
>     context)
>     > @@ -446,7 +614,18 @@ ipmi_ret_t ipmi_chassis_get_sys_boot_options
>     (ipmi_netfn_t netfn, ipmi_cmd_t cmd,
>     >          }
>     >  
>     >  
>     > -    } else {
>     > +    } else if ( reqptr->parameter == 0x61 ) {
>     > +       resp->parm      = 0x61;
>     > +       int ret = getHostNetworkData(resp);
>     > +       if (ret < 0) {
>     > +           fprintf(stderr, "getHostNetworkData failed for
>     get_sys_boot_options.\n");
>     > +           rc = IPMI_CC_UNSPECIFIED_ERROR;
>     > +
>     > +       }else
>     > +          rc = IPMI_CC_OK;
>     > +    }
>     > +
>     > +    else {
>     >          fprintf(stderr, "Unsupported parameter 0x%x\n", reqptr->
>     parameter);
>     >      }
>     >  
>     > @@ -464,11 +643,10 @@ ipmi_ret_t ipmi_chassis_set_sys_boot_options
>     (ipmi_netfn_t netfn, ipmi_cmd_t cmd,
>     >  {
>     >      ipmi_ret_t rc = IPMI_CC_OK;
>     >      char *s;
>     > -
>     > -    printf("IPMI SET_SYS_BOOT_OPTIONS\n");
>     > -
>     >      set_sys_boot_options_t *reqptr = (set_sys_boot_options_t *) request;
>     >  
>     > +    printf("IPMI SET_SYS_BOOT_OPTIONS reqptr->parameter =[%d]\
>     n",reqptr->parameter);
>     > +
>     >      // This IPMI command does not have any resposne data
>     >      *data_len = 0;
>     >  
>     > @@ -476,6 +654,7 @@ ipmi_ret_t ipmi_chassis_set_sys_boot_options
>     (ipmi_netfn_t netfn, ipmi_cmd_t cmd,
>     >       * Parameter #5 means boot flags. Please refer to 28.13 of ipmi doc.
>     >       * This is the only parameter used by petitboot.
>     >       */
>     > +
> 
>     Extra line
> 
>     >      if (reqptr->parameter == 5) {
>     >  
>     >          s = get_boot_option_by_ipmi(((reqptr->data[1] & 0x3C) >> 2));
>     > @@ -507,7 +686,16 @@ ipmi_ret_t ipmi_chassis_set_sys_boot_options
>     (ipmi_netfn_t netfn, ipmi_cmd_t cmd,
>     >              rc = IPMI_CC_UNSPECIFIED_ERROR;
>     >          }
>     >  
>     > -    } else {
>     > +    }
>     > +    else if ( reqptr->parameter == 0x61 ) {
>     > +       printf("IPMI SET_SYS_BOOT_OPTIONS reqptr->parameter =[%d]\
>     n",reqptr->parameter);
>     > +       int ret = setHostNetworkData(reqptr);
>     > +       if (ret < 0) {
>     > +           fprintf(stderr, "setHostNetworkData failed for
>     set_sys_boot_options.\n");
>     > +           rc = IPMI_CC_UNSPECIFIED_ERROR;
>     > +       }
>     > +    }      
>     > +    else {
>     >          fprintf(stderr, "Unsupported parameter 0x%x\n", reqptr->
>     parameter);
>     >          rc = IPMI_CC_PARM_NOT_SUPPORTED;
>     >      }
>     > --
>     > 2.8.4
>     >
>     >
>     > _______________________________________________
>     > openbmc mailing list
>     > openbmc@lists.ozlabs.org
>     > https://lists.ozlabs.org/listinfo/openbmc
> 
>  
> 

> _______________________________________________
> openbmc mailing list
> openbmc@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/openbmc

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2016-06-20  0:25 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-06-16 14:50 [PATCH phosphor-host-ipmid v5] Implement Network Override OpenBMC Patches
2016-06-16 14:50 ` [PATCH phosphor-host-ipmid v5] Resolves openbmc/openbmc#267' OpenBMC Patches
2016-06-17  5:47   ` Samuel Mendoza-Jonas
2016-06-17 11:48     ` Ratan K Gupta
2016-06-20  0:25       ` Samuel Mendoza-Jonas

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.