Skip to content

Commit 6f47f6e

Browse files
committed
mctpd: add AssignBridgeStatic method
Add AssignBridgeStatic method to assign static EID with bridge pool allocation. Tested: ``` root@bmc:~# busctl call au.com.codeconstruct.MCTP1 /au/com/codeconstruct/mctp1/interfaces/mcu1u2u1u4u1 au.com.codeconstruct.MCTP.BusOwner1 AssignBridgeStatic ayyyy 0 30 31 5 yisb 30 1 "/au/com/codeconstruct/mctp1/networks/1/endpoints/30" true root@bmc:~# busctl introspect au.com.codeconstruct.MCTP1 /au/com/codeconstruct/mctp1/networks/1/endpoints/30 NAME TYPE SIGNATURE RESULT/VALUE FLAGS au.com.codeconstruct.MCTP.Bridge1 interface - - - .PoolEnd property y 35 const .PoolStart property y 31 const au.com.codeconstruct.MCTP.Endpoint1 interface - - - .Recover method - - - .Remove method - - - .SetMTU method u - - .Connectivity property s "Available" emits-change org.freedesktop.DBus.Introspectable interface - - - .Introspect method - s - org.freedesktop.DBus.Peer interface - - - .GetMachineId method - s - .Ping method - - - org.freedesktop.DBus.Properties interface - - - .Get method ss v - .GetAll method s a{sv} - .Set method ssv - - .PropertiesChanged signal sa{sv}as - - xyz.openbmc_project.Common.UUID interface - - - .UUID property s "8b7e3d86-5fa5-298c-a9d6-a2d5d4baa6fa" const xyz.openbmc_project.MCTP.Endpoint interface - - - .EID property y 30 const .NetworkId property u 1 const .SupportedMessageTypes property ay 4 1 5 126 127 const .VendorDefinedMessageTypes property a(yvq) 0 const ``` Signed-off-by: Potin Lai <potin.lai@quantatw.com>
1 parent c7a27cf commit 6f47f6e

2 files changed

Lines changed: 241 additions & 0 deletions

File tree

docs/mctpd.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,22 @@ This call will fail if the endpoint already has an EID, and that EID is
203203
different from `static-EID`, or if `static-EID` is already assigned to another
204204
endpoint.
205205

206+
#### `.AssignBridgeStatic`: `ayyyy``yisb`
207+
208+
Similar to AssignEndpointStatic, but takes an additional pool-size and
209+
pool-start-EID argument:
210+
211+
```
212+
AssignBridgeStatic <hwaddr> <static-EID> <pool-start-EID> <pool-size>
213+
```
214+
215+
`<pool-start-EID>`: The starting EID for the range of EIDs being allocated.
216+
This EID must be contiguous with the bridge’s own EID.
217+
218+
`<pool-size>`: The number of EIDs to be allocated to the bridge's EID pool.
219+
220+
This method performs a static assignment with bridge EID pool allocation.
221+
206222
#### `.LearnEndpoint`: `ay``yisb`
207223

208224
Like SetupEndpoint but will not assign EIDs, will only query endpoints for a

src/mctpd.c

Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2265,6 +2265,34 @@ static int allocate_eid(struct ctx *ctx, struct net *net,
22652265
return -1;
22662266
}
22672267

2268+
/**
2269+
* Validate EID pool allocation for an MCTP bridge.
2270+
*
2271+
* Ensures the pool starts at bridge_eid + 1 and verifies that neither the
2272+
* bridge EID nor the pool range conflicts with existing peer allocations in
2273+
* the network.
2274+
*
2275+
* @return 0 on success, -1 on failure.
2276+
*/
2277+
static int check_bridge_eid_alloc(struct net *net, mctp_eid_t bridge_eid,
2278+
mctp_eid_t pool_start, unsigned int pool_size)
2279+
{
2280+
mctp_eid_t eid;
2281+
2282+
if (pool_start != (bridge_eid + 1))
2283+
return -1;
2284+
2285+
if (net->peers[bridge_eid])
2286+
return -1;
2287+
2288+
for (eid = pool_start; eid < (pool_start + pool_size); eid++) {
2289+
if (net->peers[eid])
2290+
return -1;
2291+
}
2292+
2293+
return 0;
2294+
}
2295+
22682296
static int endpoint_assign_eid(struct ctx *ctx, sd_bus_error *berr,
22692297
const dest_phys *dest, struct peer **ret_peer,
22702298
mctp_eid_t static_eid, bool assign_bridge)
@@ -2378,6 +2406,100 @@ static int endpoint_assign_eid(struct ctx *ctx, sd_bus_error *berr,
23782406
return 0;
23792407
}
23802408

2409+
static int
2410+
endpoint_assign_bridge_static_eid(struct ctx *ctx, sd_bus_error *berr,
2411+
const dest_phys *dest, struct peer **ret_peer,
2412+
mctp_eid_t static_eid, mctp_eid_t pool_start,
2413+
uint8_t pool_size)
2414+
{
2415+
struct net *n = NULL;
2416+
struct peer *peer = NULL;
2417+
uint8_t req_pool_size;
2418+
uint32_t net;
2419+
int rc;
2420+
2421+
net = mctp_nl_net_byindex(ctx->nl, dest->ifindex);
2422+
if (!net) {
2423+
bug_warn("No net known for ifindex %d", dest->ifindex);
2424+
return -EPROTO;
2425+
}
2426+
2427+
n = lookup_net(ctx, net);
2428+
if (!n) {
2429+
bug_warn("Unknown net %d", net);
2430+
return -EPROTO;
2431+
}
2432+
2433+
rc = check_bridge_eid_alloc(n, static_eid, pool_start, pool_size);
2434+
if (rc) {
2435+
warnx("Cannot allocate static EID (+pool %d) on net %d for %s",
2436+
pool_size, net, dest_phys_tostr(dest));
2437+
sd_bus_error_setf(berr, SD_BUS_ERROR_FAILED, "Ran out of EIDs");
2438+
return -EADDRNOTAVAIL;
2439+
}
2440+
2441+
rc = add_peer(ctx, dest, static_eid, net, &peer, false);
2442+
if (rc < 0)
2443+
return rc;
2444+
2445+
peer->pool_size = pool_size;
2446+
if (peer->pool_size)
2447+
peer->pool_start = pool_start;
2448+
2449+
add_peer_route(peer);
2450+
2451+
rc = endpoint_send_set_endpoint_id(peer, &static_eid, &req_pool_size);
2452+
if (rc == -ECONNREFUSED)
2453+
sd_bus_error_setf(
2454+
berr, SD_BUS_ERROR_FAILED,
2455+
"Endpoint returned failure to Set Endpoint ID");
2456+
2457+
if (rc < 0) {
2458+
// we have not yet created the pool route, reset here so that
2459+
// remove_peer() does not attempt to remove it
2460+
peer->pool_size = 0;
2461+
peer->pool_start = 0;
2462+
remove_peer(peer);
2463+
return rc;
2464+
}
2465+
2466+
if (req_pool_size > peer->pool_size) {
2467+
warnx("EID %d: requested pool size (%d) > pool size available (%d), limiting.",
2468+
peer->eid, req_pool_size, peer->pool_size);
2469+
} else {
2470+
// peer will likely have requested less than the available range
2471+
peer->pool_size = req_pool_size;
2472+
}
2473+
2474+
if (!peer->pool_size)
2475+
peer->pool_start = 0;
2476+
2477+
if (static_eid != peer->eid) {
2478+
// avoid allocation for any different EID in response
2479+
warnx("Mismatch of requested from received EID, resetting the pool");
2480+
peer->pool_size = 0;
2481+
peer->pool_start = 0;
2482+
rc = change_peer_eid(peer, static_eid);
2483+
if (rc == -EEXIST) {
2484+
sd_bus_error_setf(
2485+
berr, SD_BUS_ERROR_FAILED,
2486+
"Endpoint requested EID %d instead of assigned %d, already used",
2487+
static_eid, peer->eid);
2488+
}
2489+
if (rc < 0) {
2490+
remove_peer(peer);
2491+
return rc;
2492+
}
2493+
}
2494+
2495+
rc = setup_added_peer(peer);
2496+
if (rc < 0)
2497+
return rc;
2498+
*ret_peer = peer;
2499+
2500+
return 0;
2501+
}
2502+
23812503
/* Populates a sd_bus_error based on mctpd's convention for error codes.
23822504
* Does nothing if berr is already set.
23832505
*/
@@ -3071,6 +3193,95 @@ static int method_assign_endpoint_static(sd_bus_message *call, void *data,
30713193
return rc;
30723194
}
30733195

3196+
static int method_assign_bridge_static(sd_bus_message *call, void *data,
3197+
sd_bus_error *berr)
3198+
{
3199+
dest_phys desti, *dest = &desti;
3200+
const char *peer_path = NULL;
3201+
struct peer *peer = NULL;
3202+
struct link *link = data;
3203+
struct ctx *ctx = link->ctx;
3204+
uint8_t eid;
3205+
uint8_t pool_start;
3206+
uint8_t pool_size;
3207+
bool new = true;
3208+
int rc;
3209+
3210+
dest->ifindex = link->ifindex;
3211+
if (dest->ifindex <= 0)
3212+
return sd_bus_error_setf(berr, SD_BUS_ERROR_INVALID_ARGS,
3213+
"Unknown MCTP interface");
3214+
3215+
rc = message_read_hwaddr(call, dest);
3216+
if (rc < 0)
3217+
goto err;
3218+
3219+
rc = sd_bus_message_read(call, "y", &eid);
3220+
if (rc < 0)
3221+
goto err;
3222+
3223+
rc = sd_bus_message_read(call, "y", &pool_start);
3224+
if (rc < 0)
3225+
goto err;
3226+
3227+
rc = sd_bus_message_read(call, "y", &pool_size);
3228+
if (rc < 0)
3229+
goto err;
3230+
3231+
rc = validate_dest_phys(ctx, dest);
3232+
if (rc < 0)
3233+
return sd_bus_error_setf(berr, SD_BUS_ERROR_INVALID_ARGS,
3234+
"Bad physaddr");
3235+
3236+
if (pool_start != (eid + 1)) {
3237+
return sd_bus_error_setf(berr, SD_BUS_ERROR_INVALID_ARGS,
3238+
"Bad pool start EID");
3239+
}
3240+
3241+
peer = find_peer_by_phys(ctx, dest);
3242+
if (peer) {
3243+
if (eid && peer->eid == eid && pool_size == peer->pool_size) {
3244+
new = false;
3245+
goto out;
3246+
}
3247+
3248+
remove_peer(peer);
3249+
peer = NULL;
3250+
} else {
3251+
uint32_t netid;
3252+
3253+
// is the requested EID already in use? if so, reject
3254+
netid = mctp_nl_net_byindex(ctx->nl, dest->ifindex);
3255+
peer = find_peer_by_addr(ctx, eid, netid);
3256+
if (peer) {
3257+
return sd_bus_error_setf(berr,
3258+
SD_BUS_ERROR_INVALID_ARGS,
3259+
"Address in use");
3260+
}
3261+
}
3262+
3263+
rc = endpoint_assign_bridge_static_eid(ctx, berr, dest, &peer, eid,
3264+
pool_start, pool_size);
3265+
if (rc < 0) {
3266+
goto err;
3267+
}
3268+
3269+
if (peer->pool_size > 0)
3270+
endpoint_allocate_eids(peer);
3271+
3272+
out:
3273+
peer_path = path_from_peer(peer);
3274+
if (!peer_path)
3275+
goto err;
3276+
3277+
return sd_bus_reply_method_return(call, "yisb", peer->eid, peer->net,
3278+
peer_path, new);
3279+
3280+
err:
3281+
set_berr(ctx, rc, berr);
3282+
return rc;
3283+
}
3284+
30743285
static int method_learn_endpoint(sd_bus_message *call, void *data,
30753286
sd_bus_error *berr)
30763287
{
@@ -4056,6 +4267,20 @@ static const sd_bus_vtable bus_link_owner_vtable[] = {
40564267
method_assign_endpoint_static,
40574268
0),
40584269

4270+
SD_BUS_METHOD_WITH_NAMES("AssignBridgeStatic",
4271+
"ayyyy",
4272+
SD_BUS_PARAM(physaddr)
4273+
SD_BUS_PARAM(eid)
4274+
SD_BUS_PARAM(poolstart)
4275+
SD_BUS_PARAM(poolsize),
4276+
"yisb",
4277+
SD_BUS_PARAM(eid)
4278+
SD_BUS_PARAM(net)
4279+
SD_BUS_PARAM(path)
4280+
SD_BUS_PARAM(new),
4281+
method_assign_bridge_static,
4282+
0),
4283+
40594284
SD_BUS_METHOD_WITH_NAMES("LearnEndpoint",
40604285
"ay",
40614286
SD_BUS_PARAM(physaddr),

0 commit comments

Comments
 (0)