From: Jeremy Kerr Date: Mon, 21 Nov 2022 08:35:38 +0000 (+0800) Subject: MI: switch from libsdbus to libdbus X-Git-Tag: v1.3~22^2 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=e7ea8c143e9b501d2207271fb4e9e2046a84a9c5;p=users%2Fsagi%2Flibnvme.git MI: switch from libsdbus to libdbus libsystemd is not generally available as a static library, and we would like to produce a static nvme-cli. This change switches to libdbus instead. This requires slightly more boilerplate code for the dbus marshalling/unmarshalling as part of the MCTP endpoint scan, but means we have a simpler upstream lib dependency. Fixes: https://github.com/linux-nvme/nvme-cli/issues/1734 Signed-off-by: Jeremy Kerr --- diff --git a/examples/meson.build b/examples/meson.build index 31d05d71..3139311a 100644 --- a/examples/meson.build +++ b/examples/meson.build @@ -40,11 +40,11 @@ executable( include_directories: [incdir, internal_incdir] ) -if libsystemd_dep.found() +if libdbus_dep.found() executable( 'mi-conf', ['mi-conf.c'], - dependencies: [libnvme_mi_dep, libsystemd_dep], + dependencies: [libnvme_mi_dep, libdbus_dep], include_directories: [incdir, internal_incdir] ) endif diff --git a/examples/mi-conf.c b/examples/mi-conf.c index 90d590ea..4fdd4055 100644 --- a/examples/mi-conf.c +++ b/examples/mi-conf.c @@ -23,7 +23,7 @@ #include #include -#include +#include #define MCTP_DBUS_NAME "xyz.openbmc_project.MCTP" #define MCTP_DBUS_PATH "/xyz/openbmc_project/mctp" @@ -79,10 +79,11 @@ int find_port(nvme_mi_ep_t ep, uint8_t *portp, uint16_t *mtup) return found ? 0 : 1; } -int set_local_mtu(sd_bus *bus, unsigned int net, uint8_t eid, uint32_t mtu) +int set_local_mtu(DBusConnection *bus, unsigned int net, uint8_t eid, + uint32_t mtu) { - sd_bus_error err = SD_BUS_ERROR_NULL; - sd_bus_message *resp; + DBusMessage *msg, *resp; + DBusError berr; char *ep_path; int rc; @@ -99,26 +100,50 @@ int set_local_mtu(sd_bus *bus, unsigned int net, uint8_t eid, uint32_t mtu) */ mtu += 4; - rc = sd_bus_call_method(bus, MCTP_DBUS_NAME, ep_path, - MCTP_DBUS_EP_IFACE, "SetMTU", &err, &resp, - "u", mtu); - if (rc < 0) { - warnx("Failed to set local MTU: %s", strerror(-rc)); - return -1; + rc = -1; + dbus_error_init(&berr); + msg = dbus_message_new_method_call(MCTP_DBUS_NAME, ep_path, + MCTP_DBUS_EP_IFACE, "SetMTU"); + if (!msg) { + warnx("Can't create D-Bus message"); + goto out; } - return 0; + rc = dbus_message_append_args(msg, + DBUS_TYPE_UINT32, &mtu, + DBUS_TYPE_INVALID); + if (!rc) { + warnx("Can't construct D-Bus message arguments"); + goto out_free_msg; + } + + resp = dbus_connection_send_with_reply_and_block(bus, msg, + 2000, &berr); + if (!resp) { + warnx("Failed to set local MTU: %s (%s)", berr.message, + berr.name); + } else { + dbus_message_unref(resp); + rc = 0; + } + +out_free_msg: + dbus_message_unref(msg); +out: + dbus_error_free(&berr); + return rc; } int main(int argc, char **argv) { uint16_t cur_mtu, mtu; + DBusConnection *bus; const char *devstr; uint8_t eid, port; nvme_root_t root; unsigned int net; nvme_mi_ep_t ep; - sd_bus *bus; + DBusError berr; int rc; if (argc != 2) { @@ -141,10 +166,13 @@ int main(int argc, char **argv) goto out_free_root; } - rc = sd_bus_default_system(&bus); - if (rc < 0) { + dbus_error_init(&berr); + bus = dbus_bus_get(DBUS_BUS_SYSTEM, &berr); + if (!bus) { + warnx("Failed opening D-Bus: %s (%s)\n", + berr.message, berr.name); + rc = -1; goto out_close_ep; - warnx("Failed opening D-Bus: %s\n", strerror(-rc)); } rc = find_port(ep, &port, &mtu); @@ -185,8 +213,9 @@ int main(int argc, char **argv) } out_close_bus: - sd_bus_close(bus); + dbus_connection_unref(bus); out_close_ep: + dbus_error_free(&berr); nvme_mi_close(ep); out_free_root: nvme_mi_free_root(root); diff --git a/meson.build b/meson.build index c7b0c59a..674ef4b0 100644 --- a/meson.build +++ b/meson.build @@ -89,24 +89,9 @@ if openssl_dep.found() description: 'OpenSSL/LibreSSL API version @0@'.format(api_version)) endif -# Check for libsystemd availability. Optional, only required for MCTP dbus scan -libsystemd_dep = dependency('libsystemd', version: '>219', required: false) -if libsystemd_dep.found() - # When the user has CFLAGS=-static environment variable set - # dependency() will find the shared library libsystemd Thus double - # check if we are able to link - if not cc.links('''#include - int main(void) { - struct sd_bus *ret; - return sd_bus_default(&ret); - } - ''', - dependencies: libsystemd_dep, - name: 'libsystemd') - libsystemd_dep = declare_dependency() - endif - conf.set('CONFIG_LIBSYSTEMD', libsystemd_dep.found(), description: 'Is libsystemd(>219) available?') -endif +# Check for libdus availability. Optional, only required for MCTP dbus scan +libdbus_dep = dependency('dbus-1', required: false) +conf.set('CONFIG_DBUS', libdbus_dep.found(), description: 'Enable dbus support?') # local (cross-compilable) implementations of ccan configure steps conf.set10( diff --git a/src/meson.build b/src/meson.build index 9e49a077..1186e81f 100644 --- a/src/meson.build +++ b/src/meson.build @@ -33,7 +33,7 @@ deps = [ ] mi_deps = [ - libsystemd_dep, + libdbus_dep, ] source_dir = meson.current_source_dir() diff --git a/src/nvme/mi-mctp.c b/src/nvme/mi-mctp.c index b3239ccb..0c5972a5 100644 --- a/src/nvme/mi-mctp.c +++ b/src/nvme/mi-mctp.c @@ -23,10 +23,8 @@ #include -#ifdef CONFIG_LIBSYSTEMD -#include -#include -#include +#ifdef CONFIG_DBUS +#include #define MCTP_DBUS_PATH "/xyz/openbmc_project/mctp" #define MCTP_DBUS_IFACE "xyz.openbmc_project.MCTP" @@ -522,19 +520,7 @@ err_free_ep: return NULL; } -#ifdef CONFIG_LIBSYSTEMD - -/* helper for handling dbus errors: D-Bus API returns a negtive errno on - * failure; set errno and log. - */ -static void _dbus_err(nvme_root_t root, int rc, int line) -{ - nvme_msg(root, LOG_ERR, "MCTP D-Bus failed line %d: %s %d\n", - line, strerror(-rc), rc); - errno = -rc; -} - -#define dbus_err(r, rc) _dbus_err(r, rc, __LINE__) +#ifdef CONFIG_DBUS static int nvme_mi_mctp_add(nvme_root_t root, unsigned int netid, __u8 eid) { @@ -558,84 +544,99 @@ static int nvme_mi_mctp_add(nvme_root_t root, unsigned int netid, __u8 eid) return 0; } -/* We can't rely on sd_bus_message_enter_container() == 0 at the end of - a dictionary (it returns -ENXIO) so we test separately */ -static bool container_end(sd_bus_message *m) +static bool dbus_object_is_type(DBusMessageIter *obj, int type) +{ + return dbus_message_iter_get_arg_type(obj) == type; +} + +static bool dbus_object_is_dict(DBusMessageIter *obj) +{ + return dbus_object_is_type(obj, DBUS_TYPE_ARRAY) && + dbus_message_iter_get_element_type(obj) == DBUS_TYPE_DICT_ENTRY; +} + +static int read_variant_basic(DBusMessageIter *var, int type, void *val) { - return sd_bus_message_peek_type(m, NULL, NULL) == 0; + if (!dbus_object_is_type(var, type)) + return -1; + + dbus_message_iter_get_basic(var, val); + + return 0; +} + +static bool has_message_type(DBusMessageIter *prop, uint8_t type) +{ + DBusMessageIter inner; + uint8_t *types; + int i, n; + + if (!dbus_object_is_type(prop, DBUS_TYPE_ARRAY) || + dbus_message_iter_get_element_type(prop) != DBUS_TYPE_BYTE) + return false; + + dbus_message_iter_recurse(prop, &inner); + + dbus_message_iter_get_fixed_array(&inner, &types, &n); + + for (i = 0; i < n; i++) { + if (types[i] == type) + return true; + } + + return false; } static int handle_mctp_endpoint(nvme_root_t root, const char* objpath, - sd_bus_message *m) + DBusMessageIter *props) { bool have_eid = false, have_net = false, have_nvmemi = false; mctp_eid_t eid; int net; int rc; - /* Iterate properties on this interface */ - while (!container_end(m)) { - /* Enter property dict */ - rc = sd_bus_message_enter_container(m, 'a', "{sv}"); - if (rc < 0) { - dbus_err(root, rc); + /* for each property */ + for (;;) { + DBusMessageIter prop, val; + const char *propname; + + dbus_message_iter_recurse(props, &prop); + + if (!dbus_object_is_type(&prop, DBUS_TYPE_STRING)) { + nvme_msg(root, LOG_ERR, + "error unmashalling object (propname)\n"); return -1; } - while (!container_end(m)) { - char *propname = NULL; - size_t sz; - const uint8_t *types = NULL; - /* Enter property item */ - rc = sd_bus_message_enter_container(m, 'e', "sv"); - if (rc < 0) { - dbus_err(root, rc); - return -1; - } - - rc = sd_bus_message_read(m, "s", &propname); - if (rc < 0) { - dbus_err(root, rc); - return -1; - } - - if (strcmp(propname, "EID") == 0) { - rc = sd_bus_message_read(m, "v", "y", &eid); - have_eid = true; - } else if (strcmp(propname, "NetworkId") == 0) { - rc = sd_bus_message_read(m, "v", "i", &net); - have_net = true; - } else if (strcmp(propname, "SupportedMessageTypes") == 0) { - sd_bus_message_enter_container(m, 'v', "ay"); - rc = sd_bus_message_read_array(m, 'y', (const void**)&types, &sz); - if (rc >= 0) - for (size_t s = 0; s < sz; s++) - if (types[s] == MCTP_TYPE_NVME) - have_nvmemi = true; - sd_bus_message_exit_container(m); - } else { - rc = sd_bus_message_skip(m, "v"); - } - - if (rc < 0) { - dbus_err(root, rc); - return -1; - } - - /* Exit prop item */ - rc = sd_bus_message_exit_container(m); - if (rc < 0) { - dbus_err(root, rc); - return -1; - } - } + dbus_message_iter_get_basic(&prop, &propname); - /* Exit property dict */ - rc = sd_bus_message_exit_container(m); - if (rc < 0) { - dbus_err(root, rc); + dbus_message_iter_next(&prop); + + if (!dbus_object_is_type(&prop, DBUS_TYPE_VARIANT)) { + nvme_msg(root, LOG_ERR, + "error unmashalling object (propval)\n"); return -1; } + + dbus_message_iter_recurse(&prop, &val); + + if (!strcmp(propname, "EID")) { + rc = read_variant_basic(&val, DBUS_TYPE_BYTE, &eid); + have_eid = true; + + } else if (!strcmp(propname, "NetworkId")) { + rc = read_variant_basic(&val, DBUS_TYPE_INT32, &net); + have_net = true; + + } else if (!strcmp(propname, "SupportedMessageTypes")) { + have_nvmemi = has_message_type(&val, MCTP_TYPE_NVME); + } + + if (rc) + return rc; + + if (!dbus_message_iter_next(props)) + break; } if (have_nvmemi) { @@ -659,70 +660,61 @@ static int handle_mctp_endpoint(nvme_root_t root, const char* objpath, return rc; } -static int handle_mctp_obj(nvme_root_t root, sd_bus_message *m) +/* obj is an array of (object path, interfaces) dict entries - ie., dbus type + * a{oa{sa{sv}}} + */ +static int handle_mctp_obj(nvme_root_t root, DBusMessageIter *obj) { - char *objpath = NULL; - char *ifname = NULL; - int rc; + const char *objpath = NULL; + DBusMessageIter intfs; - rc = sd_bus_message_read(m, "o", &objpath); - if (rc < 0) { - dbus_err(root, rc); + if (!dbus_object_is_type(obj, DBUS_TYPE_OBJECT_PATH)) { + nvme_msg(root, LOG_ERR, "error unmashalling object (path)\n"); return -1; } - /* Enter response object: our array of (string, property dict) - * values */ - rc = sd_bus_message_enter_container(m, 'a', "{sa{sv}}"); - if (rc < 0) { - dbus_err(root, rc); + dbus_message_iter_get_basic(obj, &objpath); + + dbus_message_iter_next(obj); + + if (!dbus_object_is_dict(obj)) { + nvme_msg(root, LOG_ERR, "error unmashalling object (intfs)\n"); return -1; } + dbus_message_iter_recurse(obj, &intfs); /* for each interface */ - while (!container_end(m)) { - /* Enter interface item */ - rc = sd_bus_message_enter_container(m, 'e', "sa{sv}"); - if (rc < 0) { - dbus_err(root, rc); - return -1; - } + for (;;) { + DBusMessageIter props, intf; + const char *intfname; - rc = sd_bus_message_read(m, "s", &ifname); - if (rc < 0) { - dbus_err(root, rc); + dbus_message_iter_recurse(&intfs, &intf); + + if (!dbus_object_is_type(&intf, DBUS_TYPE_STRING)) { + nvme_msg(root, LOG_ERR, + "error unmashalling object (intf)\n"); return -1; } - if (!strcmp(ifname, MCTP_DBUS_IFACE_ENDPOINT)) { - - rc = handle_mctp_endpoint(root, objpath, m); - if (rc < 0) { - /* continue to next object */ - } - } else { - /* skip the interfaces we don't care about */ - rc = sd_bus_message_skip(m, "a{sv}"); - if (rc < 0) { - dbus_err(root, rc); - return -1; - } + dbus_message_iter_get_basic(&intf, &intfname); + + if (strcmp(intfname, MCTP_DBUS_IFACE_ENDPOINT)) { + if (!dbus_message_iter_next(&intfs)) + break; + continue; } - /* Exit interface item */ - rc = sd_bus_message_exit_container(m); - if (rc < 0) { - dbus_err(root, rc); + dbus_message_iter_next(&intf); + + if (!dbus_object_is_dict(&intf)) { + nvme_msg(root, LOG_ERR, + "error unmarshalling object (props)\n"); return -1; } - } - /* Exit response object */ - rc = sd_bus_message_exit_container(m); - if (rc < 0) { - dbus_err(root, rc); - return -1; + dbus_message_iter_recurse(&intf, &props); + return handle_mctp_endpoint(root, objpath, &props); } return 0; @@ -730,85 +722,85 @@ static int handle_mctp_obj(nvme_root_t root, sd_bus_message *m) nvme_root_t nvme_mi_scan_mctp(void) { - sd_bus *bus = NULL; - sd_bus_message *resp = NULL; - sd_bus_error berr = SD_BUS_ERROR_NULL; - int rc, errno_save; + DBusMessage *msg, *resp = NULL; + DBusConnection *bus = NULL; + DBusMessageIter args, objs; + int errno_save, rc = -1; nvme_root_t root; + dbus_bool_t drc; + DBusError berr; root = nvme_mi_create_root(NULL, DEFAULT_LOGLEVEL); if (!root) { errno = ENOMEM; - rc = -1; + return NULL; + } + + dbus_error_init(&berr); + + bus = dbus_bus_get(DBUS_BUS_SYSTEM, &berr); + if (!bus) { + nvme_msg(root, LOG_ERR, "Failed connecting to D-Bus: %s (%s)\n", + berr.message, berr.name); goto out; } - rc = sd_bus_default_system(&bus); - if (rc < 0) { - nvme_msg(root, LOG_ERR, "Failed opening D-Bus: %s\n", - strerror(-rc)); - errno = -rc; - rc = -1; + msg = dbus_message_new_method_call(MCTP_DBUS_IFACE, + MCTP_DBUS_PATH, + "org.freedesktop.DBus.ObjectManager", + "GetManagedObjects"); + if (!msg) { + nvme_msg(root, LOG_ERR, "Failed creating call message\n"); goto out; } - rc = sd_bus_call_method(bus, - MCTP_DBUS_IFACE, - MCTP_DBUS_PATH, - "org.freedesktop.DBus.ObjectManager", - "GetManagedObjects", - &berr, - &resp, - ""); - if (rc < 0) { + resp = dbus_connection_send_with_reply_and_block(bus, msg, + DBUS_TIMEOUT_USE_DEFAULT, + &berr); + dbus_message_unref(msg); + if (!resp) { nvme_msg(root, LOG_ERR, "Failed querying MCTP D-Bus: %s (%s)\n", berr.message, berr.name); - errno = -rc; - rc = -1; goto out; } - rc = sd_bus_message_enter_container(resp, 'a', "{oa{sa{sv}}}"); - if (rc != 1) { - dbus_err(root, rc); - if (rc == 0) - errno = EPROTO; - rc = -1; + /* argument container */ + drc = dbus_message_iter_init(resp, &args); + if (!drc) { + nvme_msg(root, LOG_ERR, "can't read dbus reply args\n"); goto out; } - /* Iterate over all managed objects */ - while (!container_end(resp)) { - rc = sd_bus_message_enter_container(resp, 'e', "oa{sa{sv}}"); - if (rc < 0) { - dbus_err(root, rc); - rc = -1; - goto out; - } + if (!dbus_object_is_dict(&args)) { + nvme_msg(root, LOG_ERR, "error unmashalling args\n"); + goto out; + } - handle_mctp_obj(root, resp); + /* objects container */ + dbus_message_iter_recurse(&args, &objs); - rc = sd_bus_message_exit_container(resp); - if (rc < 0) { - dbus_err(root, rc); - rc = -1; - goto out; - } - } + rc = 0; - rc = sd_bus_message_exit_container(resp); - if (rc < 0) { - dbus_err(root, rc); - rc = -1; - goto out; + for (;;) { + DBusMessageIter ent; + + dbus_message_iter_recurse(&objs, &ent); + + rc = handle_mctp_obj(root, &ent); + if (rc) + break; + + if (!dbus_message_iter_next(&objs)) + break; } - rc = 0; out: errno_save = errno; - sd_bus_error_free(&berr); - sd_bus_message_unref(resp); - sd_bus_unref(bus); + if (resp) + dbus_message_unref(resp); + if (bus) + dbus_connection_unref(bus); + dbus_error_free(&berr); if (rc < 0) { if (root) { @@ -820,11 +812,11 @@ out: return root; } -#else /* CONFIG_LIBSYSTEMD */ +#else /* CONFIG_DBUS */ nvme_root_t nvme_mi_scan_mctp(void) { return NULL; } -#endif /* CONFIG_LIBSYSTEMD */ +#endif /* CONFIG_DBUS */