summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNan Li <william.bjlinan@hotmail.com>2016-10-18 19:51:41 +0800
committerPatrick Williams <patrick@stwcx.xyz>2016-11-23 14:03:55 +0000
commit3d0df91dc704fbcfa819ba42cccfa6a2f1616ff9 (patch)
tree66b66f65aab5c26c29e89ed6b8afd0937473bb64
parent41fa24a108cc3f1e6ecc1fb9cce6cf1d9c5a5764 (diff)
downloadphosphor-host-ipmid-3d0df91dc704fbcfa819ba42cccfa6a2f1616ff9.tar.gz
phosphor-host-ipmid-3d0df91dc704fbcfa819ba42cccfa6a2f1616ff9.zip
Add transaction support to Set Lan Cmd and Set Channel Access Cmd
* Ipmid will cache single setting to memory by Set Lan cmd * Add Set Channel Access cmd to ipmid * Set Channel Access cmd is used to apply the previous cached settings TODO: parse the request data of Set Channel Access cmd if needed. Resolves openbmc/openbmc#444 Change-Id: Ia7ac57a551731920ffe69dad5c69c995521fed02 Signed-off-by: Nan Li <william.bjlinan@hotmail.com>
-rw-r--r--apphandler.cpp121
-rw-r--r--apphandler.h1
-rw-r--r--transporthandler.cpp111
-rw-r--r--transporthandler.h6
4 files changed, 171 insertions, 68 deletions
diff --git a/apphandler.cpp b/apphandler.cpp
index 9d94b1b..431cbf0 100644
--- a/apphandler.cpp
+++ b/apphandler.cpp
@@ -7,9 +7,15 @@
#include <systemd/sd-bus.h>
#include <mapper.h>
#include <array>
+#include <arpa/inet.h>
+#include "transporthandler.h"
extern sd_bus *bus;
+constexpr auto app_obj = "/org/openbmc/NetworkManager/Interface";
+constexpr auto app_ifc = "org.openbmc.NetworkManager";
+constexpr auto app_nwinterface = "eth0";
+
void register_netfn_app_functions() __attribute__((constructor));
// Offset in get device id command.
@@ -535,6 +541,117 @@ finish:
return rc;
}
+extern struct channel_config_t channel_config;
+
+ipmi_ret_t ipmi_set_channel_access(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;
+
+ sd_bus *bus = ipmid_get_sd_bus_connection();
+ sd_bus_message *reply = nullptr;
+ sd_bus_error error = SD_BUS_ERROR_NULL;
+ int r = 0;
+ char *app = nullptr;
+ int family = 0;
+ unsigned char prefixlen = 0;
+ char* ipaddr = nullptr;
+ uint32_t mask = 0xFFFFFFFF;
+ char* gateway = nullptr;
+ char tmp_netmask[INET_ADDRSTRLEN];
+
+ // Todo: parse the request data if needed.
+
+ // Using Set Channel cmd to apply changes of Set Lan Cmd.
+
+ r = mapper_get_service(bus, app_obj, &app);
+ if (r < 0) {
+ fprintf(stderr, "Failed to get %s bus name: %s\n",
+ app_obj, strerror(-r));
+ rc = IPMI_CC_UNSPECIFIED_ERROR;
+ goto finish;
+ }
+
+ r = sd_bus_call_method(bus, app, app_obj, app_ifc, "GetAddress4", &error,
+ &reply, "s", app_nwinterface);
+ if (r < 0) {
+ fprintf(stderr, "Failed to call Get Method: %s\n", strerror(-r));
+ rc = IPMI_CC_UNSPECIFIED_ERROR;
+ goto finish;
+ }
+
+ r = sd_bus_message_read(reply, "iyss",
+ &family, &prefixlen, &ipaddr, &gateway);
+ if (r < 0) {
+ fprintf(stderr, "Failed to get a response: %s\n", strerror(-r));
+ rc = IPMI_CC_RESPONSE_ERROR;
+ goto finish;
+ }
+
+ printf("N/W data from Cache: %s:%s:%s\n",
+ channel_config.new_ipaddr.c_str(),
+ channel_config.new_netmask.c_str(),
+ channel_config.new_gateway.c_str());
+
+ if(channel_config.new_ipaddr.empty()) {
+ channel_config.new_ipaddr.assign(ipaddr);
+ }
+
+ if(channel_config.new_netmask.empty()) {
+ mask = htonl(mask<<(32-prefixlen));
+ uint8_t* p = (uint8_t*)&mask;
+
+ snprintf(tmp_netmask, INET_ADDRSTRLEN, "%d.%d.%d.%d",
+ *p, *(p+1), *(p+2), *(p+3));
+ channel_config.new_netmask.assign(tmp_netmask);
+ }
+
+ if(channel_config.new_gateway.empty()) {
+ channel_config.new_gateway.assign(gateway);
+ }
+
+ printf("N/W data from HW %s:%d:%s:%s\n",
+ family==AF_INET?"IPv4":"IPv6", prefixlen, ipaddr,gateway);
+ printf("N/W data from Cache: %s:%s:%s\n",
+ channel_config.new_ipaddr.c_str(),
+ channel_config.new_netmask.c_str(),
+ channel_config.new_gateway.c_str());
+
+ r = sd_bus_call_method(bus, // On the System Bus
+ app, // Service to contact
+ app_obj, // Object path
+ app_ifc, // Interface name
+ "SetAddress4", // Method to be called
+ &error, // object to return error
+ &reply, // Response message on success
+ "ssss", // input message (Interface,
+ // IP Address, Netmask, Gateway)
+ app_nwinterface, // eth0
+ channel_config.new_ipaddr.c_str(),
+ channel_config.new_netmask.c_str(),
+ channel_config.new_gateway.c_str());
+ if(r < 0) {
+ fprintf(stderr, "Failed to set network data %s:%s:%s %s\n",
+ channel_config.new_ipaddr.c_str(),
+ channel_config.new_netmask.c_str(),
+ channel_config.new_gateway.c_str(),
+ error.message);
+ rc = IPMI_CC_UNSPECIFIED_ERROR;
+ }
+
+ channel_config.new_ipaddr.clear();
+ channel_config.new_netmask.clear();
+ channel_config.new_gateway.clear();
+
+finish:
+ sd_bus_error_free(&error);
+ reply = sd_bus_message_unref(reply);
+ free(app);
+
+ return rc;
+}
+
// ATTENTION: This ipmi function is very hardcoded on purpose
// OpenBMC does not fully support IPMI. This command is useful
// to have around because it enables testing of interfaces with
@@ -644,6 +761,10 @@ void register_netfn_app_functions()
printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_APP, IPMI_CMD_GET_MSG_FLAGS);
ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_MSG_FLAGS, NULL, ipmi_app_get_msg_flags);
+ printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_APP,
+ IPMI_CMD_SET_CHAN_ACCESS);
+ ipmi_register_callback(NETFUN_APP, IPMI_CMD_SET_CHAN_ACCESS, NULL,
+ ipmi_set_channel_access);
printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_APP, IPMI_CMD_GET_CHAN_INFO);
ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_CHAN_INFO, NULL, ipmi_app_channel_info);
diff --git a/apphandler.h b/apphandler.h
index f59e315..5753c27 100644
--- a/apphandler.h
+++ b/apphandler.h
@@ -28,6 +28,7 @@ enum ipmi_netfn_app_cmds
IPMI_CMD_GET_MSG_FLAGS = 0x31,
IPMI_CMD_READ_EVENT = 0x35,
IPMI_CMD_GET_CAP_BIT = 0x36,
+ IPMI_CMD_SET_CHAN_ACCESS = 0x40,
IPMI_CMD_GET_CHAN_INFO = 0x42,
};
diff --git a/transporthandler.cpp b/transporthandler.cpp
index 32ed993..8ee2dbe 100644
--- a/transporthandler.cpp
+++ b/transporthandler.cpp
@@ -23,9 +23,7 @@ const char *nwinterface = "eth0";
const int SIZE_MAC = 18; //xx:xx:xx:xx:xx:xx
-char new_ipaddr [INET_ADDRSTRLEN] = "";
-char new_netmask [INET_ADDRSTRLEN] = "";
-char new_gateway [INET_ADDRSTRLEN] = "";
+struct channel_config_t channel_config;
const uint8_t SET_COMPLETE = 0;
const uint8_t SET_IN_PROGRESS = 1;
@@ -39,8 +37,8 @@ uint8_t lan_set_in_progress = SET_COMPLETE;
void register_netfn_transport_functions() __attribute__((constructor));
-// Helper Function to get IP Address/NetMask/Gateway from Network Manager or Cache
-// based on Set-In-Progress State
+// Helper Function to get IP Address/NetMask/Gateway from Network Manager or
+// Cache based on Set-In-Progress State
ipmi_ret_t getNetworkData(uint8_t lan_param, uint8_t * data)
{
sd_bus *bus = ipmid_get_sd_bus_connection();
@@ -59,6 +57,7 @@ ipmi_ret_t getNetworkData(uint8_t lan_param, uint8_t * data)
if (r < 0) {
fprintf(stderr, "Failed to get %s bus name: %s\n",
obj, strerror(-r));
+ rc = IPMI_CC_UNSPECIFIED_ERROR;
goto cleanup;
}
r = sd_bus_call_method(bus, app, obj, ifc, "GetAddress4", &error,
@@ -70,7 +69,8 @@ ipmi_ret_t getNetworkData(uint8_t lan_param, uint8_t * data)
goto cleanup;
}
- r = sd_bus_message_read(reply, "iyss", &family, &prefixlen, &ipaddr, &gateway);
+ r = sd_bus_message_read(reply, "iyss",
+ &family, &prefixlen, &ipaddr, &gateway);
if(r < 0)
{
fprintf(stderr, "Failed to get a response: %s\n", strerror(-rc));
@@ -78,8 +78,12 @@ ipmi_ret_t getNetworkData(uint8_t lan_param, uint8_t * data)
goto cleanup;
}
- printf("N/W data from HW %s:%d:%s:%s\n", family==AF_INET?"IPv4":"IPv6", prefixlen, ipaddr,gateway);
- printf("N/W data from Cache: %s:%s:%s\n", new_ipaddr, new_netmask, new_gateway);
+ printf("N/W data from HW %s:%d:%s:%s\n",
+ family==AF_INET?"IPv4":"IPv6", prefixlen, ipaddr,gateway);
+ printf("N/W data from Cache: %s:%s:%s\n",
+ channel_config.new_ipaddr.c_str(),
+ channel_config.new_netmask.c_str(),
+ channel_config.new_gateway.c_str());
if(lan_param == LAN_PARM_IP)
{
@@ -90,7 +94,7 @@ ipmi_ret_t getNetworkData(uint8_t lan_param, uint8_t * data)
}
else if(lan_set_in_progress == SET_IN_PROGRESS)
{
- inet_pton(AF_INET, new_ipaddr, (void *)data);
+ inet_pton(AF_INET, channel_config.new_ipaddr.c_str(), (void *)data);
}
}
else if(lan_param == LAN_PARM_SUBNET)
@@ -102,7 +106,7 @@ ipmi_ret_t getNetworkData(uint8_t lan_param, uint8_t * data)
}
else if(lan_set_in_progress == SET_IN_PROGRESS)
{
- inet_pton(AF_INET, new_netmask, (void *)data);
+ inet_pton(AF_INET, channel_config.new_netmask.c_str(), (void *)data);
}
}
else if(lan_param == LAN_PARM_GATEWAY)
@@ -114,7 +118,7 @@ ipmi_ret_t getNetworkData(uint8_t lan_param, uint8_t * data)
}
else if(lan_set_in_progress == SET_IN_PROGRESS)
{
- inet_pton(AF_INET, new_gateway,(void *)data);
+ inet_pton(AF_INET, channel_config.new_gateway.c_str(),(void *)data);
}
}
else
@@ -154,26 +158,24 @@ ipmi_ret_t ipmi_transport_set_lan(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
ipmi_ret_t rc = IPMI_CC_OK;
*data_len = 0;
sd_bus *bus = ipmid_get_sd_bus_connection();
- sd_bus_message *reply = NULL;
+ sd_bus_message *reply = nullptr;
sd_bus_error error = SD_BUS_ERROR_NULL;
int r = 0;
- char *app = NULL;
+ char *app = nullptr;
+
+ char tmp_ipaddr[INET_ADDRSTRLEN];
+ char tmp_netmask[INET_ADDRSTRLEN];
+ char tmp_gateway[INET_ADDRSTRLEN];
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 == LAN_PARM_IP)
- {
- snprintf(new_ipaddr, INET_ADDRSTRLEN, "%d.%d.%d.%d",
+ if (reqptr->parameter == LAN_PARM_IP) {
+ snprintf(tmp_ipaddr, INET_ADDRSTRLEN, "%d.%d.%d.%d",
reqptr->data[0], reqptr->data[1], reqptr->data[2], reqptr->data[3]);
- }
- else if (reqptr->parameter == LAN_PARM_MAC)
- {
+ channel_config.new_ipaddr.assign(tmp_ipaddr);
+ } else if (reqptr->parameter == LAN_PARM_MAC) {
char mac[SIZE_MAC];
snprintf(mac, SIZE_MAC, "%02x:%02x:%02x:%02x:%02x:%02x",
@@ -192,63 +194,36 @@ ipmi_ret_t ipmi_transport_set_lan(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
}
r = sd_bus_call_method(bus, app, obj, ifc, "SetHwAddress", &error,
&reply, "ss", nwinterface, mac);
- if(r < 0)
- {
+ if (r < 0) {
fprintf(stderr, "Failed to call the method: %s\n", strerror(-r));
rc = IPMI_CC_UNSPECIFIED_ERROR;
}
- }
- else if (reqptr->parameter == LAN_PARM_SUBNET)
+ } else if (reqptr->parameter == LAN_PARM_SUBNET)
{
- snprintf(new_netmask, INET_ADDRSTRLEN, "%d.%d.%d.%d",
+ snprintf(tmp_netmask, INET_ADDRSTRLEN, "%d.%d.%d.%d",
reqptr->data[0], reqptr->data[1], reqptr->data[2], reqptr->data[3]);
- }
- else if (reqptr->parameter == LAN_PARM_GATEWAY)
+ channel_config.new_netmask.assign(tmp_netmask);
+ } else if (reqptr->parameter == LAN_PARM_GATEWAY)
{
- snprintf(new_gateway, INET_ADDRSTRLEN, "%d.%d.%d.%d",
+ snprintf(tmp_gateway, INET_ADDRSTRLEN, "%d.%d.%d.%d",
reqptr->data[0], reqptr->data[1], reqptr->data[2], reqptr->data[3]);
- }
- else if (reqptr->parameter == LAN_PARM_INPROGRESS)
+ channel_config.new_gateway.assign(tmp_gateway);
+ } else if (reqptr->parameter == LAN_PARM_INPROGRESS)
{
- if(reqptr->data[0] == SET_COMPLETE) // Set Complete
- {
+ if(reqptr->data[0] == SET_COMPLETE) {
lan_set_in_progress = SET_COMPLETE;
- // Apply the IP settings once IP Address, Netmask and Gateway is set
- if (!strcmp(new_ipaddr, "") || !strcmp (new_netmask, "") || !strcmp (new_gateway, ""))
- {
- printf("ERROR: Incomplete LAN Parameters\n");
- }
- else
- {
-
- r = sd_bus_call_method(bus, // On the System Bus
- app, // Service to contact
- obj, // Object path
- ifc, // Interface name
- "SetAddress4", // Method to be called
- &error, // object to return error
- &reply, // Response message on success
- "ssss", // input message (Interface, IP Address, Netmask, Gateway)
- nwinterface, // eth0
- new_ipaddr,
- new_netmask,
- new_gateway);
- if(r < 0)
- {
- fprintf(stderr, "Failed to set network data %s:%s:%s %s\n", new_ipaddr, new_netmask, new_gateway, error.message);
- rc = IPMI_CC_UNSPECIFIED_ERROR;
- }
- memset(new_ipaddr, 0, INET_ADDRSTRLEN);
- memset(new_netmask, 0, INET_ADDRSTRLEN);
- memset(new_gateway, 0, INET_ADDRSTRLEN);
- }
- }
- else if(reqptr->data[0] == SET_IN_PROGRESS) // Set In Progress
+
+ printf("N/W data from Cache: %s:%s:%s\n",
+ channel_config.new_ipaddr.c_str(),
+ channel_config.new_netmask.c_str(),
+ channel_config.new_gateway.c_str());
+ printf("Use Set Channel Access command to apply them\n");
+
+ } else if(reqptr->data[0] == SET_IN_PROGRESS) // Set In Progress
{
lan_set_in_progress = SET_IN_PROGRESS;
}
- }
- else
+ } else
{
fprintf(stderr, "Unsupported parameter 0x%x\n", reqptr->parameter);
rc = IPMI_CC_PARM_NOT_SUPPORTED;
diff --git a/transporthandler.h b/transporthandler.h
index ce7842b..171a636 100644
--- a/transporthandler.h
+++ b/transporthandler.h
@@ -24,4 +24,10 @@ static const int LAN_PARM_MAC = 5;
static const int LAN_PARM_SUBNET = 6;
static const int LAN_PARM_GATEWAY = 12;
+struct channel_config_t {
+ std::string new_ipaddr;
+ std::string new_netmask;
+ std::string new_gateway;
+};
+
#endif
OpenPOWER on IntegriCloud