D-Bus Guide

Master D-Bus communication in OpenBMC.

Table of Contents

  1. Overview
  2. D-Bus Concepts
    1. Core Components
    2. Terminology
    3. Naming Conventions
  3. Using busctl
    1. List Services
    2. Explore Objects
    3. Introspect Objects
    4. Read Properties
    5. Set Properties
    6. Call Methods
    7. Monitor Signals
  4. phosphor-dbus-interfaces
    1. YAML Format
    2. Type Signatures
  5. sdbusplus Library
    1. Creating a D-Bus Client
    2. Creating a D-Bus Server
    3. Async with sdbusplus and Boost.Asio
  6. phosphor-objmgr (Object Mapper)
    1. Query Objects by Interface
    2. Get Service for Object
    3. Using mapper CLI
  7. D-Bus Associations
    1. Association Structure
    2. Query Associations
  8. Troubleshooting
    1. Common Issues
    2. Debug Commands
  9. Next Steps
  10. Examples
  11. References
  12. Deep Dive
    1. D-Bus Message Flow Architecture
    2. Object Mapper Internals
    3. sdbusplus Code Generation Pipeline
    4. D-Bus Policy Configuration
    5. D-Bus Type System Internals
    6. PropertiesChanged Signal Mechanism
    7. Source Code References

Overview

D-Bus is the central communication system in OpenBMC. All services expose their functionality through D-Bus, enabling:

  • Loose coupling: Services don’t need to know about each other’s implementation
  • Discovery: Services can be found dynamically at runtime
  • Introspection: Interfaces can be explored without documentation
  • Language agnostic: Any language with D-Bus bindings can participate

D-Bus Concepts

Core Components

flowchart TB
    daemon["D-Bus Daemon<br/>(Message Router)"]

    subgraph services["Connected Services"]
        direction LR
        A["Service A<br/>xyz.openbmc_project.ServiceA"]
        B["Service B<br/>xyz.openbmc_project.ServiceB"]
        C["Service C<br/>xyz.openbmc_project.ServiceC"]
    end

    daemon <--> A
    daemon <--> B
    daemon <--> C
ASCII-art version (for comparison)
┌─────────────────────────────────────────────────────────────────┐
│                         D-Bus Daemon                            │
│                    (Message Router)                             │
└─────────────────────────────────────────────────────────────────┘
         │                    │                    │
         ▼                    ▼                    ▼
┌─────────────────┐  ┌─────────────────┐  ┌─────────────────┐
│    Service A    │  │    Service B    │  │    Service C    │
│                 │  │                 │  │                 │
│ Well-known name │  │ Well-known name │  │ Well-known name │
│ xyz.openbmc_    │  │ xyz.openbmc_    │  │ xyz.openbmc_    │
│ project.ServiceA│  │ project.ServiceB│  │ project.ServiceC│
└─────────────────┘  └─────────────────┘  └─────────────────┘

Terminology

Term Description Example
Bus Communication channel System bus (shared by all)
Service Application connected to bus xyz.openbmc_project.State.Host
Object Resource exposed by service /xyz/openbmc_project/state/host0
Interface Contract defining methods/properties xyz.openbmc_project.State.Host
Property Data exposed by object CurrentHostState
Method Action that can be invoked Reboot()
Signal Broadcast notification PropertiesChanged

Naming Conventions

OpenBMC uses consistent naming:

Service:   xyz.openbmc_project.<Category>.<Name>
Object:    /xyz/openbmc_project/<category>/<name>
Interface: xyz.openbmc_project.<Category>.<Name>

Examples:

  • xyz.openbmc_project.State.Host - Host state service
  • /xyz/openbmc_project/state/host0 - Host 0 state object
  • xyz.openbmc_project.Sensor.Value - Sensor value interface

Using busctl

busctl is the primary tool for D-Bus interaction.

List Services

# List all services
busctl list

# Filter OpenBMC services
busctl list | grep xyz.openbmc_project

Explore Objects

# Show object tree for a service
busctl tree xyz.openbmc_project.State.Host

# Example output:
# └─/xyz
#   └─/xyz/openbmc_project
#     └─/xyz/openbmc_project/state
#       └─/xyz/openbmc_project/state/host0

Introspect Objects

# Show interfaces, methods, properties, signals
busctl introspect xyz.openbmc_project.State.Host \
    /xyz/openbmc_project/state/host0

# Example output:
# NAME                                TYPE      SIGNATURE RESULT/VALUE
# xyz.openbmc_project.State.Host      interface -         -
# .CurrentHostState                   property  s         "xyz.openbmc_project..."
# .RequestedHostTransition            property  s         "xyz.openbmc_project..."

Read Properties

# Get a single property
busctl get-property xyz.openbmc_project.State.Host \
    /xyz/openbmc_project/state/host0 \
    xyz.openbmc_project.State.Host \
    CurrentHostState

# Output: s "xyz.openbmc_project.State.Host.HostState.Off"

Set Properties

# Set a property (request host power on)
busctl set-property xyz.openbmc_project.State.Host \
    /xyz/openbmc_project/state/host0 \
    xyz.openbmc_project.State.Host \
    RequestedHostTransition s \
    "xyz.openbmc_project.State.Host.Transition.On"

Call Methods

# Call a method
busctl call xyz.openbmc_project.ObjectMapper \
    /xyz/openbmc_project/object_mapper \
    xyz.openbmc_project.ObjectMapper \
    GetSubTree sias "/" 0 1 "xyz.openbmc_project.Sensor.Value"

Monitor Signals

# Watch for property changes
busctl monitor xyz.openbmc_project.State.Host

# Watch all D-Bus traffic (verbose)
dbus-monitor --system

phosphor-dbus-interfaces

Interface definitions live in the phosphor-dbus-interfaces repository.

YAML Format

Interfaces are defined in YAML:

# xyz/openbmc_project/Example/MyInterface.interface.yaml
description: >
    Example interface demonstrating YAML format.

properties:
    - name: MyProperty
      type: string
      description: An example string property.

    - name: MyValue
      type: int32
      description: An example integer property.

methods:
    - name: DoSomething
      description: Performs an action.
      parameters:
          - name: Input
            type: string
            description: Input parameter.
      returns:
          - name: Result
            type: boolean
            description: Success or failure.

signals:
    - name: SomethingHappened
      description: Emitted when something happens.
      properties:
          - name: What
            type: string

Type Signatures

D-Bus uses type signatures:

Signature Type C++ Type
s String std::string
b Boolean bool
i Int32 int32_t
u Uint32 uint32_t
x Int64 int64_t
t Uint64 uint64_t
d Double double
o Object path sdbusplus::message::object_path
a Array std::vector<T>
(...) Struct std::tuple<...>
a{sv} Dict std::map<std::string, std::variant<...>>

sdbusplus Library

sdbusplus is the C++ library for D-Bus in OpenBMC.

Source Reference: sdbusplus

Creating a D-Bus Client

#include <sdbusplus/bus.hpp>
#include <iostream>

int main()
{
    // Connect to system bus
    auto bus = sdbusplus::bus::new_default();

    // Create method call
    auto method = bus.new_method_call(
        "xyz.openbmc_project.State.Host",           // Service
        "/xyz/openbmc_project/state/host0",         // Object
        "org.freedesktop.DBus.Properties",          // Interface
        "Get"                                        // Method
    );

    // Add arguments
    method.append("xyz.openbmc_project.State.Host", // Interface
                  "CurrentHostState");               // Property

    // Call and get reply
    auto reply = bus.call(method);

    // Extract result
    std::variant<std::string> value;
    reply.read(value);

    std::cout << "Host state: " << std::get<std::string>(value) << "\n";

    return 0;
}

Creating a D-Bus Server

#include <sdbusplus/bus.hpp>
#include <sdbusplus/server.hpp>
#include <xyz/openbmc_project/Example/MyInterface/server.hpp>

// Generated server binding
using MyInterfaceInherit = sdbusplus::server::object_t<
    sdbusplus::xyz::openbmc_project::Example::server::MyInterface>;

class MyService : public MyInterfaceInherit
{
  public:
    MyService(sdbusplus::bus_t& bus, const char* path) :
        MyInterfaceInherit(bus, path)
    {
        // Initialize properties
        myProperty("initial value");
    }

    // Property getter/setter are auto-generated

    // Implement methods
    bool doSomething(std::string input) override
    {
        std::cout << "doSomething called with: " << input << "\n";
        return true;
    }
};

int main()
{
    auto bus = sdbusplus::bus::new_default();

    // Request well-known name
    bus.request_name("xyz.openbmc_project.Example");

    // Create server object
    MyService myService(bus, "/xyz/openbmc_project/example");

    // Process D-Bus events
    while (true)
    {
        bus.process_discard();
        bus.wait();
    }

    return 0;
}

Async with sdbusplus and Boost.Asio

#include <sdbusplus/asio/connection.hpp>
#include <sdbusplus/asio/object_server.hpp>
#include <boost/asio.hpp>

int main()
{
    boost::asio::io_context io;
    auto conn = std::make_shared<sdbusplus::asio::connection>(io);

    conn->request_name("xyz.openbmc_project.Example");

    sdbusplus::asio::object_server server(conn);

    auto iface = server.add_interface(
        "/xyz/openbmc_project/example",
        "xyz.openbmc_project.Example.MyInterface"
    );

    // Add property
    std::string myValue = "hello";
    iface->register_property("MyProperty", myValue,
        // Setter
        [](const std::string& newValue, std::string& value) {
            value = newValue;
            return true;
        }
    );

    iface->initialize();

    io.run();
    return 0;
}

phosphor-objmgr (Object Mapper)

The Object Mapper tracks all D-Bus objects and their interfaces.

Query Objects by Interface

# Find all objects implementing Sensor.Value
busctl call xyz.openbmc_project.ObjectMapper \
    /xyz/openbmc_project/object_mapper \
    xyz.openbmc_project.ObjectMapper \
    GetSubTree sias "/" 0 1 "xyz.openbmc_project.Sensor.Value"

Get Service for Object

# Find which service owns an object
busctl call xyz.openbmc_project.ObjectMapper \
    /xyz/openbmc_project/object_mapper \
    xyz.openbmc_project.ObjectMapper \
    GetObject sas "/xyz/openbmc_project/state/host0" 0

Using mapper CLI

# List objects with interface
mapper get-subtree / xyz.openbmc_project.Sensor.Value

# Get service for object
mapper get-service /xyz/openbmc_project/state/host0

D-Bus Associations

Associations link related objects together.

Association Structure

flowchart LR
    sensor["/sensors/temp0<br/><br/>associations:<br/>[inventory,sensors,<br/>/inventory/cpu0]"]
    inventory["/inventory/cpu0"]

    sensor -->|"sensors"| inventory
    inventory -->|"inventory"| sensor
ASCII-art version (click to expand)
┌─────────────────────┐           ┌─────────────────────┐
│  /sensors/temp0     │──────────▶│  /inventory/cpu0    │
│                     │  sensors  │                     │
│  associations:      │◀──────────│                     │
│  [inventory,sensors,│  inventory│                     │
│   /inventory/cpu0]  │           │                     │
└─────────────────────┘           └─────────────────────┘

Query Associations

# Get associations for an object
busctl introspect xyz.openbmc_project.ObjectMapper \
    /xyz/openbmc_project/sensors/temperature/cpu0

# Look for 'associations' property and endpoints

Troubleshooting

Common Issues

Service not found:

# Check if service is running
systemctl status xyz.openbmc_project.ServiceName

# Check service logs
journalctl -u xyz.openbmc_project.ServiceName

Permission denied:

# Check D-Bus policy
cat /usr/share/dbus-1/system.d/xyz.openbmc_project.*.conf

Property type mismatch:

# Verify property type with introspect
busctl introspect <service> <object> | grep <property>

Debug Commands

# Verbose D-Bus monitoring
dbus-monitor --system "interface='xyz.openbmc_project.State.Host'"

# Check Object Mapper health
busctl tree xyz.openbmc_project.ObjectMapper

# List all interfaces on an object
busctl introspect <service> <object> | grep interface

Next Steps


Examples

Working examples are available in the examples/dbus directory:

  • client/ - D-Bus client examples
  • server/ - D-Bus server/service examples
  • async/ - Asynchronous D-Bus programming

References


Deep Dive

This section provides detailed technical information for developers who want to understand D-Bus internals in OpenBMC.

D-Bus Message Flow Architecture

┌─────────────────────────────────────────────────────────────────────────────┐
│                        D-Bus Message Flow in OpenBMC                        │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  Client Application (e.g., bmcweb)                                          │
│  ┌────────────────────────────────────────────────────────────────────┐     │
│  │  sdbusplus::bus::new_default()                                     │     │
│  │         │                                                          │     │
│  │         v                                                          │     │
│  │  bus.new_method_call(service, object, interface, method)           │     │
│  │         │                                                          │     │
│  │         v                                                          │     │
│  │  method.append(arg1, arg2, ...)  // Serialize arguments            │     │
│  │         │                                                          │     │
│  │         v                                                          │     │
│  │  bus.call(method)  ─────────────────────────────────────────┐      │     │
│  │         │                                     Wait for reply │      │     │
│  └─────────│─────────────────────────────────────────────────────────┘     │
│            │                                                   │            │
│            v                                                   │            │
│  ┌─────────────────────────────────────────────────────────────────────┐   │
│  │                     dbus-daemon (dbus-broker)                       │   │
│  │                                                                     │   │
│  │  1. Receive message from client socket                              │   │
│  │  2. Validate message format and permissions (policy)                │   │
│  │  3. Match destination service name to unique name (:1.XX)           │   │
│  │  4. Route message to destination socket                             │   │
│  │  5. Wait for reply from service                                     │   │
│  │  6. Route reply back to client                                      │   │
│  │                                                                     │   │
│  │  Name Registry:                                                     │   │
│  │  ┌───────────────────────────────────────────────────────────────┐  │   │
│  │  │  :1.15 = xyz.openbmc_project.State.Host                       │  │   │
│  │  │  :1.23 = xyz.openbmc_project.ObjectMapper                     │  │   │
│  │  │  :1.42 = xyz.openbmc_project.Sensor.Manager                   │  │   │
│  │  │  :1.58 = xyz.openbmc_project.Logging                          │  │   │
│  │  └───────────────────────────────────────────────────────────────┘  │   │
│  └─────────────────────────────────────────────────────────────────────┘   │
│            │                                                   ^            │
│            v                                                   │            │
│  ┌─────────────────────────────────────────────────────────────────────┐   │
│  │                   Service (e.g., phosphor-state-manager)            │   │
│  │                                                                     │   │
│  │  Event Loop (sd-event / boost::asio)                                │   │
│  │         │                                                           │   │
│  │         v                                                           │   │
│  │  Message Dispatch: match destination object path                    │   │
│  │         │                                                           │   │
│  │         v                                                           │   │
│  │  Interface Lookup: find registered interface handler                │   │
│  │         │                                                           │   │
│  │         v                                                           │   │
│  │  Method/Property Handler: execute callback                          │   │
│  │         │                                                           │   │
│  │         v                                                           │   │
│  │  Serialize reply and send ───────────────────────────────────┘      │   │
│  └─────────────────────────────────────────────────────────────────────┘   │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘

Object Mapper Internals

The Object Mapper maintains a real-time view of all D-Bus objects:

┌─────────────────────────────────────────────────────────────────────────────┐
│                      Object Mapper Data Structures                          │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  Interface-to-Objects Map:                                                  │
│  ┌────────────────────────────────────────────────────────────────────────┐ │
│  │  xyz.openbmc_project.Sensor.Value:                                     │ │
│  │    - /xyz/openbmc_project/sensors/temperature/ambient                  │ │
│  │    - /xyz/openbmc_project/sensors/temperature/cpu0                     │ │
│  │    - /xyz/openbmc_project/sensors/fan_tach/fan0                        │ │
│  │                                                                        │ │
│  │  xyz.openbmc_project.State.Host:                                       │ │
│  │    - /xyz/openbmc_project/state/host0                                  │ │
│  │                                                                        │ │
│  │  xyz.openbmc_project.Inventory.Item:                                   │ │
│  │    - /xyz/openbmc_project/inventory/system/chassis/motherboard         │ │
│  │    - /xyz/openbmc_project/inventory/system/chassis/motherboard/cpu0    │ │
│  └────────────────────────────────────────────────────────────────────────┘ │
│                                                                             │
│  Object-to-Services Map:                                                    │
│  ┌────────────────────────────────────────────────────────────────────────┐ │
│  │  /xyz/openbmc_project/sensors/temperature/cpu0:                        │ │
│  │    - xyz.openbmc_project.HwmonTempSensor                               │ │
│  │        Interfaces: [xyz.openbmc_project.Sensor.Value,                  │ │
│  │                     xyz.openbmc_project.Sensor.Threshold.Warning,      │ │
│  │                     xyz.openbmc_project.Sensor.Threshold.Critical,     │ │
│  │                     xyz.openbmc_project.Association.Definitions]       │ │
│  └────────────────────────────────────────────────────────────────────────┘ │
│                                                                             │
│  Association Endpoints:                                                     │
│  ┌────────────────────────────────────────────────────────────────────────┐ │
│  │  /xyz/openbmc_project/sensors/temperature/cpu0:                        │ │
│  │    inventory (forward) -> /xyz/openbmc_project/inventory/.../cpu0      │ │
│  │                                                                        │ │
│  │  /xyz/openbmc_project/inventory/.../cpu0:                              │ │
│  │    sensors (reverse) -> /xyz/openbmc_project/sensors/temperature/cpu0  │ │
│  └────────────────────────────────────────────────────────────────────────┘ │
│                                                                             │
│  Update Mechanism:                                                          │
│  ┌────────────────────────────────────────────────────────────────────────┐ │
│  │  1. Subscribe to org.freedesktop.DBus.ObjectManager signals            │ │
│  │  2. Subscribe to NameOwnerChanged for service tracking                 │ │
│  │  3. On InterfacesAdded: update maps, create association endpoints      │ │
│  │  4. On InterfacesRemoved: clean up maps, remove endpoints              │ │
│  │  5. On NameOwnerChanged: handle service start/stop                     │ │
│  └────────────────────────────────────────────────────────────────────────┘ │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘

sdbusplus Code Generation Pipeline

┌─────────────────────────────────────────────────────────────────────────────┐
│                     sdbusplus Interface Generation                          │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  Input: YAML Interface Definition                                           │
│  ┌────────────────────────────────────────────────────────────────────────┐ │
│  │  # xyz/openbmc_project/Sensor/Value.interface.yaml                     │ │
│  │  description: Sensor value interface                                   │ │
│  │  properties:                                                           │ │
│  │    - name: Value                                                       │ │
│  │      type: double                                                      │ │
│  │    - name: Unit                                                        │ │
│  │      type: string                                                      │ │
│  │  signals:                                                              │ │
│  │    - name: ValueChanged                                                │ │
│  │      properties:                                                       │ │
│  │        - name: Value                                                   │ │
│  │          type: double                                                  │ │
│  └────────────────────────────────────────────────────────────────────────┘ │
│                              │                                              │
│                              v                                              │
│  ┌────────────────────────────────────────────────────────────────────────┐ │
│  │                    sdbus++ Code Generator                              │ │
│  │                                                                        │ │
│  │  python3 -m sdbusplus generate-cpp                                     │ │
│  │    --tool sdbus++                                                      │ │
│  │    --output-dir generated/                                             │ │
│  │    xyz/openbmc_project/Sensor/Value                                    │ │
│  └────────────────────────────────────────────────────────────────────────┘ │
│                              │                                              │
│                              v                                              │
│  Generated Output Files:                                                    │
│  ┌────────────────────────────────────────────────────────────────────────┐ │
│  │                                                                        │ │
│  │  server.hpp - Server-side implementation base class                    │ │
│  │  ┌──────────────────────────────────────────────────────────────────┐  │ │
│  │  │  namespace sdbusplus::xyz::openbmc_project::Sensor::server {     │  │ │
│  │  │  class Value {                                                   │  │ │
│  │  │    public:                                                       │  │ │
│  │  │      double value() const;          // Property getter           │  │ │
│  │  │      double value(double val);      // Property setter           │  │ │
│  │  │      std::string unit() const;                                   │  │ │
│  │  │      void valueChanged(double val); // Signal emitter            │  │ │
│  │  │  };                                                              │  │ │
│  │  │  }                                                               │  │ │
│  │  └──────────────────────────────────────────────────────────────────┘  │ │
│  │                                                                        │ │
│  │  client.hpp - Client-side proxy class                                  │ │
│  │  ┌──────────────────────────────────────────────────────────────────┐  │ │
│  │  │  class Value {                                                   │  │ │
│  │  │    public:                                                       │  │ │
│  │  │      auto value();     // Async property read                    │  │ │
│  │  │      auto value(double); // Async property write                 │  │ │
│  │  │  };                                                              │  │ │
│  │  └──────────────────────────────────────────────────────────────────┘  │ │
│  │                                                                        │ │
│  │  common.hpp - Shared type definitions, enums, errors                   │ │
│  │                                                                        │ │
│  └────────────────────────────────────────────────────────────────────────┘ │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘

D-Bus Policy Configuration

┌─────────────────────────────────────────────────────────────────────────────┐
│                      D-Bus Security Policy                                  │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  Policy File Location: /usr/share/dbus-1/system.d/                          │
│                                                                             │
│  Policy Evaluation Order:                                                   │
│  ┌────────────────────────────────────────────────────────────────────────┐ │
│  │  1. Check <deny> rules (most specific first)                           │ │
│  │  2. Check <allow> rules (most specific first)                          │ │
│  │  3. Default action (usually deny)                                      │ │
│  │                                                                        │ │
│  │  Specificity: user > group > context > default                         │ │
│  └────────────────────────────────────────────────────────────────────────┘ │
│                                                                             │
│  Example Policy: xyz.openbmc_project.State.Host.conf                        │
│  ┌────────────────────────────────────────────────────────────────────────┐ │
│  │  <busconfig>                                                           │ │
│  │    <!-- Allow root to own the service name -->                         │ │
│  │    <policy user="root">                                                │ │
│  │      <allow own="xyz.openbmc_project.State.Host"/>                     │ │
│  │    </policy>                                                           │ │
│  │                                                                        │ │
│  │    <!-- Allow anyone to call methods and read properties -->           │ │
│  │    <policy context="default">                                          │ │
│  │      <allow send_destination="xyz.openbmc_project.State.Host"/>        │ │
│  │      <allow receive_sender="xyz.openbmc_project.State.Host"/>          │ │
│  │    </policy>                                                           │ │
│  │                                                                        │ │
│  │    <!-- Restrict property writes to specific users -->                 │ │
│  │    <policy group="admin">                                              │ │
│  │      <allow send_destination="xyz.openbmc_project.State.Host"          │ │
│  │             send_interface="org.freedesktop.DBus.Properties"           │ │
│  │             send_member="Set"/>                                        │ │
│  │    </policy>                                                           │ │
│  │  </busconfig>                                                          │ │
│  └────────────────────────────────────────────────────────────────────────┘ │
│                                                                             │
│  Common Policy Patterns:                                                    │
│  ┌────────────────────────────────────────────────────────────────────────┐ │
│  │  Pattern              │ Use Case                                       │ │
│  │  ─────────────────────┼─────────────────────────────────────────────── │ │
│  │  own="service.name"   │ Allow process to claim well-known name         │ │
│  │  send_destination     │ Allow sending messages to service              │ │
│  │  send_interface       │ Restrict to specific D-Bus interface           │ │
│  │  send_member          │ Restrict to specific method/property           │ │
│  │  receive_sender       │ Allow receiving signals from service           │ │
│  └────────────────────────────────────────────────────────────────────────┘ │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘

D-Bus Type System Internals

┌─────────────────────────────────────────────────────────────────────────────┐
│                      D-Bus Type Serialization                               │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  Wire Format Example: Sensor Reading Message                                │
│                                                                             │
│  Method Call: Get("xyz.openbmc_project.Sensor.Value", "Value")              │
│                                                                             │
│  ┌────────────────────────────────────────────────────────────────────────┐ │
│  │  Message Header (fixed format):                                        │ │
│  │  ┌──────────┬──────────┬──────────┬──────────┬──────────────────────┐  │ │
│  │  │ Endian   │ Type     │ Flags    │ Version  │ Body Length          │  │ │
│  │  │ 'l'      │ 0x01     │ 0x00     │ 0x01     │ 52                   │  │ │
│  │  │ (little) │ (method) │          │          │                      │  │ │
│  │  └──────────┴──────────┴──────────┴──────────┴──────────────────────┘  │ │
│  │                                                                        │ │
│  │  Header Fields (variable):                                             │ │
│  │  ┌──────────────────────────────────────────────────────────────────┐  │ │
│  │  │  PATH:        /xyz/openbmc_project/sensors/temperature/cpu0     │  │ │
│  │  │  INTERFACE:   org.freedesktop.DBus.Properties                   │  │ │
│  │  │  MEMBER:      Get                                               │  │ │
│  │  │  DESTINATION: xyz.openbmc_project.HwmonTempSensor               │  │ │
│  │  │  SIGNATURE:   ss                                                │  │ │
│  │  └──────────────────────────────────────────────────────────────────┘  │ │
│  │                                                                        │ │
│  │  Body (marshalled arguments):                                          │ │
│  │  ┌──────────────────────────────────────────────────────────────────┐  │ │
│  │  │  String: "xyz.openbmc_project.Sensor.Value" (32 bytes + NUL)    │  │ │
│  │  │  String: "Value" (5 bytes + NUL)                                │  │ │
│  │  └──────────────────────────────────────────────────────────────────┘  │ │
│  └────────────────────────────────────────────────────────────────────────┘ │
│                                                                             │
│  Reply Message: Variant containing double                                   │
│  ┌────────────────────────────────────────────────────────────────────────┐ │
│  │  SIGNATURE: v (variant)                                                │ │
│  │                                                                        │ │
│  │  Body:                                                                 │ │
│  │  ┌──────────────────────────────────────────────────────────────────┐  │ │
│  │  │  Variant signature: "d" (1 byte + NUL)                          │  │ │
│  │  │  Padding: 5 bytes (align double to 8)                           │  │ │
│  │  │  Double value: 45.5 (8 bytes, IEEE 754)                         │  │ │
│  │  └──────────────────────────────────────────────────────────────────┘  │ │
│  └────────────────────────────────────────────────────────────────────────┘ │
│                                                                             │
│  Alignment Rules:                                                           │
│  ┌────────────────────────────────────────────────────────────────────────┐ │
│  │  Type      │ Alignment │ Size                                          │ │
│  │  ──────────┼───────────┼───────────────────────────────────────────── │ │
│  │  BYTE      │ 1         │ 1                                             │ │
│  │  INT16     │ 2         │ 2                                             │ │
│  │  INT32     │ 4         │ 4                                             │ │
│  │  INT64     │ 8         │ 8                                             │ │
│  │  DOUBLE    │ 8         │ 8                                             │ │
│  │  STRING    │ 4         │ 4 (length) + data + NUL                       │ │
│  │  ARRAY     │ 4         │ 4 (length) + elements (aligned)               │ │
│  │  STRUCT    │ 8         │ sum of members (each aligned)                 │ │
│  │  VARIANT   │ 1         │ signature + value                             │ │
│  │  DICT      │ 8         │ array of struct{key, value}                   │ │
│  └────────────────────────────────────────────────────────────────────────┘ │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘

PropertiesChanged Signal Mechanism

┌─────────────────────────────────────────────────────────────────────────────┐
│                   PropertiesChanged Signal Flow                             │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  Sensor Service                        Subscriber (bmcweb, ipmid)           │
│  ┌──────────────────────────────┐     ┌──────────────────────────────────┐  │
│  │                              │     │                                  │  │
│  │  // Update property value    │     │  // Subscribe to changes         │  │
│  │  sensorValue(newReading);    │     │  bus.add_match(                  │  │
│  │         │                    │     │    "type='signal',"              │  │
│  │         v                    │     │    "interface='org.freedesktop." │  │
│  │  // sdbusplus auto-emits:    │     │      "DBus.Properties',"         │  │
│  │  PropertiesChanged(          │     │    "member='PropertiesChanged'," │  │
│  │    "xyz.openbmc_project."    │     │    "arg0='xyz.openbmc_project."  │  │
│  │      "Sensor.Value",         │     │      "Sensor.Value'"             │  │
│  │    {"Value": variant(45.5)}, │     │  );                              │  │
│  │    []                        │     │         │                        │  │
│  │  );                          │     │         v                        │  │
│  │         │                    │     │  // Callback invoked             │  │
│  └─────────│────────────────────┘     │  handlePropertyChange(msg) {     │  │
│            │                          │    auto [iface, changed, inv] =  │  │
│            │                          │      msg.unpack<...>();          │  │
│            │                          │    double val =                  │  │
│            │                          │      std::get<double>(           │  │
│            │                          │        changed.at("Value"));     │  │
│            │                          │    // Update cache, emit SSE     │  │
│            v                          │  }                               │  │
│  ┌──────────────────────────────┐     │                                  │  │
│  │       dbus-daemon            │     └──────────────────────────────────┘  │
│  │                              │                    ^                      │
│  │  Match rules table:          │                    │                      │
│  │  ┌────────────────────────┐  │                    │                      │
│  │  │ :1.23 matches:         │  │                    │                      │
│  │  │   PropertiesChanged    │──│────────────────────┘                      │
│  │  │   on Sensor.Value      │  │                                           │
│  │  └────────────────────────┘  │                                           │
│  │                              │                                           │
│  └──────────────────────────────┘                                           │
│                                                                             │
│  Signal Contents:                                                           │
│  ┌────────────────────────────────────────────────────────────────────────┐ │
│  │  Arg 0 (s):  Interface name that changed                               │ │
│  │  Arg 1 (a{sv}): Dictionary of changed properties and new values        │ │
│  │  Arg 2 (as): Array of invalidated property names (cache hints)         │ │
│  └────────────────────────────────────────────────────────────────────────┘ │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘

Source Code References

Component Repository Key Files
sdbusplus library openbmc/sdbusplus include/sdbusplus/bus.hpp, include/sdbusplus/message.hpp
Interface definitions openbmc/phosphor-dbus-interfaces yaml/xyz/openbmc_project/**/*.interface.yaml
Object Mapper openbmc/phosphor-objmgr src/main.cpp, src/associations.cpp
sdbus++ generator openbmc/sdbusplus tools/sdbusplus/, tools/sdbus++
D-Bus policy files openbmc/openbmc meta-phosphor/recipes-phosphor/dbus/
Async connection openbmc/sdbusplus include/sdbusplus/asio/connection.hpp

Tested on: OpenBMC master, QEMU romulus


Back to top

OpenBMC Guide Tutorial is not affiliated with the OpenBMC project. Content is provided for educational purposes.

This site uses Just the Docs, a documentation theme for Jekyll.