[PATCH phosphor-host-ipmid v3] Implement Network Override

OpenBMC Patches openbmc-patches at stwcx.xyz
Fri Jun 10 22:10:40 AEST 2016


From: ratagupt <ratagupt at 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.3




More information about the openbmc mailing list