Skip to content

grpc/xds: Add feature-gated xDS proto codegen and the generated .rs code#2723

Open
gu0keno0 wants to merge 7 commits into
grpc:masterfrom
gu0keno0:xds-protoc
Open

grpc/xds: Add feature-gated xDS proto codegen and the generated .rs code#2723
gu0keno0 wants to merge 7 commits into
grpc:masterfrom
gu0keno0:xds-protoc

Conversation

@gu0keno0

@gu0keno0 gu0keno0 commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Add xds protos, codegen and generated .rs files

Motivation

The usual places for the generated code of xDS protobuf is https://github.com/envoyproxy, e.g. https://github.com/envoyproxy/go-control-plane. However, currently there's no official https://github.com/envoyproxy/rust-control-plane.

For gRPC, we need to use the Google protobuf codegen to generate the xDS structs, therefore created this PR to do the job.

Solution

  1. Add import script to download relevant protobuf sources from the SOT locations. This is mirroring grpc-java
  2. Add codegen logic to the existing codegen crate to generate .rs files for the downloaded protobuf sources. By default, the Rust protoc codegen library assumes all types are in a flattened namespace in a single crate. This does not work for us because it will cause name collisions in multiple xDS protobuf source files. Therefore, the codegen generates a aggregation .rs file to re-export the protobuf types as a module, which also provides namespace isolations and organizes the generated protobuf in the same hierarchy as the original protobuf sources.
  3. Gate xds feature in both codegen and grpc crates.

Test Plan

  1. cargo build + CI
  2. I also created a local test to verify that the generated types work as expected
#[cfg(test)]
mod tests {
    //! Demonstrates building the four core xDS resource messages
    //! (LDS/RDS/CDS/EDS) from the generated types and round-tripping them
    //! through the protobuf wire format.

    // `.serialize()` and `T::parse(&bytes)` come from the protobuf message
    // traits; the prelude brings them into scope under `_` aliases.
    use protobuf::prelude::*;

    use super::generated::envoy::config::{
        cluster::v3::cluster::{cluster::DiscoveryType, Cluster},
        endpoint::v3::endpoint::ClusterLoadAssignment,
        listener::v3::listener::Listener,
        route::v3::route::RouteConfiguration,
    };

    /// Encodes then decodes a message, exercising the protobuf wire round-trip.
    fn round_trip<M: protobuf::Message>(msg: &M) -> M {
        M::parse(&msg.serialize().expect("serialize")).expect("parse")
    }

    #[test]
    fn lds_listener_round_trip() {
        let mut listener = Listener::new();
        listener.set_name("grpc-listener");

        let decoded = round_trip(&listener);
        assert_eq!(decoded.name().as_bytes(), b"grpc-listener");
    }

    #[test]
    fn rds_route_configuration_round_trip() {
        let mut route_config = RouteConfiguration::new();
        route_config.set_name("grpc-routes");

        let decoded = round_trip(&route_config);
        assert_eq!(decoded.name().as_bytes(), b"grpc-routes");
    }

    #[test]
    fn cds_cluster_round_trip() {
        let mut cluster = Cluster::new();
        cluster.set_name("grpc-cluster");
        // A CDS cluster whose endpoints are resolved via EDS.
        cluster.set_type(DiscoveryType::Eds);

        let decoded = round_trip(&cluster);
        assert_eq!(decoded.name().as_bytes(), b"grpc-cluster");
        assert_eq!(decoded.r#type(), DiscoveryType::Eds);
    }

    #[test]
    fn eds_cluster_load_assignment_round_trip() {
        let mut endpoints = ClusterLoadAssignment::new();
        // EDS keys its endpoints by the owning cluster's name (the CDS -> EDS link).
        endpoints.set_cluster_name("grpc-cluster");

        let decoded = round_trip(&endpoints);
        assert_eq!(decoded.cluster_name().as_bytes(), b"grpc-cluster");
    }
}
  1. Soon we'll add meaningful handlings of these generated structs when we implement the xDS dependency manager.

@gu0keno0 gu0keno0 requested review from dfawley and ejona86 July 7, 2026 14:07
@gu0keno0 gu0keno0 marked this pull request as ready for review July 7, 2026 15:56
@gu0keno0 gu0keno0 requested a review from YutaoMa July 7, 2026 15:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant