Skip to content

Commit da464ea

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 1d393b5 commit da464ea

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
@@ -2264,6 +2264,34 @@ static int allocate_eid(struct ctx *ctx, struct net *net,
22642264
return -1;
22652265
}
22662266

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

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

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

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

0 commit comments

Comments
 (0)