Skip to content

Commit 46070f6

Browse files
committed
mctpd: allow configurable dynamic address ranges
As proposed in #94, add a new configuration option for specifying a global dynamic EID range: # dynamic EID range: a 2-element array of min and max (inclusive) EID values. dynamic_eid_range = [8, 254] We use this to confine the any dynamic allocations; EIDs of local interfaces and statically-defined allocations may fall outside of this range. Fixes: #94 Signed-off-by: Jeremy Kerr <[email protected]>
1 parent 7248836 commit 46070f6

File tree

5 files changed

+137
-9
lines changed

5 files changed

+137
-9
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
2020

2121
3. Added documentation for `mctpd.conf` settings
2222

23+
4. `mctpd`'s dynamic EID range is now configurable
24+
2325
## [2.2] - 2025-07-28
2426

2527
### Fixed

conf/mctpd.conf

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,8 @@ message_timeout_ms = 30
1111

1212
# bus-owner configuration
1313
[bus-owner]
14-
max_pool_size = 15
1514

15+
# dynamic EID range: a 2-element array of min and max (inclusive) EID values.
16+
dynamic_eid_range = [8, 254]
17+
18+
max_pool_size = 15

docs/mctpd.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,20 @@ uuid = "21f0f554-7f7c-4211-9ca1-6d0f000ea9e7"
276276

277277
This section affects behaviour when `mctpd` is running in bus owner mode
278278

279+
#### `dynamic_eid_range`: Range for dynamic EID allocations
280+
281+
* type: array of integers, 2 elements
282+
* default: `[ 8, 254 ]`
283+
284+
This setting specifies the range of dynamic EIDs that `mctpd` will allocate
285+
new peers' EIDs from. Values are inclusive.
286+
287+
Local interface EIDs and statically-allocated EIDs may fall outside this range;
288+
it is only used when a peer needs a new dynamic address.
289+
290+
The default value makes the entire MCTP EID address space available for dynamic
291+
allocations.
292+
279293
#### `max_pool_size`: Maximum peer allocation pool size
280294

281295
* type: integer

src/mctpd.c

Lines changed: 59 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@ static const char *mctpd_appid = "67369c05-4b97-4b7e-be72-65cfd8639f10";
5757

5858
static const char *conf_file_default = MCTPD_CONF_FILE_DEFAULT;
5959

60-
static mctp_eid_t eid_alloc_min = 0x08;
61-
static mctp_eid_t eid_alloc_max = 0xfe;
60+
static const mctp_eid_t eid_alloc_min = 0x08;
61+
static const mctp_eid_t eid_alloc_max = 0xfe;
6262

6363
// arbitrary sanity
6464
static size_t MAX_PEER_SIZE = 1000000;
@@ -206,6 +206,10 @@ struct ctx {
206206
struct net **nets;
207207
size_t num_nets;
208208

209+
// the range we allocate any dynamic EIDs from
210+
mctp_eid_t dyn_eid_min;
211+
mctp_eid_t dyn_eid_max;
212+
209213
// Timeout in usecs for a MCTP response
210214
uint64_t mctp_timeout;
211215

@@ -1667,16 +1671,16 @@ static int endpoint_assign_eid(struct ctx *ctx, sd_bus_error *berr,
16671671

16681672
new_eid = static_eid;
16691673
} else {
1670-
/* Find an unused EID */
1671-
for (e = eid_alloc_min; e <= eid_alloc_max; e++) {
1674+
/* Find an unused dynamic EID */
1675+
for (e = ctx->dyn_eid_min; e <= ctx->dyn_eid_max; e++) {
16721676
if (n->peers[e])
16731677
continue;
16741678
rc = add_peer(ctx, dest, e, net, &peer);
16751679
if (rc < 0)
16761680
return rc;
16771681
break;
16781682
}
1679-
if (e > eid_alloc_max) {
1683+
if (e > ctx->dyn_eid_max) {
16801684
warnx("Ran out of EIDs for net %d, allocating %s", net,
16811685
dest_phys_tostr(dest));
16821686
sd_bus_error_setf(berr, SD_BUS_ERROR_FAILED,
@@ -3935,21 +3939,67 @@ static int parse_config_mctp(struct ctx *ctx, toml_table_t *mctp_tab)
39353939
return 0;
39363940
}
39373941

3942+
static int parse_config_dyn_eid_range(struct ctx *ctx, toml_array_t *arr)
3943+
{
3944+
int sz = toml_array_nelem(arr);
3945+
toml_datum_t min_val, max_val;
3946+
3947+
if (sz < 2) {
3948+
warnx("dynamic_eid_range has invalid format - needs two elements");
3949+
return -1;
3950+
}
3951+
if (sz > 2) {
3952+
warnx("dynamic_eid_range: ignoring extra (> 2) elements");
3953+
}
3954+
3955+
min_val = toml_int_at(arr, 0);
3956+
max_val = toml_int_at(arr, 1);
3957+
3958+
if (!min_val.ok || !max_val.ok) {
3959+
warnx("dynamic_eid_range: invalid range data");
3960+
return -1;
3961+
}
3962+
3963+
if (min_val.u.i < eid_alloc_min || min_val.u.i > eid_alloc_max) {
3964+
warnx("dynamic_eid_range: start address is invalid");
3965+
return -1;
3966+
}
3967+
3968+
if (max_val.u.i < eid_alloc_min || max_val.u.i > eid_alloc_max ||
3969+
max_val.u.i < min_val.u.i) {
3970+
warnx("dynamic_eid_range: end address is invalid");
3971+
return -1;
3972+
}
3973+
3974+
ctx->dyn_eid_max = max_val.u.i;
3975+
ctx->dyn_eid_min = min_val.u.i;
3976+
return 0;
3977+
}
3978+
39383979
static int parse_config_bus_owner(struct ctx *ctx, toml_table_t *bus_owner)
39393980
{
3981+
toml_array_t *array;
39403982
toml_datum_t val;
3983+
int rc;
39413984

39423985
val = toml_int_in(bus_owner, "max_pool_size");
39433986
if (val.ok) {
39443987
int64_t i = val.u.i;
3945-
if (i <= 0 || i > (eid_alloc_max - eid_alloc_min)) {
3988+
if (i <= 0 || i > (ctx->dyn_eid_max - ctx->dyn_eid_min)) {
39463989
warnx("invalid max_pool_size value (must be 1-%d)",
3947-
eid_alloc_max - eid_alloc_min);
3990+
ctx->dyn_eid_max - ctx->dyn_eid_min);
39483991
return -1;
39493992
}
39503993
ctx->max_pool_size = i;
39513994
}
39523995

3996+
array = toml_array_in(bus_owner, "dynamic_eid_range");
3997+
if (array) {
3998+
rc = parse_config_dyn_eid_range(ctx, array);
3999+
if (rc)
4000+
return rc;
4001+
}
4002+
39534003
return 0;
39544004
}
39554005

@@ -4021,6 +4071,8 @@ static void setup_config_defaults(struct ctx *ctx)
40214071
ctx->mctp_timeout = 250000; // 250ms
40224072
ctx->default_role = ENDPOINT_ROLE_BUS_OWNER;
40234073
ctx->max_pool_size = 15;
4074+
ctx->dyn_eid_min = eid_alloc_min;
4075+
ctx->dyn_eid_max = eid_alloc_max;
40244076
}
40254077

40264078
static void free_config(struct ctx *ctx)

tests/test_mctpd.py

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
mctpd_mctp_endpoint_common_obj,
1010
mctpd_mctp_endpoint_control_obj
1111
)
12-
from mctpenv import Endpoint, MCTPSockAddr, MCTPControlCommand
12+
from mctpenv import Endpoint, MCTPSockAddr, MCTPControlCommand, MctpdWrapper
1313

1414
# DBus constant symbol suffixes:
1515
#
@@ -869,3 +869,60 @@ async def test_interface_rename_with_peers(dbus, mctpd):
869869
# ensure the endpoint persists after rename
870870
ep_obj = await dbus.get_proxy_object(MCTPD_C, ep_path)
871871
assert ep_obj is not None
872+
873+
""" Test that we use the minimum EID from the dynamic_eid_range config """
874+
async def test_config_dyn_eid_range_min(nursery, dbus, sysnet):
875+
(min_dyn_eid, max_dyn_eid) = (20, 254)
876+
config = f"""
877+
[bus-owner]
878+
dynamic_eid_range = [{min_dyn_eid}, {max_dyn_eid}]
879+
"""
880+
881+
# since we're specifying per-test config, we create the wrapper directly
882+
# rather than using the fixture.
883+
mctpd = MctpdWrapper(dbus, sysnet, config = config)
884+
await mctpd.start_mctpd(nursery)
885+
886+
iface = mctpd.system.interfaces[0]
887+
ep = mctpd.network.endpoints[0]
888+
889+
mctp = await mctpd_mctp_iface_obj(dbus, iface)
890+
(eid, net, path, new) = await mctp.call_setup_endpoint(ep.lladdr)
891+
assert eid == min_dyn_eid
892+
assert ep.eid == eid
893+
894+
res = await mctpd.stop_mctpd()
895+
assert res == 0
896+
897+
""" Test that we use the maximum EID from the dynamic_eid_range config """
898+
async def test_config_dyn_eid_range_max(nursery, dbus, sysnet):
899+
(min_dyn_eid, max_dyn_eid) = (20, 21)
900+
config = f"""
901+
[bus-owner]
902+
dynamic_eid_range = [{min_dyn_eid}, {max_dyn_eid}]
903+
"""
904+
905+
mctpd = MctpdWrapper(dbus, sysnet, config = config)
906+
await mctpd.start_mctpd(nursery)
907+
908+
iface = mctpd.system.interfaces[0]
909+
mctp = await mctpd_mctp_iface_obj(dbus, iface)
910+
911+
mctpd.network.add_endpoint(Endpoint(iface, bytes([0x01]), types = [0, 1]))
912+
mctpd.network.add_endpoint(Endpoint(iface, bytes([0x02]), types = [0, 1]))
913+
914+
for i in range(0, 2):
915+
ep = mctpd.network.endpoints[i]
916+
(eid, net, path, new) = await mctp.call_setup_endpoint(ep.lladdr)
917+
assert eid >= 20 and eid <= 21
918+
919+
# we should have run out of EIDs
920+
with pytest.raises(asyncdbus.errors.DBusError) as ex:
921+
ep = mctpd.network.endpoints[2]
922+
(eid, net, path, new) = await mctp.call_setup_endpoint(ep.lladdr)
923+
924+
assert str(ex.value) == "Ran out of EIDs"
925+
assert mctpd.network.endpoints[2].eid == 0
926+
927+
res = await mctpd.stop_mctpd()
928+
assert res == 0

0 commit comments

Comments
 (0)