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} += " \