Skip to content

Commit 7ae64b2

Browse files
Implement ALLOCATE_ENDPOINT_ID support for bridges
Add implementation for the MCTP ALLOCATE_ENDPOINT_ID control command to enable bridges to allocate EID pools for downstream endpoints. - Add endpoint_send_allocate_endpoint_id() for sending allocation requests - Update gateway route for downstream EIDs - Integrate allocation of dynamic eid for downstream endpoints of bridge with AssignEndpoint d-bus method Signed-off-by: Faizan Ali <[email protected]>
1 parent 9e1fc7c commit 7ae64b2

File tree

1 file changed

+149
-0
lines changed

1 file changed

+149
-0
lines changed

src/mctpd.c

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,7 @@ static int del_local_eid(struct ctx *ctx, uint32_t net, int eid);
253253
static int add_net(struct ctx *ctx, uint32_t net);
254254
static void del_net(struct net *net);
255255
static int add_interface(struct ctx *ctx, int ifindex);
256+
static int endpoint_allocate_eid(struct peer *peer);
256257

257258
static const sd_bus_vtable bus_endpoint_obmc_vtable[];
258259
static const sd_bus_vtable bus_endpoint_cc_vtable[];
@@ -2251,6 +2252,18 @@ static int method_assign_endpoint(sd_bus_message *call, void *data,
22512252

22522253
if (peer->pool_size > 0) {
22532254
// Call for Allocate EndpointID
2255+
rc = endpoint_allocate_eid(peer);
2256+
if (rc < 0) {
2257+
warnx("Failed to allocate downstream EIDs");
2258+
} else {
2259+
if (peer->ctx->verbose) {
2260+
fprintf(stderr,
2261+
"Downstream EIDs assigned from %d to %d : pool size %d\n",
2262+
peer->pool_start,
2263+
peer->pool_start + peer->pool_size - 1,
2264+
peer->pool_size);
2265+
}
2266+
}
22542267
}
22552268

22562269
return sd_bus_reply_method_return(call, "yisb", peer->eid, peer->net,
@@ -2473,6 +2486,20 @@ static int peer_route_update(struct peer *peer, uint16_t type)
24732486
return mctp_nl_route_add(peer->ctx->nl, peer->eid, 0,
24742487
peer->phys.ifindex, NULL, peer->mtu);
24752488
} else if (type == RTM_DELROUTE) {
2489+
if (peer->pool_size > 0) {
2490+
int rc = 0;
2491+
struct mctp_fq_addr gw_addr = { 0 };
2492+
gw_addr.net = peer->net;
2493+
gw_addr.eid = peer->eid;
2494+
rc = mctp_nl_route_del(peer->ctx->nl, peer->pool_start,
2495+
peer->pool_size - 1,
2496+
peer->phys.ifindex, &gw_addr);
2497+
if (rc < 0)
2498+
warnx("failed to delete route for peer pool eids %d-%d %s",
2499+
peer->pool_start,
2500+
peer->pool_start + peer->pool_size - 1,
2501+
strerror(-rc));
2502+
}
24762503
return mctp_nl_route_del(peer->ctx->nl, peer->eid, 0,
24772504
peer->phys.ifindex, NULL);
24782505
}
@@ -4138,6 +4165,128 @@ static void free_config(struct ctx *ctx)
41384165
free(ctx->config_filename);
41394166
}
41404167

4168+
static int endpoint_send_allocate_endpoint_id(struct peer *peer,
4169+
mctp_eid_t eid_start,
4170+
uint8_t eid_pool_size,
4171+
mctp_ctrl_cmd_alloc_eid_op oper,
4172+
uint8_t *allocated_pool_size,
4173+
mctp_eid_t *allocated_pool_start)
4174+
{
4175+
struct sockaddr_mctp_ext addr;
4176+
struct mctp_ctrl_cmd_alloc_eid req = { 0 };
4177+
struct mctp_ctrl_resp_alloc_eid *resp = NULL;
4178+
uint8_t *buf = NULL;
4179+
size_t buf_size;
4180+
uint8_t iid, stat;
4181+
int rc;
4182+
4183+
iid = mctp_next_iid(peer->ctx);
4184+
req.ctrl_hdr.rq_dgram_inst = RQDI_REQ | iid;
4185+
req.ctrl_hdr.command_code = MCTP_CTRL_CMD_ALLOCATE_ENDPOINT_IDS;
4186+
req.alloc_eid_op = (uint8_t)(oper & 0x03);
4187+
req.pool_size = eid_pool_size;
4188+
req.start_eid = eid_start;
4189+
rc = endpoint_query_peer(peer, MCTP_CTRL_HDR_MSG_TYPE, &req,
4190+
sizeof(req), &buf, &buf_size, &addr);
4191+
if (rc < 0)
4192+
goto out;
4193+
4194+
rc = mctp_ctrl_validate_response(buf, buf_size, sizeof(*resp),
4195+
peer_tostr_short(peer), iid,
4196+
MCTP_CTRL_CMD_ALLOCATE_ENDPOINT_IDS);
4197+
4198+
if (rc)
4199+
goto out;
4200+
4201+
resp = (void *)buf;
4202+
if (!resp) {
4203+
warnx("%s Invalid response Buffer\n", __func__);
4204+
return -ENOMEM;
4205+
}
4206+
4207+
stat = resp->status & 0x03;
4208+
if (stat == 0x00) {
4209+
if (peer->ctx->verbose) {
4210+
fprintf(stderr, "%s Allocation Accepted \n", __func__);
4211+
}
4212+
if (resp->eid_pool_size != eid_pool_size ||
4213+
resp->eid_set != eid_start) {
4214+
warnx("Unexpected pool start %d pool size %d",
4215+
resp->eid_set, resp->eid_pool_size);
4216+
rc = -1;
4217+
goto out;
4218+
}
4219+
} else {
4220+
if (stat == 0x1)
4221+
warnx("%s Allocation was rejected: already allocated by other bus"
4222+
" pool start %d, pool size %d",
4223+
__func__, resp->eid_pool_size, resp->eid_set);
4224+
rc = -1;
4225+
goto out;
4226+
}
4227+
4228+
*allocated_pool_size = resp->eid_pool_size;
4229+
*allocated_pool_start = resp->eid_set;
4230+
if (peer->ctx->verbose) {
4231+
fprintf(stderr,
4232+
"%s Allocated size of %d, starting from EID %d\n",
4233+
__func__, resp->eid_pool_size, resp->eid_set);
4234+
}
4235+
4236+
out:
4237+
free(buf);
4238+
return rc;
4239+
}
4240+
4241+
static int endpoint_allocate_eid(struct peer *peer)
4242+
{
4243+
uint8_t allocated_pool_size = 0;
4244+
mctp_eid_t allocated_pool_start = 0;
4245+
int rc = 0;
4246+
4247+
/* Find pool sized contiguous unused eids to allocate on the bridge. */
4248+
if (peer->pool_start >= eid_alloc_max || peer->pool_start <= 0) {
4249+
warnx("%s Invalid Pool start %d", __func__, peer->pool_start);
4250+
return -1;
4251+
}
4252+
rc = endpoint_send_allocate_endpoint_id(
4253+
peer, peer->pool_start, peer->pool_size,
4254+
mctp_ctrl_cmd_alloc_eid_alloc_eid, &allocated_pool_size,
4255+
&allocated_pool_start);
4256+
if (rc) {
4257+
//reset peer pool
4258+
peer->pool_size = 0;
4259+
peer->pool_start = 0;
4260+
} else {
4261+
peer->pool_size = allocated_pool_size;
4262+
peer->pool_start = allocated_pool_start;
4263+
4264+
// add Gateway route for all Bridge's downstream eids
4265+
if (peer->pool_size > 0) {
4266+
struct mctp_fq_addr gw_addr = { 0 };
4267+
gw_addr.net = peer->net;
4268+
gw_addr.eid = peer->eid;
4269+
rc = mctp_nl_route_add(peer->ctx->nl, peer->pool_start,
4270+
peer->pool_size - 1,
4271+
peer->phys.ifindex, &gw_addr,
4272+
peer->mtu);
4273+
if (rc < 0) {
4274+
warnx("Failed to add Gateway route for EID %d: %s",
4275+
gw_addr.eid, strerror(-rc));
4276+
// If the route already exists, continue polling
4277+
if (rc != -EEXIST) {
4278+
return rc;
4279+
} else {
4280+
rc = 0;
4281+
}
4282+
}
4283+
// TODO: Polling logic for downstream EID
4284+
}
4285+
}
4286+
4287+
return rc;
4288+
}
4289+
41414290
int main(int argc, char **argv)
41424291
{
41434292
struct ctx ctxi = { 0 }, *ctx = &ctxi;

0 commit comments

Comments
 (0)