Skip to content

Commit 171ee34

Browse files
committed
mctpd: allow for pool allocations that are smaller than our max limit
Currently, we attempt to allocate bridge pool ranges of the size of our max pool configuration setting, and then trim after we know the requested pool size. If the max allocation is not available, we do not provide *any* EID range to the requesting bridge. However, it's entirely likely that the bridge will request a pool that is smaller than our maximum. We should not reject that allocation, as there is space available. Instead of insisting on allocating the max, just pre-allocate the largest space up to the max. When we then learn the bridge pool size, offer the allocation that we made. If this is smaller than the preallocation, we trim. If it is larger, we just offer what is allocated. This changes a failure case, where the tests expect the less-than-max allocation to fail. No need to preserve this behaviour, as we can actually offer a workable pool at this point. Signed-off-by: Jeremy Kerr <[email protected]>
1 parent 2926e62 commit 171ee34

File tree

2 files changed

+57
-27
lines changed

2 files changed

+57
-27
lines changed

src/mctpd.c

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1943,19 +1943,6 @@ static int endpoint_assign_eid(struct ctx *ctx, sd_bus_error *berr,
19431943
return -EADDRNOTAVAIL;
19441944
}
19451945

1946-
/* Only allow complete pools for now. In future we could reserve
1947-
* this range, in the assumption that the subsequent pool
1948-
* request (in the Set Endpoint ID response) will fit in this
1949-
* reservation.
1950-
*/
1951-
if (alloc.extent < alloc_size) {
1952-
warnx("Cannot allocate sufficient EIDs (+pool %d) on net %d for %s"
1953-
" (largest span %d at %d)",
1954-
alloc_size, net, dest_phys_tostr(dest),
1955-
alloc.extent, alloc.start);
1956-
alloc.extent = 0;
1957-
}
1958-
19591946
new_eid = alloc.start;
19601947

19611948
rc = add_peer(ctx, dest, new_eid, net, &peer, false);
@@ -1983,12 +1970,12 @@ static int endpoint_assign_eid(struct ctx *ctx, sd_bus_error *berr,
19831970
}
19841971

19851972
if (req_pool_size > peer->pool_size) {
1986-
warnx("EID %d: requested pool size (%d) > pool size available (%d)",
1973+
warnx("EID %d: requested pool size (%d) > pool size available (%d), limiting.",
19871974
peer->eid, req_pool_size, peer->pool_size);
1988-
req_pool_size = peer->pool_size;
1975+
} else {
1976+
// peer will likely have requested less than the available range
1977+
peer->pool_size = req_pool_size;
19891978
}
1990-
// peer will likely have requested less than the available range
1991-
peer->pool_size = req_pool_size;
19921979

19931980
if (!peer->pool_size)
19941981
peer->pool_start = 0;

tests/test_mctpd.py

Lines changed: 53 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1105,10 +1105,10 @@ async def test_assign_dynamic_eid_limited_pool(nursery, dbus, sysnet):
11051105
res = await mctpd.stop_mctpd()
11061106
assert res == 0
11071107

1108-
""" Test that no pool is assigned for requested pool size from
1109-
unavailable pool space"""
1110-
async def test_assign_dynamic_unavailable_pool(nursery, dbus, sysnet):
1111-
(min_dyn_eid, max_dyn_eid) = (8, 12)
1108+
""" Test that a limited pool is assigned if we run out of space for a full
1109+
allocation"""
1110+
async def test_bridge_pool_assign_limited(nursery, dbus, sysnet):
1111+
(min_dyn_eid, max_dyn_eid) = (8, 13)
11121112
config = f"""
11131113
[bus-owner]
11141114
dynamic_eid_range = [{min_dyn_eid}, {max_dyn_eid}]
@@ -1121,8 +1121,9 @@ async def test_assign_dynamic_unavailable_pool(nursery, dbus, sysnet):
11211121
ep = mctpd.network.endpoints[0]
11221122
mctp = await mctpd_mctp_iface_obj(dbus, iface)
11231123

1124-
# Set up bridged endpoints as undiscovered EID 0
1125-
for i in range(0, 2):
1124+
# Set up bridged endpoints as undiscovered EID 0; three bridged EPs,
1125+
# which is larger than the available space
1126+
for i in range(0, 3):
11261127
br_ep = Endpoint(iface, bytes(), types=[0, 2])
11271128
ep.add_bridged_ep(br_ep)
11281129
mctpd.network.add_endpoint(br_ep)
@@ -1139,10 +1140,10 @@ async def test_assign_dynamic_unavailable_pool(nursery, dbus, sysnet):
11391140
# dynamic EID assigment for dev1
11401141
(eid, _, path, new) = await mctp.call_assign_endpoint(ep.lladdr)
11411142
assert new
1142-
# Interface should not be present for unavailable pool space
1143-
with pytest.raises(asyncdbus.errors.InterfaceNotFoundError):
1144-
bridge_obj = await dbus.get_proxy_object(MCTPD_C, path)
1145-
await bridge_obj.get_interface(MCTPD_ENDPOINT_BRIDGE_I)
1143+
assert ep.allocated_pool is not None
1144+
# we should have the largest range possible; the 8,9-9 range is smaller
1145+
# than the 11,12-13
1146+
assert ep.allocated_pool == (12, 2)
11461147

11471148
res = await mctpd.stop_mctpd()
11481149
assert res == 0
@@ -1209,3 +1210,45 @@ async def test_assign_without_bridge_range(dbus, sysnet, nursery):
12091210
assert eid == dyn_eid_min
12101211
res = await mctpd.stop_mctpd()
12111212
assert res == 0
1213+
1214+
""" Test that we can still allocate a bridge pool even though we may not have
1215+
the maximum EID range available. The bridge pool's full allocation is still
1216+
possible, since it is smaller than the configured max"""
1217+
async def test_bridge_pool_range_limited(dbus, sysnet, nursery):
1218+
# configure for:
1219+
# 10: bridge A
1220+
# 11-13: bridge A pool
1221+
# 14: bridge B
1222+
# 15-17: bridge B pool
1223+
(dyn_eid_min, dyn_eid_max) = (10, 17)
1224+
bridge_downstreams = 3
1225+
# max pool size would consume more than half of the range, so bridge B
1226+
# cannot be allocated this max
1227+
max_pool_size = 5
1228+
config = f"""
1229+
[bus-owner]
1230+
dynamic_eid_range = [{dyn_eid_min}, {dyn_eid_max}]
1231+
max_pool_size = {max_pool_size}
1232+
"""
1233+
1234+
mctpd = MctpdWrapper(dbus, sysnet, config = config)
1235+
await mctpd.start_mctpd(nursery)
1236+
1237+
iface = mctpd.system.interfaces[0]
1238+
bridges = [
1239+
Endpoint(iface, bytes([0x30])),
1240+
Endpoint(iface, bytes([0x31])),
1241+
]
1242+
for bridge in bridges:
1243+
mctpd.network.add_endpoint(bridge)
1244+
for i in range(bridge_downstreams):
1245+
bridge.add_bridged_ep(Endpoint(iface, bytes()))
1246+
1247+
iface_obj = await mctpd_mctp_iface_obj(dbus, iface)
1248+
for bridge in bridges:
1249+
(eid, _, _, _) = await iface_obj.call_assign_endpoint(bridge.lladdr)
1250+
assert bridge.allocated_pool is not None
1251+
assert bridge.allocated_pool[1] == 3
1252+
1253+
res = await mctpd.stop_mctpd()
1254+
assert res == 0

0 commit comments

Comments
 (0)