mctp: fix mctp bridge endpoints issues
We need some patches to fix issues related to mctp bridge endpoints:
- https://github.com/CodeConstruct/mctp/issues/112
- https://github.com/CodeConstruct/mctp/issues/115
Tested:
https://paste.googleplex.com/4664789641068544
Fusion-Link:
platform5: http://fusion2/c9890165-129b-4c1b-b7d9-4f089a9c7b25
platform11: http://fusion2/89b6bf5a-d09f-3c6e-9d5d-643e51e02a15
platform15: http://fusion2/ef596b9f-c54c-3413-90fc-9fd3446d0fbf
platform17: http://fusion2/97565f8e-3be6-3bfe-9204-4c6d709f8599
Google-Bug-Id: 442009064
Change-Id: I09a22a0aeb2228292f6a6fff29572637c6483937
Signed-off-by: Jinliang Wang <jinliangw@google.com>
diff --git a/recipes-connectivity/mctp/mctp/0001-use-RTA_OIF-Outgoing-Interface-route-in-gbmc.patch b/recipes-connectivity/mctp/mctp/0001-use-RTA_OIF-Outgoing-Interface-route-in-gbmc.patch
new file mode 100644
index 0000000..da062b8
--- /dev/null
+++ b/recipes-connectivity/mctp/mctp/0001-use-RTA_OIF-Outgoing-Interface-route-in-gbmc.patch
@@ -0,0 +1,71 @@
+From 3eb4d6f1cc0c2e97114cef3da5cb5f19f66fc95d Mon Sep 17 00:00:00 2001
+From: Jinliang Wang <jinliangw@google.com>
+Date: Fri, 19 Sep 2025 15:18:16 -0700
+Subject: [PATCH 1/3] use RTA_OIF (Outgoing Interface) route in gbmc
+
+1) Google gbmc-5.15 kernel branch doesn't support MCTP RTA_GATEWAY route
+yet.
+2) avoids 0 mtu for the route to the bridge itself.
+
+Signed-off-by: Jinliang Wang <jinliangw@google.com>
+---
+ src/mctpd.c | 15 +++++++++------
+ 1 file changed, 9 insertions(+), 6 deletions(-)
+
+diff --git a/src/mctpd.c b/src/mctpd.c
+index 4919c19..743b9b2 100644
+--- a/src/mctpd.c
++++ b/src/mctpd.c
+@@ -591,7 +591,7 @@ static int read_message(struct ctx *ctx, int sd, uint8_t **ret_buf,
+ goto out;
+ }
+
+- if (ctx->verbose) {
++ if (0 && ctx->verbose) {
+ warnx("read_message got from %s len %zu",
+ ext_addr_tostr(ret_addr), buf_size);
+ }
+@@ -2883,7 +2883,8 @@ static int peer_route_update(struct peer *peer, uint16_t type)
+
+ if (type == RTM_NEWROUTE) {
+ return mctp_nl_route_add(peer->ctx->nl, peer->eid, 0,
+- peer->phys.ifindex, NULL, peer->mtu);
++ peer->phys.ifindex, NULL,
++ (peer->mtu > 0 ? peer->mtu : 68));
+ } else if (type == RTM_DELROUTE) {
+ if (peer->pool_size > 0) {
+ int rc = 0;
+@@ -2891,8 +2892,8 @@ static int peer_route_update(struct peer *peer, uint16_t type)
+ gw_addr.net = peer->net;
+ gw_addr.eid = peer->eid;
+ rc = mctp_nl_route_del(peer->ctx->nl, peer->pool_start,
+- peer->pool_size - 1, 0,
+- &gw_addr);
++ peer->pool_size - 1,
++ peer->phys.ifindex, &gw_addr);
+ if (rc < 0)
+ warnx("failed to delete route for peer pool eids %d-%d %s",
+ peer->pool_start,
+@@ -4930,7 +4931,8 @@ static int endpoint_allocate_eids(struct peer *peer)
+ gw_addr.net = peer->net;
+ gw_addr.eid = peer->eid;
+ rc = mctp_nl_route_add(peer->ctx->nl, peer->pool_start,
+- peer->pool_size - 1, 0, &gw_addr, peer->mtu);
++ peer->pool_size - 1, peer->phys.ifindex,
++ &gw_addr, peer->mtu);
+ if (rc < 0 && rc != -EEXIST) {
+ warnx("Failed to add gateway route for EID %d: %s", gw_addr.eid,
+ strerror(-rc));
+@@ -4945,7 +4947,8 @@ static int endpoint_allocate_eids(struct peer *peer)
+ warnx("Failed to allocate downstream EIDs");
+ // delete prior set routes for downstream endpoints
+ rc = mctp_nl_route_del(peer->ctx->nl, peer->pool_start,
+- peer->pool_size - 1, 0, &gw_addr);
++ peer->pool_size - 1, peer->phys.ifindex,
++ &gw_addr);
+ if (rc < 0)
+ warnx("failed to delete route for peer pool eids %d-%d %s",
+ peer->pool_start,
+--
+2.51.0.570.gb178f27e6d-goog
+
diff --git a/recipes-connectivity/mctp/mctp/0002-mctpd-remove_peer-if-get-endpoint-id-fails.patch b/recipes-connectivity/mctp/mctp/0002-mctpd-remove_peer-if-get-endpoint-id-fails.patch
new file mode 100644
index 0000000..9d8053a
--- /dev/null
+++ b/recipes-connectivity/mctp/mctp/0002-mctpd-remove_peer-if-get-endpoint-id-fails.patch
@@ -0,0 +1,123 @@
+From 6ff3de4c3f8c3470230d29f323ebd28294f3117f Mon Sep 17 00:00:00 2001
+From: Jinliang Wang <jinliangw@google.com>
+Date: Tue, 23 Sep 2025 14:54:40 -0700
+Subject: [PATCH 2/3] mctpd: remove_peer if get endpoint id fails
+
+method_net_learn_endpoint shall only keep the peer which is alive
+(responds to the query_get_endpoint_id).
+
+Tested:
+busctl call au.com.codeconstruct.MCTP1 /au/com/codeconstruct/mctp1/networks/1 au.com.codeconstruct.MCTP.Network1 LearnEndpoint y 8
+sb "/au/com/codeconstruct/mctp1/networks/1/endpoints/8" false
+busctl call au.com.codeconstruct.MCTP1 /au/com/codeconstruct/mctp1/networks/1 au.com.codeconstruct.MCTP.Network1 LearnEndpoint y 9
+Call failed: MCTP Endpoint did not respond
+busctl call au.com.codeconstruct.MCTP1 /au/com/codeconstruct/mctp1/networks/1 au.com.codeconstruct.MCTP.Network1 LearnEndpoint y 10
+sb "/au/com/codeconstruct/mctp1/networks/1/endpoints/10" true
+busctl call au.com.codeconstruct.MCTP1 /au/com/codeconstruct/mctp1/networks/1 au.com.codeconstruct.MCTP.Network1 LearnEndpoint y 15
+Call failed: Request failed
+
+Signed-off-by: Jinliang Wang <jinliangw@google.com>
+---
+ src/mctpd.c | 37 +++++++++++++++++++++++++++++++------
+ 1 file changed, 31 insertions(+), 6 deletions(-)
+
+diff --git a/src/mctpd.c b/src/mctpd.c
+index 743b9b2..6e3f768 100644
+--- a/src/mctpd.c
++++ b/src/mctpd.c
+@@ -2240,7 +2240,7 @@ static void set_berr(struct ctx *ctx, int errcode, sd_bus_error *berr)
+
+ static int query_get_endpoint_id(struct ctx *ctx, const dest_phys *dest,
+ mctp_eid_t *ret_eid, uint8_t *ret_ep_type,
+- uint8_t *ret_media_spec)
++ uint8_t *ret_media_spec, struct peer *peer)
+ {
+ struct sockaddr_mctp_ext addr;
+ struct mctp_ctrl_cmd_get_eid req = { 0 };
+@@ -2255,8 +2255,13 @@ static int query_get_endpoint_id(struct ctx *ctx, const dest_phys *dest,
+ mctp_ctrl_msg_hdr_init_req(&req.ctrl_hdr, iid,
+ MCTP_CTRL_CMD_GET_ENDPOINT_ID);
+
+- rc = endpoint_query_phys(ctx, dest, MCTP_CTRL_HDR_MSG_TYPE, &req,
+- sizeof(req), &buf, &buf_size, &addr);
++ if (peer)
++ rc = endpoint_query_peer(peer, MCTP_CTRL_HDR_MSG_TYPE, &req,
++ sizeof(req), &buf, &buf_size, &addr);
++ else
++ rc = endpoint_query_phys(ctx, dest, MCTP_CTRL_HDR_MSG_TYPE,
++ &req, sizeof(req), &buf, &buf_size,
++ &addr);
+ if (rc < 0)
+ goto out;
+
+@@ -2291,7 +2296,8 @@ static int get_endpoint_peer(struct ctx *ctx, sd_bus_error *berr,
+ int rc;
+
+ *ret_peer = NULL;
+- rc = query_get_endpoint_id(ctx, dest, &eid, &ep_type, &medium_spec);
++ rc = query_get_endpoint_id(ctx, dest, &eid, &ep_type, &medium_spec,
++ /*peer=*/NULL);
+ if (rc)
+ return rc;
+
+@@ -2557,7 +2563,8 @@ static int method_setup_endpoint(sd_bus_message *call, void *data,
+ }
+
+ /* Get Endpoint ID */
+- rc = query_get_endpoint_id(ctx, dest, &eid, &ep_type, &medium_spec);
++ rc = query_get_endpoint_id(ctx, dest, &eid, &ep_type, &medium_spec,
++ /*peer=*/NULL);
+ if (rc)
+ goto err;
+
+@@ -3143,7 +3150,7 @@ static int peer_endpoint_recover(sd_event_source *s, uint64_t usec,
+ */
+ rc = query_get_endpoint_id(ctx, &peer->phys, &peer->recovery.eid,
+ &peer->recovery.endpoint_type,
+- &peer->recovery.medium_spec);
++ &peer->recovery.medium_spec, /*peer=*/NULL);
+ if (rc < 0) {
+ goto reschedule;
+ }
+@@ -3341,6 +3348,8 @@ static int method_net_learn_endpoint(sd_bus_message *call, void *data,
+ mctp_eid_t eid = 0;
+ struct peer *peer;
+ int rc;
++ mctp_eid_t ret_eid;
++ uint8_t ret_ep_type, ret_medium_spec;
+
+ rc = sd_bus_message_read(call, "y", &eid);
+ if (rc < 0)
+@@ -3358,6 +3367,18 @@ static int method_net_learn_endpoint(sd_bus_message *call, void *data,
+ goto err;
+ }
+
++ rc = query_get_endpoint_id(peer->ctx, &dest, &ret_eid, &ret_ep_type,
++ &ret_medium_spec, peer);
++ if (rc) {
++ warnx("Error getting endpoint id for %s. error %d %s",
++ peer_tostr(peer), rc, strerror(-rc));
++ goto err;
++ } else if (ret_eid != eid) {
++ warnx("Error getting endpoint eid %u not match expected eid %u.",
++ ret_eid, eid);
++ goto err;
++ }
++
+ query_peer_properties(peer);
+
+ publish_peer(peer);
+@@ -3367,6 +3388,10 @@ static int method_net_learn_endpoint(sd_bus_message *call, void *data,
+ goto err;
+ return sd_bus_reply_method_return(call, "sb", peer_path, 1);
+ err:
++ if (peer) {
++ remove_peer(peer);
++ }
++
+ set_berr(ctx, rc, berr);
+ return rc;
+ }
+--
+2.51.0.570.gb178f27e6d-goog
+
diff --git a/recipes-connectivity/mctp/mctp/0003-mctpd-remove-MCTP-endpoints-behind-MCTP-bridge.patch b/recipes-connectivity/mctp/mctp/0003-mctpd-remove-MCTP-endpoints-behind-MCTP-bridge.patch
new file mode 100644
index 0000000..e11786d
--- /dev/null
+++ b/recipes-connectivity/mctp/mctp/0003-mctpd-remove-MCTP-endpoints-behind-MCTP-bridge.patch
@@ -0,0 +1,44 @@
+From 4be0914ea3c31fbc8129d2fb696eb70cfa589f12 Mon Sep 17 00:00:00 2001
+From: Jinliang Wang <jinliangw@google.com>
+Date: Tue, 23 Sep 2025 22:56:00 -0700
+Subject: [PATCH 3/3] mctpd: remove MCTP endpoints behind MCTP bridge
+
+Tested:
+The bridged MCTP endpoints are removed when interface is removed or
+when MCTP bridge EID is removed.
+
+Signed-off-by: Jinliang Wang <jinliangw@google.com>
+---
+ src/mctpd.c | 16 ++++++++++++++++
+ 1 file changed, 16 insertions(+)
+
+diff --git a/src/mctpd.c b/src/mctpd.c
+index 6e3f768..e506582 100644
+--- a/src/mctpd.c
++++ b/src/mctpd.c
+@@ -1883,6 +1883,22 @@ static int remove_peer(struct peer *peer)
+ return -EPROTO;
+ }
+
++ // Remove peers after MCTP bridge
++ for (uint8_t i = 0; i < peer->pool_size; i++) {
++ // Avoids overflow
++ if (peer->pool_start > 255 - i)
++ break;
++ uint8_t eid = peer->pool_start + i;
++ if (n->peers[eid]) {
++ int rc = remove_peer(n->peers[eid]);
++ if (rc) {
++ bug_warn(
++ "Failed to remove bridged peer: net %u eid %u, rc = %d",
++ n->net, eid, rc);
++ }
++ }
++ }
++
+ unpublish_peer(peer);
+
+ // Clear it
+--
+2.51.0.570.gb178f27e6d-goog
+
diff --git a/recipes-connectivity/mctp/mctp_%.bbappend b/recipes-connectivity/mctp/mctp_%.bbappend
index c27fef8..4afadca 100644
--- a/recipes-connectivity/mctp/mctp_%.bbappend
+++ b/recipes-connectivity/mctp/mctp_%.bbappend
@@ -6,6 +6,9 @@
file://init-mctp-i2c-endpoint.sh \
file://service-override.conf \
file://0001-mctpd-ignore-IIDs-validation-for-control-responses.patch \
+ file://0001-use-RTA_OIF-Outgoing-Interface-route-in-gbmc.patch \
+ file://0002-mctpd-remove_peer-if-get-endpoint-id-fails.patch \
+ file://0003-mctpd-remove-MCTP-endpoints-behind-MCTP-bridge.patch \
"
RDEPENDS:${PN} += " \