[PATCH phosphor-host-ipmid] IPMI support for get and set lan

OpenBMC Patches patches at stwcx.xyz
Fri Oct 30 14:15:33 AEDT 2015


From: Adriana Kobylak <anoo at us.ibm.com>

Add enough support to query common network parameters
and be able to setup the network vi IPMI.
Use command line for now.
---
 Makefile           |   1 +
 ipmid-api.h        |  20 +++---
 transporthandler.C | 202 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 transporthandler.h |  18 +++++
 4 files changed, 231 insertions(+), 10 deletions(-)
 create mode 100644 transporthandler.C
 create mode 100644 transporthandler.h

diff --git a/Makefile b/Makefile
index a91328e..97c45e6 100644
--- a/Makefile
+++ b/Makefile
@@ -14,6 +14,7 @@ LIB_APP_OBJ = apphandler.o     \
               dcmihandler.o    \
               ipmisensor.o     \
               storageaddsel.o  \
+              transporthandler.o  \
 
 
 TESTADDSEL_OBJ = $(TESTADDSEL).o \
diff --git a/ipmid-api.h b/ipmid-api.h
index a78846c..b3117d5 100644
--- a/ipmid-api.h
+++ b/ipmid-api.h
@@ -62,16 +62,16 @@ extern "C" void ipmi_register_callback(ipmi_netfn_t, ipmi_cmd_t,
 // Note: these are also shifted left to make room for the LUN.
 enum ipmi_net_fns
 {
-    NETFUN_CHASSIS  =   0x00,
-    NETFUN_BRIDGE   =   0x02,
-    NETFUN_SENSOR   =   0x04,
-    NETFUN_APP      =   0x06,
-    NETFUN_FIRMWARE =   0x08,
-    NETFUN_STORAGE  =   0x0a,
-    NETFUN_TRANPORT =   0x0c,
-    NETFUN_GRPEXT   =   0x2c,
-    NETFUN_NONE     =   0x30,
-    NETFUN_OEM      =   0x32
+    NETFUN_CHASSIS   =   0x00,
+    NETFUN_BRIDGE    =   0x02,
+    NETFUN_SENSOR    =   0x04,
+    NETFUN_APP       =   0x06,
+    NETFUN_FIRMWARE  =   0x08,
+    NETFUN_STORAGE   =   0x0a,
+    NETFUN_TRANSPORT =   0x0c,
+    NETFUN_GRPEXT    =   0x2c,
+    NETFUN_NONE      =   0x30,
+    NETFUN_OEM       =   0x32
 };
 
 // IPMI commands for net functions. Since this is to be used both by the ipmi
diff --git a/transporthandler.C b/transporthandler.C
new file mode 100644
index 0000000..997f681
--- /dev/null
+++ b/transporthandler.C
@@ -0,0 +1,202 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "ipmid-api.h"
+#include "ipmid.H"
+#include "transporthandler.h"
+
+void register_netfn_transport_functions() __attribute__((constructor));
+
+ipmi_ret_t ipmi_transport_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)
+{
+    printf("Handling TRANSPORT WILDCARD Netfn:[0x%X], Cmd:[0x%X]\n",netfn, cmd);
+    // Status code.
+    ipmi_ret_t rc = IPMI_CC_OK;
+    *data_len = 0;
+    return rc;
+}
+
+struct set_lan_t {
+    uint8_t channel;
+    uint8_t parameter;
+    uint8_t data[8]; // Per IPMI spec, not expecting more than this size
+}  __attribute__ ((packed));
+
+ipmi_ret_t ipmi_transport_set_lan(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)
+{
+    ipmi_ret_t rc = IPMI_CC_OK;
+    *data_len = 0;
+
+    int i = 0;
+    char syscmd[128];
+
+    printf("IPMI SET_LAN\n");
+
+    set_lan_t *reqptr = (set_lan_t*) request;
+
+    // TODO Use dbus interface once available. For now use cmd line.
+    // TODO Add the rest of the parameters like setting auth type
+    // TODO Add error handling
+
+    if (reqptr->parameter == 3) // IP
+    {
+        sprintf(syscmd, "ifconfig eth0 %d.%d.%d.%d", reqptr->data[0], reqptr->data[1], reqptr->data[2], reqptr->data[3]);
+        system(syscmd);
+    }
+    else if (reqptr->parameter == 6) // Subnet
+    {
+        sprintf(syscmd, "ifconfig eth0 netmask %d.%d.%d.%d", reqptr->data[0], reqptr->data[1], reqptr->data[2], reqptr->data[3]);
+        system(syscmd);
+    }
+    else if (reqptr->parameter == 12) // Gateway
+    {
+        sprintf(syscmd, "route add default gw %d.%d.%d.%d", reqptr->data[0], reqptr->data[1], reqptr->data[2], reqptr->data[3]);
+        system(syscmd);
+    }
+    else
+    {
+        fprintf(stderr, "Unsupported parameter 0x%x\n", reqptr->parameter);
+        return IPMI_CC_PARM_NOT_SUPPORTED;
+    }
+
+    return rc;
+}
+
+struct get_lan_t {
+    uint8_t rev_channel;
+    uint8_t parameter;
+    uint8_t parameter_set;
+    uint8_t parameter_block;
+}  __attribute__ ((packed));
+
+ipmi_ret_t ipmi_transport_get_lan(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)
+{
+    ipmi_ret_t rc = IPMI_CC_OK;
+    *data_len = 0;
+
+    const uint32_t current_revision = 0x11; // Current rev per IPMI Spec 2.0
+    char syscmd[128];
+    int revision = 0;
+    int i = 0;
+
+    printf("IPMI GET_LAN\n");
+
+    get_lan_t *reqptr = (get_lan_t*) request;
+
+    revision = reqptr->rev_channel >> 8; // Revision is bit 7
+    if (revision == 1)
+    {
+        // Only current revision was requested
+        *data_len = sizeof(current_revision);
+        memcpy(response, &current_revision, *data_len);
+        return IPMI_CC_OK;
+    }
+
+    // TODO Use dbus interface once available. For now use ip cmd.
+    // TODO Add the rest of the parameters, like gateway
+
+    if (reqptr->parameter == 0) // In progress
+    {
+        uint8_t buf[] = {current_revision,0};
+        *data_len = sizeof(buf);
+        memcpy(response, &buf, *data_len);
+        return IPMI_CC_OK;
+    }
+    else if (reqptr->parameter == 1) // Authentication support
+    {
+        uint8_t buf[] = {current_revision,0x04};
+        *data_len = sizeof(buf);
+        memcpy(response, &buf, *data_len);
+        return IPMI_CC_OK;
+    }
+    else if (reqptr->parameter == 2) // Authentication enables
+    {
+        uint8_t buf[] = {current_revision,0x04,0x04,0x04,0x04,0x04};
+        *data_len = sizeof(buf);
+        memcpy(response, &buf, *data_len);
+        return IPMI_CC_OK;
+    }
+    else if (reqptr->parameter == 3) // IP
+    {
+        //string to parse: inet xx.xx.xxx.xxx/xx
+
+        uint8_t buf[5];
+        memcpy((void*)&buf[0], &current_revision, 1);
+
+        for (i=0; i<4; i++)
+        {
+            char ip[5];
+
+            sprintf(syscmd, "ip address show dev eth0|grep inet|cut -d'/' -f1|cut -d' ' -f 6|cut -d'.' -f%d|head -n1", i+1);
+            FILE *fp = popen(syscmd, "r");
+
+            memset(ip,0,sizeof(ip));
+            while (fgets(ip, sizeof(ip), fp) != 0)
+            {
+                int tmpip = strtoul(ip, NULL, 10);
+                memcpy((void*)&buf[i+1], &tmpip, 1);
+            }
+            pclose(fp);
+        }
+
+        *data_len = sizeof(buf);
+        memcpy(response, &buf, *data_len);
+        return IPMI_CC_OK;
+    }
+    else if (reqptr->parameter == 5) // MAC
+    {
+        //string to parse: link/ether xx:xx:xx:xx:xx:xx
+
+        uint8_t buf[7];
+        memcpy((void*)&buf[0], &current_revision, 1);
+
+        for (i=0; i<6; i++)
+        {
+            char mac[4];
+
+            sprintf(syscmd, "ip address show dev eth0|grep link|cut -d' ' -f 6|cut -d':' -f%d", i+1);
+            FILE *fp = popen(syscmd, "r");
+
+            memset(mac,0,sizeof(mac));
+            while (fgets(mac, sizeof(mac), fp) != 0)
+            {
+                int tmpmac = strtoul(mac, NULL, 16);
+                memcpy((void*)&buf[i+1], &tmpmac, 1);
+            }
+            pclose(fp);
+        }
+
+        *data_len = sizeof(buf);
+        memcpy(response, &buf, *data_len);
+        return IPMI_CC_OK;
+    }
+    else
+    {
+        fprintf(stderr, "Unsupported parameter 0x%x\n", reqptr->parameter);
+        return IPMI_CC_PARM_NOT_SUPPORTED;
+    }
+
+    return rc;
+}
+
+void register_netfn_transport_functions()
+{
+    printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_TRANSPORT, IPMI_CMD_WILDCARD);
+    ipmi_register_callback(NETFUN_TRANSPORT, IPMI_CMD_WILDCARD, NULL, ipmi_transport_wildcard);
+
+    printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_TRANSPORT, IPMI_CMD_SET_LAN);
+    ipmi_register_callback(NETFUN_TRANSPORT, IPMI_CMD_SET_LAN, NULL, ipmi_transport_set_lan);
+
+    printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_TRANSPORT, IPMI_CMD_GET_LAN);
+    ipmi_register_callback(NETFUN_TRANSPORT, IPMI_CMD_GET_LAN, NULL, ipmi_transport_get_lan);
+
+    return;
+}
+
diff --git a/transporthandler.h b/transporthandler.h
new file mode 100644
index 0000000..49b1d95
--- /dev/null
+++ b/transporthandler.h
@@ -0,0 +1,18 @@
+#ifndef __HOST_IPMI_TRANSPORT_HANDLER_H__
+#define __HOST_IPMI_TRANSPORT_HANDLER_H__
+
+// IPMI commands for Transport net functions.
+enum ipmi_netfn_storage_cmds
+{
+    // Get capability bits
+    IPMI_CMD_SET_LAN = 0x01,
+    IPMI_CMD_GET_LAN = 0x02,
+};
+
+// Command specific completion codes
+enum ipmi_transport_return_codes
+{
+    IPMI_CC_PARM_NOT_SUPPORTED = 0x80,
+};
+
+#endif
-- 
2.6.0




More information about the openbmc mailing list