Skip to content

Commit 307298d

Browse files
committed
mctpd: allow bridge allocation with SetupEndpoint
Currently, we only allow bridge pool allocation through an AssignEndpoint call, as that is guaranteed to involve a Set Endpoint ID command, required to start the pool allocation process. LearnEndpoint is intended to never modify endpoint state, so we keep that as-is. SetupEndpoint has always been a convenience method, intended to do a LearnEndpoint if possible, or fall back to AssignEndpoint if not. Because of this, we are not making any assurances about preserving state with SetupEndpoint. With the new bridge support, the current distinction between AssignEndpoint (which will allocate a bridge pool) and SetupEndpoint (which will not) is a potential point of confusion. Instead, allow bridge allocations through SetupEndpoint. We have a new conditional path here: we try the LearnEndpoint (ie, a Get Endpoint ID, to see if we can use that EID) first, but add a new check to determine if this is a bridge EID type. Is so, we force the fallback to Set Endpoint ID, which will allow a bridge EID allocation too. Signed-off-by: Jeremy Kerr <jk@codeconstruct.com.au>
1 parent c022a72 commit 307298d

File tree

4 files changed

+85
-10
lines changed

4 files changed

+85
-10
lines changed

src/mctp-control-spec.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,28 @@ struct mctp_ctrl_resp_allocate_eids {
279279
#define MCTP_SET_EID_ACCEPTED 0x0
280280
#define MCTP_SET_EID_REJECTED 0x1
281281

282+
/* MCTP Get Endpoint ID request and response fields
283+
* See DSP0236 v1.3.0 Table 15.
284+
*/
285+
#define MCTP_GET_EID_EP_TYPE_SHIFT 4
286+
#define MCTP_GET_EID_EP_TYPE_MASK 0x03
287+
#define GET_MCTP_GET_EID_EP_TYPE(field) \
288+
(((field) >> MCTP_GET_EID_EP_TYPE_SHIFT) & MCTP_GET_EID_EP_TYPE_MASK)
289+
#define MCTP_GET_EID_EP_TYPE_EP 0
290+
#define MCTP_GET_EID_EP_TYPE_BRIDGE 1
291+
292+
#define MCTP_GET_EID_EID_TYPE_SHIFT 0
293+
#define MCTP_GET_EID_EID_TYPE_MASK 0x03
294+
#define GET_MCTP_GET_EID_EID_TYPE(field) \
295+
(((field) >> MCTP_GET_EID_EID_TYPE_SHIFT) & MCTP_GET_EID_EID_TYPE_MASK)
296+
#define MCTP_GET_EID_EID_TYPE_DYNAMIC 0
297+
/* Static EID is supported, may or may not match current */
298+
#define MCTP_GET_EID_EID_TYPE_STATIC 1
299+
/* Current eid is the same as static */
300+
#define MCTP_GET_EID_EID_TYPE_STATIC_SAME 2
301+
/* Current eid is different from static */
302+
#define MCTP_GET_EID_EID_TYPE_STATIC_DIFFERENT 3
303+
282304
#define MCTP_EID_ALLOCATION_STATUS_SHIFT 0x0
283305
#define MCTP_EID_ALLOCATION_STATUS_MASK 0x3
284306
#define SET_MCTP_EID_ALLOCATION_STATUS(status) \

src/mctpd.c

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2383,15 +2383,27 @@ static int method_setup_endpoint(sd_bus_message *call, void *data,
23832383
/* Get Endpoint ID */
23842384
rc = get_endpoint_peer(ctx, berr, dest, &peer, NULL);
23852385
if (rc >= 0 && peer) {
2386-
if (ctx->verbose)
2386+
uint8_t ep_type = GET_MCTP_GET_EID_EP_TYPE(peer->endpoint_type);
2387+
if (ep_type == MCTP_GET_EID_EP_TYPE_BRIDGE) {
23872388
fprintf(stderr,
2388-
"%s returning from get_endpoint_peer %s\n",
2389-
__func__, peer_tostr(peer));
2390-
peer_path = path_from_peer(peer);
2391-
if (!peer_path)
2392-
goto err;
2393-
return sd_bus_reply_method_return(call, "yisb", peer->eid,
2394-
peer->net, peer_path, 0);
2389+
"SetupEndpoint, eid %d: Get EID "
2390+
"response indicated a bridge with existing "
2391+
"EID, reassigning\n",
2392+
peer->eid);
2393+
remove_peer(peer);
2394+
peer = NULL;
2395+
} else {
2396+
if (ctx->verbose)
2397+
fprintf(stderr,
2398+
"%s returning from get_endpoint_peer %s\n",
2399+
__func__, peer_tostr(peer));
2400+
peer_path = path_from_peer(peer);
2401+
if (!peer_path)
2402+
goto err;
2403+
return sd_bus_reply_method_return(call, "yisb",
2404+
peer->eid, peer->net,
2405+
peer_path, 0);
2406+
}
23952407
} else if (rc == -EEXIST) {
23962408
// EEXISTS is OK, we will assign a new eid instead.
23972409
} else if (rc < 0) {
@@ -2400,10 +2412,13 @@ static int method_setup_endpoint(sd_bus_message *call, void *data,
24002412
}
24012413

24022414
/* Set Endpoint ID */
2403-
rc = endpoint_assign_eid(ctx, berr, dest, &peer, 0, false);
2415+
rc = endpoint_assign_eid(ctx, berr, dest, &peer, 0, true);
24042416
if (rc < 0)
24052417
goto err;
24062418

2419+
if (peer->pool_size)
2420+
endpoint_allocate_eids(peer);
2421+
24072422
peer_path = path_from_peer(peer);
24082423
if (!peer_path)
24092424
goto err;
@@ -2582,6 +2597,14 @@ static int method_learn_endpoint(sd_bus_message *call, void *data,
25822597
if (!peer)
25832598
return sd_bus_reply_method_return(call, "yisb", 0, 0, "", 0);
25842599

2600+
uint8_t ep_type = GET_MCTP_GET_EID_EP_TYPE(peer->endpoint_type);
2601+
if (ep_type == MCTP_GET_EID_EP_TYPE_BRIDGE) {
2602+
warnx("LearnEndpoint, eid %d: Get EID response "
2603+
"indicated a bridge with existing EID, "
2604+
"but no pool is assignable",
2605+
peer->eid);
2606+
}
2607+
25852608
peer_path = path_from_peer(peer);
25862609
if (!peer_path)
25872610
goto err;

tests/mctpenv/__init__.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,10 @@ async def handle_mctp_control(self, sock, addr, data):
361361

362362
elif opcode == 2:
363363
# Get Endpoint ID
364-
data = bytes(hdr + [0x00, self.eid, 0x00, 0x00])
364+
ep_type = 0
365+
if len(self.bridged_eps) > 0:
366+
ep_type = 0x1 << 4
367+
data = bytes(hdr + [0x00, self.eid, ep_type, 0x00])
365368
await sock.send(raddr, data)
366369

367370
elif opcode == 3:

tests/test_mctpd.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1042,6 +1042,33 @@ async def test_bridge_ep_conflict_setup(dbus, mctpd):
10421042
(eid, _, _, _) = await mctp.call_setup_endpoint(dev.lladdr)
10431043
assert eid not in pool_range
10441044

1045+
""" Test that mctpd will reassign a bridge endpoints (pre-configured) EID
1046+
if necessary to satisfy the bridge pool allocation"""
1047+
async def test_bridge_setup_reassign(dbus, mctpd):
1048+
iface = mctpd.system.interfaces[0]
1049+
mctp = await mctpd_mctp_iface_obj(dbus, iface)
1050+
1051+
# ep: regular endpoint, will conflict with a bridge pool
1052+
ep = mctpd.network.endpoints[0]
1053+
static_eid = 10
1054+
(eid, _, _, _) = await mctp.call_assign_endpoint_static(
1055+
ep.lladdr,
1056+
static_eid
1057+
)
1058+
1059+
assert eid == static_eid
1060+
1061+
# br: our bridge
1062+
conflict_eid = 9
1063+
br = Endpoint(iface, bytes([ep.lladdr[0] + 1]), eid=conflict_eid)
1064+
br.add_bridged_ep(Endpoint(iface, bytes()))
1065+
mctpd.network.add_endpoint(br)
1066+
1067+
(eid, _, _, _) = await mctp.call_setup_endpoint(br.lladdr)
1068+
assert eid != conflict_eid
1069+
assert br.allocated_pool is not None
1070+
assert br.allocated_pool[0] == eid + 1
1071+
10451072
""" Test that we truncate the requested pool size to
10461073
the max_pool_size config """
10471074
async def test_assign_dynamic_eid_limited_pool(nursery, dbus, sysnet):

0 commit comments

Comments
 (0)