From 99e42aaabaf7b4d56d708c5efdd198d21e19e146 Mon Sep 17 00:00:00 2001 From: Jeremy Kerr Date: Thu, 12 Feb 2026 16:02:09 +0800 Subject: [PATCH] mctpd: Update interface vtables when we change to BusOwner role Currently, setting an interface's Role property only sets the link->role. However, we also want to expose the BusOwner1 interface when changing from Unknown to BusOwner, so register the bus_link_owner_vtable on the interface object when this happens. dbus does not like the vtables changing during a call, so we defer this to the main loop context. Fixes: https://github.com/CodeConstruct/mctp/issues/130 Signed-off-by: Jeremy Kerr --- CHANGELOG.md | 5 +++++ src/mctpd.c | 30 ++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3f9ce12..ac5e26b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## [Unreleased] +### Fixes + +1. mctpd's interface objects now expose the BusOwner1 interface when set + as a BusOwner via the Role property + ### Added 1. `mctpd` will now retry endpoint query commands (Get Message Type Support and diff --git a/src/mctpd.c b/src/mctpd.c index a7036ad..96c5606 100644 --- a/src/mctpd.c +++ b/src/mctpd.c @@ -144,6 +144,7 @@ struct link { char *path; sd_bus_slot *slot_iface; sd_bus_slot *slot_busowner; + sd_event_source *role_defer; struct ctx *ctx; }; @@ -4023,6 +4024,27 @@ static int bus_link_get_prop(sd_bus *bus, const char *path, return rc; } +/* deferred handler for link changes, which may alter vtable state */ +static int link_set_role(sd_event_source *ev, void *userdata) +{ + struct link *link = userdata; + int rc; + + sd_event_source_unref(link->role_defer); + link->role_defer = NULL; + + if (link->role != ENDPOINT_ROLE_BUS_OWNER) + return 0; + + rc = sd_bus_add_object_vtable(link->ctx->bus, &link->slot_busowner, + link->path, CC_MCTP_DBUS_IFACE_BUSOWNER, + bus_link_owner_vtable, link); + if (rc) + warnx("adding link owner vtable failed: %d", rc); + + return 0; +} + static int bus_link_set_prop(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *value, void *userdata, @@ -4063,8 +4085,15 @@ static int bus_link_set_prop(sd_bus *bus, const char *path, rc = -EINVAL; goto out; } + + printf("Role for %s set to %s, via dbus\n", link->path, role.conf_val); link->role = role.role; + /* We need to defer the link role change, as we cannot update the vtables + * during the call. + */ + sd_event_add_defer(ctx->event, &link->role_defer, link_set_role, link); + out: set_berr(ctx, rc, berr); return rc; @@ -4494,6 +4523,7 @@ static int prune_old_nets(struct ctx *ctx) static void free_link(struct link *link) { + sd_event_source_disable_unref(link->role_defer); sd_bus_slot_unref(link->slot_iface); sd_bus_slot_unref(link->slot_busowner); free(link->path);