sdbusplus reading InterfacesAdded issue: not all variants are created equal

Patrick Williams patrick at stwcx.xyz
Fri Dec 24 03:24:30 AEDT 2021


On Thu, Dec 23, 2021 at 06:45:26PM +0300, Paul Fertser wrote:
> Hello,
> 
> While digging into current state of SNMP notifications (traps) support
> in OpenBMC I found some code I have no idea how to properly improve.
> 
> phosphor-dbus-monitor has a handler that's meant to be called whenever
> a new log entry is created by monitoring InterfacesAdded signals on
> D-Bus logger paths. The processing is at
> 
> https://github.com/openbmc/phosphor-dbus-monitor/blob/master/src/snmp_trap.cpp#L28
> 
> It seems OK until you look into PathInterfacesAdded definition which
> includes a hard-coded std::variant<>:
> https://github.com/openbmc/phosphor-dbus-monitor/blob/master/src/data_types.hpp#L66
> 
> This already raises suspicions and rightfully so: the interface we're
> specifically interested in, xyz.openbmc_project.Logging.Entry,
> includes AdditionalData property which should be of type
> std::vector<std::string> , but that's not in the list of the allowed
> hardcoded variants.
> 
> If I'm trying to use the std::variant<> type suitable for
> Logging.Entry then msg.read() fails with InvalidEnum error, probably
> trying to parse data about other interfaces, and this is a bad idea
> anyway.
> 
> So what is the correct method of using statically-typed sdbusplus APIs
> to parse such a "dynamic" reply?

The short answer is that there isn't currently.  The code doesn't support either
something like 'std::any' or something like 'std::placeholders' to skip past
parsing of an entry.

Generally, you know the type of the signal you're trying to listen to, so this
wasn't very important.  There are a few cases where the code interacting with
dbus is "generic" and it becomes important.  I think in this case you're
expecting to be able to match against configuration in JSON?  So we probably
need to do something to make the situation better.

In phosphor-inventory-manager they've had a similar problem and what we've ended
up having to do is extend the variant list for each new element type they want
to accept.  I think they wrote a python script that generates it from the
phosphor-dbus-interfaces YAML information at build time.

There is something a little better than that available though.  If you look at
the generated headers for phosphor-dbus-interface, you'll see that each class
has a PropertiesVariant.  Here is the one for Logging.Entry:

   using PropertiesVariant = sdbusplus::utility::dedup_variant_t<
                Level,
                bool,
                std::string,
                std::vector<std::string>,
                uint32_t,
                uint64_t>;

`dedup_variant_t` is a class that evaluates to a std::variant, but makes sure
that each type is only listed once.  You could pretty easily add a
`merge_variant` on top of this that would be the union of all the variant types.
Then, the type you'd pass into `msg.read` would be:

    using Value =
        merge_variant<xyz::openbmc_project::Logging::Entry::PropertiesVariant,
                      ...>;

Where we'd list all the interfaces we expect phosphor-dbus-monitor to be able to
handle.

You mentioned the InvalidEnum error.  I'd have to see what you were doing there
but if you both an Enum-type and a std::string in the variant it should have
parsed as a std::string if the Enum-matching was unsuccessful and not thrown an
error.  I thought I had a test case for that exact scenario as well.  If you are
seeing that, it sounds like a bug.

-- 
Patrick Williams
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://lists.ozlabs.org/pipermail/openbmc/attachments/20211223/f419bfc2/attachment.sig>


More information about the openbmc mailing list