Skip to content

Commit 02e1334

Browse files
Add interface au.com.codeconstruct.MCTP.Bridge1
New endpoint object interface au.com.codeconstruct.MCTP.Bridge1 which will capture details of bridge type endpoint such as pool start, pool end. Update test framework with new test methods to validate bridge pool assignemnt. Signed-off-by: Faizan Ali <[email protected]>
1 parent 61c8920 commit 02e1334

File tree

3 files changed

+142
-0
lines changed

3 files changed

+142
-0
lines changed

docs/mctpd.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,17 @@ busctl call au.com.codeconstruct.MCTP1 \
219219

220220
Removes the MCTP endpoint from `mctpd`, and deletes routes and neighbour entries.
221221

222+
For any endpoint which also happens to be an MCTP Bridge, if dynamic eid is assgined to it via d-bus method `.AssignEndpoint`,
223+
such endpoint's pool allocation details would be reflected into `au.com.codeconstruct.MCTP.Bridge1` interface of bridge's endpoint object.
224+
225+
### `.PoolEnd`: `y`
226+
227+
A constant property representing last EID in the contiguous range allocated for downstream endpoints.
228+
229+
### `.PoolStart`: `y`
230+
231+
A constant property representing first EID in the contiguous range allocated for downstream endpoints.
232+
222233
## Configuration
223234

224235
`mctpd` reads configuration data from a TOML file, typically `/etc/mctpd.conf`.

src/mctpd.c

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
#define MCTP_DBUS_PATH_LINKS "/au/com/codeconstruct/mctp1/interfaces"
4646
#define CC_MCTP_DBUS_IFACE_BUSOWNER "au.com.codeconstruct.MCTP.BusOwner1"
4747
#define CC_MCTP_DBUS_IFACE_ENDPOINT "au.com.codeconstruct.MCTP.Endpoint1"
48+
#define CC_MCTP_DBUS_IFACE_BRIDGE "au.com.codeconstruct.MCTP.Bridge1"
4849
#define CC_MCTP_DBUS_IFACE_TESTING "au.com.codeconstruct.MCTPTesting"
4950
#define MCTP_DBUS_NAME "au.com.codeconstruct.MCTP1"
5051
#define MCTP_DBUS_IFACE_ENDPOINT "xyz.openbmc_project.MCTP.Endpoint"
@@ -151,6 +152,7 @@ struct peer {
151152
bool published;
152153
sd_bus_slot *slot_obmc_endpoint;
153154
sd_bus_slot *slot_cc_endpoint;
155+
sd_bus_slot *slot_bridge;
154156
sd_bus_slot *slot_uuid;
155157
char *path;
156158

@@ -256,6 +258,7 @@ static int endpoint_allocate_eid(struct peer *peer);
256258

257259
static const sd_bus_vtable bus_endpoint_obmc_vtable[];
258260
static const sd_bus_vtable bus_endpoint_cc_vtable[];
261+
static const sd_bus_vtable bus_endpoint_bridge[];
259262
static const sd_bus_vtable bus_endpoint_uuid_vtable[];
260263

261264
__attribute__((format(printf, 1, 2))) static void bug_warn(const char *fmt, ...)
@@ -1586,6 +1589,7 @@ static void free_peers(struct ctx *ctx)
15861589
free(peer->path);
15871590
sd_bus_slot_unref(peer->slot_obmc_endpoint);
15881591
sd_bus_slot_unref(peer->slot_cc_endpoint);
1592+
sd_bus_slot_unref(peer->slot_bridge);
15891593
sd_bus_slot_unref(peer->slot_uuid);
15901594
free(peer);
15911595
}
@@ -2624,6 +2628,11 @@ static int publish_peer(struct peer *peer, bool add_route)
26242628
peer->path, CC_MCTP_DBUS_IFACE_ENDPOINT,
26252629
bus_endpoint_cc_vtable, peer);
26262630

2631+
if (peer->pool_size > 0) {
2632+
sd_bus_add_object_vtable(peer->ctx->bus, &peer->slot_bridge,
2633+
peer->path, CC_MCTP_DBUS_IFACE_BRIDGE,
2634+
bus_endpoint_bridge, peer);
2635+
}
26272636
if (peer->uuid) {
26282637
sd_bus_add_object_vtable(peer->ctx->bus, &peer->slot_uuid,
26292638
peer->path, OPENBMC_IFACE_COMMON_UUID,
@@ -2674,6 +2683,8 @@ static int unpublish_peer(struct peer *peer)
26742683
peer->slot_obmc_endpoint = NULL;
26752684
sd_bus_slot_unref(peer->slot_cc_endpoint);
26762685
peer->slot_cc_endpoint = NULL;
2686+
sd_bus_slot_unref(peer->slot_bridge);
2687+
peer->slot_bridge = NULL;
26772688
sd_bus_slot_unref(peer->slot_uuid);
26782689
peer->slot_uuid = NULL;
26792690
peer->published = false;
@@ -3058,6 +3069,28 @@ static int bus_endpoint_get_prop(sd_bus *bus, const char *path,
30583069
return rc;
30593070
}
30603071

3072+
static int bus_bridge_get_prop(sd_bus *bus, const char *path,
3073+
const char *interface, const char *property,
3074+
sd_bus_message *reply, void *userdata,
3075+
sd_bus_error *berr)
3076+
{
3077+
struct peer *peer = userdata;
3078+
int rc;
3079+
3080+
if (strcmp(property, "PoolStart") == 0) {
3081+
rc = sd_bus_message_append(reply, "y", peer->pool_start);
3082+
} else if (strcmp(property, "PoolEnd") == 0) {
3083+
uint8_t pool_end = peer->pool_start + peer->pool_size - 1;
3084+
rc = sd_bus_message_append(reply, "y", pool_end);
3085+
} else {
3086+
warnx("Unknown bridge property '%s' for %s iface %s", property,
3087+
path, interface);
3088+
rc = -ENOENT;
3089+
}
3090+
3091+
return rc;
3092+
}
3093+
30613094
static int bus_network_get_prop(sd_bus *bus, const char *path,
30623095
const char *interface, const char *property,
30633096
sd_bus_message *reply, void *userdata,
@@ -3257,6 +3290,21 @@ static const sd_bus_vtable bus_endpoint_cc_vtable[] = {
32573290
SD_BUS_VTABLE_END
32583291
};
32593292

3293+
static const sd_bus_vtable bus_endpoint_bridge[] = {
3294+
SD_BUS_VTABLE_START(0),
3295+
SD_BUS_PROPERTY("PoolStart",
3296+
"y",
3297+
bus_bridge_get_prop,
3298+
0,
3299+
SD_BUS_VTABLE_PROPERTY_CONST),
3300+
SD_BUS_PROPERTY("PoolEnd",
3301+
"y",
3302+
bus_bridge_get_prop,
3303+
0,
3304+
SD_BUS_VTABLE_PROPERTY_CONST),
3305+
SD_BUS_VTABLE_END
3306+
};
3307+
32603308
static const sd_bus_vtable bus_link_vtable[] = {
32613309
SD_BUS_VTABLE_START(0),
32623310
SD_BUS_WRITABLE_PROPERTY("Role",

tests/test_mctpd.py

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
MCTPD_MCTP_P = '/au/com/codeconstruct/mctp1'
2121
MCTPD_MCTP_I = 'au.com.codeconstruct.MCTP.BusOwner1'
2222
MCTPD_ENDPOINT_I = 'au.com.codeconstruct.MCTP.Endpoint1'
23+
MCTPD_ENDPOINT_BRIDGE_I = 'au.com.codeconstruct.MCTP.Bridge1'
2324
DBUS_OBJECT_MANAGER_I = 'org.freedesktop.DBus.ObjectManager'
2425
DBUS_PROPERTIES_I = 'org.freedesktop.DBus.Properties'
2526

@@ -971,3 +972,85 @@ async def test_assign_dynamic_bridge_eid(dbus, mctpd):
971972
assert ep.eid < br_ep.eid <= ep.eid + ep.allocated_pool_size
972973
(_, new) = await net.call_learn_endpoint(br_ep.eid)
973974
assert new
975+
976+
""" Test that we truncate the requested pool size to
977+
the max_pool_size config """
978+
async def test_assign_dynamic_eid_limited_pool(nursery, dbus, sysnet):
979+
max_pool_size = 1
980+
config = f"""
981+
[bus-owner]
982+
max_pool_size = {max_pool_size}
983+
"""
984+
985+
mctpd = MctpdWrapper(dbus, sysnet, config = config)
986+
await mctpd.start_mctpd(nursery)
987+
988+
iface = mctpd.system.interfaces[0]
989+
ep = mctpd.network.endpoints[0]
990+
mctp = await mctpd_mctp_iface_obj(dbus, iface)
991+
992+
# Set up bridged endpoints as undiscovered EID 0
993+
for i in range(0, 2):
994+
br_ep = Endpoint(iface, bytes(), types=[0, 2])
995+
ep.add_bridged_ep(br_ep)
996+
mctpd.network.add_endpoint(br_ep)
997+
998+
# dynamic EID assigment for dev1
999+
(eid, _, path, new) = await mctp.call_assign_endpoint(
1000+
ep.lladdr,
1001+
)
1002+
1003+
assert new
1004+
1005+
bridge_obj = await dbus.get_proxy_object(MCTPD_C, path)
1006+
props_iface = await bridge_obj.get_interface(DBUS_PROPERTIES_I)
1007+
pool_end = await props_iface.call_get(MCTPD_ENDPOINT_BRIDGE_I, "PoolEnd")
1008+
pool_size = pool_end.value - eid
1009+
assert pool_size == max_pool_size
1010+
1011+
res = await mctpd.stop_mctpd()
1012+
assert res == 0
1013+
1014+
""" Test that no pool is assigned for requested pool size from
1015+
unavailable pool space"""
1016+
async def test_assign_dynamic_unavailable_pool(nursery, dbus, sysnet):
1017+
(min_dyn_eid, max_dyn_eid) = (8, 12)
1018+
config = f"""
1019+
[bus-owner]
1020+
dynamic_eid_range = [{min_dyn_eid}, {max_dyn_eid}]
1021+
"""
1022+
1023+
mctpd = MctpdWrapper(dbus, sysnet, config = config)
1024+
await mctpd.start_mctpd(nursery)
1025+
1026+
iface = mctpd.system.interfaces[0]
1027+
ep = mctpd.network.endpoints[0]
1028+
mctp = await mctpd_mctp_iface_obj(dbus, iface)
1029+
1030+
# Set up bridged endpoints as undiscovered EID 0
1031+
for i in range(0, 2):
1032+
br_ep = Endpoint(iface, bytes(), types=[0, 2])
1033+
ep.add_bridged_ep(br_ep)
1034+
mctpd.network.add_endpoint(br_ep)
1035+
1036+
# consume middle eid from the range to dev2
1037+
dev2 = Endpoint(iface, bytes([0x09]))
1038+
mctpd.network.add_endpoint(dev2)
1039+
(eid, _, path, new) = await mctp.call_assign_endpoint_static(
1040+
dev2.lladdr,
1041+
10
1042+
)
1043+
assert new
1044+
1045+
# dynamic EID assigment for dev1
1046+
(eid, _, path, new) = await mctp.call_assign_endpoint(
1047+
ep.lladdr,
1048+
)
1049+
assert new
1050+
# Interface should not be present for unavailable pool space
1051+
with pytest.raises(asyncdbus.errors.InterfaceNotFoundError):
1052+
bridge_obj = await dbus.get_proxy_object(MCTPD_C, path)
1053+
await bridge_obj.get_interface(MCTPD_ENDPOINT_BRIDGE_I)
1054+
1055+
res = await mctpd.stop_mctpd()
1056+
assert res == 0

0 commit comments

Comments
 (0)