From 5d9cdc8e6756135d516bb47b32796bd2351cbfb2 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Wed, 1 Jun 2022 14:08:26 -0700 Subject: [PATCH] xds: Add XdsLbRegistry (#29756) * xds: Add XdsLbRegistry * Formatting * Fix upb output * Allow alternative type url for Custom LBs * Cleanup * Reviewer comments * Add some comments * Reviewer comments * Reviewer comments * Reviewer comments * Reviewer comments * Fix tests * Fix tests * Fix tests * Fix tests * Fix tests * Unused parameters * Change to make TextFormat usage work internally * Fix namespace qualification error --- BUILD | 15 + CMakeLists.txt | 117 ++++ Makefile | 6 + build_autogenerated.yaml | 43 ++ config.m4 | 5 + config.w32 | 8 + gRPC-C++.podspec | 6 + gRPC-Core.podspec | 9 + grpc.gemspec | 6 + grpc.gyp | 3 + package.xml | 6 + .../ring_hash/v3/ring_hash.upb.c | 52 ++ .../ring_hash/v3/ring_hash.upb.h | 164 ++++++ .../wrr_locality/v3/wrr_locality.upb.c | 46 ++ .../wrr_locality/v3/wrr_locality.upb.h | 94 +++ src/core/ext/xds/xds_common_types.cc | 32 +- src/core/ext/xds/xds_common_types.h | 12 +- src/core/ext/xds/xds_lb_policy_registry.cc | 291 ++++++++++ src/core/ext/xds/xds_lb_policy_registry.h | 72 +++ src/core/ext/xds/xds_listener.cc | 23 +- src/core/ext/xds/xds_route_config.cc | 27 +- src/proto/grpc/testing/xds/v3/BUILD | 44 ++ src/proto/grpc/testing/xds/v3/cluster.proto | 39 ++ src/proto/grpc/testing/xds/v3/ring_hash.proto | 59 ++ .../grpc/testing/xds/v3/round_robin.proto | 28 + .../grpc/testing/xds/v3/typed_struct.proto | 53 ++ .../testing/xds/v3/udpa_typed_struct.proto | 53 ++ .../grpc/testing/xds/v3/wrr_locality.proto | 31 + src/python/grpcio/grpc_core_dependencies.py | 3 + test/core/xds/BUILD | 20 + test/core/xds/xds_lb_policy_registry_test.cc | 534 ++++++++++++++++++ test/cpp/end2end/xds/xds_end2end_test.cc | 6 +- .../end2end/xds/xds_routing_end2end_test.cc | 8 +- tools/doxygen/Doxyfile.c++.internal | 6 + tools/doxygen/Doxyfile.core.internal | 6 + tools/run_tests/generated/tests.json | 24 + 36 files changed, 1903 insertions(+), 48 deletions(-) create mode 100644 src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb.c create mode 100644 src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb.h create mode 100644 src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/wrr_locality/v3/wrr_locality.upb.c create mode 100644 src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/wrr_locality/v3/wrr_locality.upb.h create mode 100644 src/core/ext/xds/xds_lb_policy_registry.cc create mode 100644 src/core/ext/xds/xds_lb_policy_registry.h create mode 100644 src/proto/grpc/testing/xds/v3/ring_hash.proto create mode 100644 src/proto/grpc/testing/xds/v3/round_robin.proto create mode 100644 src/proto/grpc/testing/xds/v3/typed_struct.proto create mode 100644 src/proto/grpc/testing/xds/v3/udpa_typed_struct.proto create mode 100644 src/proto/grpc/testing/xds/v3/wrr_locality.proto create mode 100644 test/core/xds/xds_lb_policy_registry_test.cc diff --git a/BUILD b/BUILD index 0dd4274e90d..a1c6f9eebf6 100644 --- a/BUILD +++ b/BUILD @@ -3623,6 +3623,7 @@ grpc_cc_library( "src/core/ext/xds/xds_http_fault_filter.cc", "src/core/ext/xds/xds_http_filters.cc", "src/core/ext/xds/xds_http_rbac_filter.cc", + "src/core/ext/xds/xds_lb_policy_registry.cc", "src/core/ext/xds/xds_listener.cc", "src/core/ext/xds/xds_resource_type.cc", "src/core/ext/xds/xds_route_config.cc", @@ -3648,6 +3649,7 @@ grpc_cc_library( "src/core/ext/xds/xds_http_fault_filter.h", "src/core/ext/xds/xds_http_filters.h", "src/core/ext/xds/xds_http_rbac_filter.h", + "src/core/ext/xds/xds_lb_policy_registry.h", "src/core/ext/xds/xds_listener.h", "src/core/ext/xds/xds_resource_type.h", "src/core/ext/xds/xds_resource_type_impl.h", @@ -3699,6 +3701,8 @@ grpc_cc_library( "envoy_extensions_filters_http_router_upbdefs", "envoy_extensions_filters_network_http_connection_manager_upb", "envoy_extensions_filters_network_http_connection_manager_upbdefs", + "envoy_extensions_load_balancing_policies_ring_hash_upb", + "envoy_extensions_load_balancing_policies_wrr_locality_upb", "envoy_extensions_transport_sockets_tls_upb", "envoy_extensions_transport_sockets_tls_upbdefs", "envoy_service_discovery_upb", @@ -3736,6 +3740,7 @@ grpc_cc_library( "protobuf_any_upb", "protobuf_duration_upb", "protobuf_struct_upb", + "protobuf_struct_upbdefs", "protobuf_timestamp_upb", "protobuf_wrappers_upb", "ref_counted_ptr", @@ -6624,6 +6629,16 @@ grpc_upb_proto_reflection_library( deps = ["@envoy_api//envoy/extensions/filters/http/router/v3:pkg"], ) +grpc_upb_proto_library( + name = "envoy_extensions_load_balancing_policies_ring_hash_upb", + deps = ["@envoy_api//envoy/extensions/load_balancing_policies/ring_hash/v3:pkg"], +) + +grpc_upb_proto_library( + name = "envoy_extensions_load_balancing_policies_wrr_locality_upb", + deps = ["@envoy_api//envoy/extensions/load_balancing_policies/wrr_locality/v3:pkg"], +) + grpc_upb_proto_library( name = "envoy_extensions_filters_network_http_connection_manager_upb", deps = ["@envoy_api//envoy/extensions/filters/network/http_connection_manager/v3:pkg"], diff --git a/CMakeLists.txt b/CMakeLists.txt index c7ed9c0934c..7f9c1083c70 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -730,6 +730,12 @@ protobuf_generate_grpc_cpp_with_import_path_correction( protobuf_generate_grpc_cpp_with_import_path_correction( src/proto/grpc/testing/xds/v3/regex.proto src/proto/grpc/testing/xds/v3/regex.proto ) +protobuf_generate_grpc_cpp_with_import_path_correction( + src/proto/grpc/testing/xds/v3/ring_hash.proto src/proto/grpc/testing/xds/v3/ring_hash.proto +) +protobuf_generate_grpc_cpp_with_import_path_correction( + src/proto/grpc/testing/xds/v3/round_robin.proto src/proto/grpc/testing/xds/v3/round_robin.proto +) protobuf_generate_grpc_cpp_with_import_path_correction( src/proto/grpc/testing/xds/v3/route.proto src/proto/grpc/testing/xds/v3/route.proto ) @@ -742,6 +748,15 @@ protobuf_generate_grpc_cpp_with_import_path_correction( protobuf_generate_grpc_cpp_with_import_path_correction( src/proto/grpc/testing/xds/v3/tls.proto src/proto/grpc/testing/xds/v3/tls.proto ) +protobuf_generate_grpc_cpp_with_import_path_correction( + src/proto/grpc/testing/xds/v3/typed_struct.proto src/proto/grpc/testing/xds/v3/typed_struct.proto +) +protobuf_generate_grpc_cpp_with_import_path_correction( + src/proto/grpc/testing/xds/v3/udpa_typed_struct.proto src/proto/grpc/testing/xds/v3/udpa_typed_struct.proto +) +protobuf_generate_grpc_cpp_with_import_path_correction( + src/proto/grpc/testing/xds/v3/wrr_locality.proto src/proto/grpc/testing/xds/v3/wrr_locality.proto +) protobuf_generate_grpc_cpp_with_import_path_correction( test/core/tsi/alts/fake_handshaker/handshaker.proto test/core/tsi/alts/fake_handshaker/handshaker.proto ) @@ -1209,6 +1224,7 @@ if(gRPC_BUILD_TESTS) endif() add_dependencies(buildtests_cxx xds_interop_client) add_dependencies(buildtests_cxx xds_interop_server) + add_dependencies(buildtests_cxx xds_lb_policy_registry_test) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_cxx xds_outlier_detection_end2end_test) endif() @@ -1779,6 +1795,8 @@ add_library(grpc src/core/ext/upb-generated/envoy/extensions/filters/http/rbac/v3/rbac.upb.c src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.c src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.c + src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb.c + src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/wrr_locality/v3/wrr_locality.upb.c src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/cert.upb.c src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/common.upb.c src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/secret.upb.c @@ -2004,6 +2022,7 @@ add_library(grpc src/core/ext/xds/xds_http_fault_filter.cc src/core/ext/xds/xds_http_filters.cc src/core/ext/xds/xds_http_rbac_filter.cc + src/core/ext/xds/xds_lb_policy_registry.cc src/core/ext/xds/xds_listener.cc src/core/ext/xds/xds_resource_type.cc src/core/ext/xds/xds_route_config.cc @@ -19047,6 +19066,104 @@ target_link_libraries(xds_interop_server ) +endif() +if(gRPC_BUILD_TESTS) + +add_executable(xds_lb_policy_registry_test + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/reflection/v1alpha/reflection.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/reflection/v1alpha/reflection.grpc.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/reflection/v1alpha/reflection.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/reflection/v1alpha/reflection.grpc.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/address.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/address.grpc.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/address.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/address.grpc.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/base.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/base.grpc.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/base.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/base.grpc.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/cluster.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/cluster.grpc.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/cluster.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/cluster.grpc.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_source.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_source.grpc.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_source.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_source.grpc.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/endpoint.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/endpoint.grpc.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/endpoint.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/endpoint.grpc.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/extension.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/extension.grpc.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/extension.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/extension.grpc.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/outlier_detection.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/outlier_detection.grpc.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/outlier_detection.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/outlier_detection.grpc.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/percent.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/percent.grpc.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/percent.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/percent.grpc.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/ring_hash.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/ring_hash.grpc.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/ring_hash.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/ring_hash.grpc.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/round_robin.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/round_robin.grpc.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/round_robin.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/round_robin.grpc.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/typed_struct.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/typed_struct.grpc.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/typed_struct.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/typed_struct.grpc.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/udpa_typed_struct.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/udpa_typed_struct.grpc.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/udpa_typed_struct.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/udpa_typed_struct.grpc.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/wrr_locality.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/wrr_locality.grpc.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/wrr_locality.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/wrr_locality.grpc.pb.h + test/core/xds/xds_lb_policy_registry_test.cc + test/cpp/util/cli_call.cc + test/cpp/util/cli_credentials.cc + test/cpp/util/proto_file_parser.cc + test/cpp/util/proto_reflection_descriptor_database.cc + test/cpp/util/service_describer.cc + third_party/googletest/googletest/src/gtest-all.cc + third_party/googletest/googlemock/src/gmock-all.cc +) + +target_include_directories(xds_lb_policy_registry_test + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/include + ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} + ${_gRPC_RE2_INCLUDE_DIR} + ${_gRPC_SSL_INCLUDE_DIR} + ${_gRPC_UPB_GENERATED_DIR} + ${_gRPC_UPB_GRPC_GENERATED_DIR} + ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} + ${_gRPC_ZLIB_INCLUDE_DIR} + third_party/googletest/googletest/include + third_party/googletest/googletest + third_party/googletest/googlemock/include + third_party/googletest/googlemock + ${_gRPC_PROTO_GENS_DIR} +) + +target_link_libraries(xds_lb_policy_registry_test + ${_gRPC_PROTOBUF_LIBRARIES} + ${_gRPC_ALLTARGETS_LIBRARIES} + absl::flags + grpc++ + grpc_test_util +) + + endif() if(gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) diff --git a/Makefile b/Makefile index 9ff5b20bb91..92a7a3714b5 100644 --- a/Makefile +++ b/Makefile @@ -1186,6 +1186,8 @@ LIBGRPC_SRC = \ src/core/ext/upb-generated/envoy/extensions/filters/http/rbac/v3/rbac.upb.c \ src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.c \ src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.c \ + src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb.c \ + src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/wrr_locality/v3/wrr_locality.upb.c \ src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/cert.upb.c \ src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/common.upb.c \ src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/secret.upb.c \ @@ -1411,6 +1413,7 @@ LIBGRPC_SRC = \ src/core/ext/xds/xds_http_fault_filter.cc \ src/core/ext/xds/xds_http_filters.cc \ src/core/ext/xds/xds_http_rbac_filter.cc \ + src/core/ext/xds/xds_lb_policy_registry.cc \ src/core/ext/xds/xds_listener.cc \ src/core/ext/xds/xds_resource_type.cc \ src/core/ext/xds/xds_route_config.cc \ @@ -2896,6 +2899,8 @@ src/core/ext/upb-generated/envoy/extensions/filters/http/fault/v3/fault.upb.c: $ src/core/ext/upb-generated/envoy/extensions/filters/http/rbac/v3/rbac.upb.c: $(OPENSSL_DEP) src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.c: $(OPENSSL_DEP) src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.c: $(OPENSSL_DEP) +src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb.c: $(OPENSSL_DEP) +src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/wrr_locality/v3/wrr_locality.upb.c: $(OPENSSL_DEP) src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/cert.upb.c: $(OPENSSL_DEP) src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/common.upb.c: $(OPENSSL_DEP) src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/secret.upb.c: $(OPENSSL_DEP) @@ -3104,6 +3109,7 @@ src/core/ext/xds/xds_endpoint.cc: $(OPENSSL_DEP) src/core/ext/xds/xds_http_fault_filter.cc: $(OPENSSL_DEP) src/core/ext/xds/xds_http_filters.cc: $(OPENSSL_DEP) src/core/ext/xds/xds_http_rbac_filter.cc: $(OPENSSL_DEP) +src/core/ext/xds/xds_lb_policy_registry.cc: $(OPENSSL_DEP) src/core/ext/xds/xds_listener.cc: $(OPENSSL_DEP) src/core/ext/xds/xds_resource_type.cc: $(OPENSSL_DEP) src/core/ext/xds/xds_route_config.cc: $(OPENSSL_DEP) diff --git a/build_autogenerated.yaml b/build_autogenerated.yaml index dc5543387c8..062433b09af 100644 --- a/build_autogenerated.yaml +++ b/build_autogenerated.yaml @@ -487,6 +487,8 @@ libs: - src/core/ext/upb-generated/envoy/extensions/filters/http/rbac/v3/rbac.upb.h - src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.h - src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.h + - src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb.h + - src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/wrr_locality/v3/wrr_locality.upb.h - src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/cert.upb.h - src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/common.upb.h - src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/secret.upb.h @@ -715,6 +717,7 @@ libs: - src/core/ext/xds/xds_http_fault_filter.h - src/core/ext/xds/xds_http_filters.h - src/core/ext/xds/xds_http_rbac_filter.h + - src/core/ext/xds/xds_lb_policy_registry.h - src/core/ext/xds/xds_listener.h - src/core/ext/xds/xds_resource_type.h - src/core/ext/xds/xds_resource_type_impl.h @@ -1165,6 +1168,8 @@ libs: - src/core/ext/upb-generated/envoy/extensions/filters/http/rbac/v3/rbac.upb.c - src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.c - src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.c + - src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb.c + - src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/wrr_locality/v3/wrr_locality.upb.c - src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/cert.upb.c - src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/common.upb.c - src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/secret.upb.c @@ -1390,6 +1395,7 @@ libs: - src/core/ext/xds/xds_http_fault_filter.cc - src/core/ext/xds/xds_http_filters.cc - src/core/ext/xds/xds_http_rbac_filter.cc + - src/core/ext/xds/xds_lb_policy_registry.cc - src/core/ext/xds/xds_listener.cc - src/core/ext/xds/xds_resource_type.cc - src/core/ext/xds/xds_route_config.cc @@ -9350,6 +9356,43 @@ targets: - grpcpp_channelz - grpc_test_util - grpc++_test_config +- name: xds_lb_policy_registry_test + gtest: true + build: test + language: c++ + headers: + - test/cpp/util/cli_call.h + - test/cpp/util/cli_credentials.h + - test/cpp/util/config_grpc_cli.h + - test/cpp/util/proto_file_parser.h + - test/cpp/util/proto_reflection_descriptor_database.h + - test/cpp/util/service_describer.h + src: + - src/proto/grpc/reflection/v1alpha/reflection.proto + - src/proto/grpc/testing/xds/v3/address.proto + - src/proto/grpc/testing/xds/v3/base.proto + - src/proto/grpc/testing/xds/v3/cluster.proto + - src/proto/grpc/testing/xds/v3/config_source.proto + - src/proto/grpc/testing/xds/v3/endpoint.proto + - src/proto/grpc/testing/xds/v3/extension.proto + - src/proto/grpc/testing/xds/v3/outlier_detection.proto + - src/proto/grpc/testing/xds/v3/percent.proto + - src/proto/grpc/testing/xds/v3/ring_hash.proto + - src/proto/grpc/testing/xds/v3/round_robin.proto + - src/proto/grpc/testing/xds/v3/typed_struct.proto + - src/proto/grpc/testing/xds/v3/udpa_typed_struct.proto + - src/proto/grpc/testing/xds/v3/wrr_locality.proto + - test/core/xds/xds_lb_policy_registry_test.cc + - test/cpp/util/cli_call.cc + - test/cpp/util/cli_credentials.cc + - test/cpp/util/proto_file_parser.cc + - test/cpp/util/proto_reflection_descriptor_database.cc + - test/cpp/util/service_describer.cc + deps: + - absl/flags:flag + - grpc++ + - grpc_test_util + uses_polling: false - name: xds_outlier_detection_end2end_test gtest: true build: test diff --git a/config.m4 b/config.m4 index 397f6ea78bd..5d3ecbc0bdb 100644 --- a/config.m4 +++ b/config.m4 @@ -208,6 +208,8 @@ if test "$PHP_GRPC" != "no"; then src/core/ext/upb-generated/envoy/extensions/filters/http/rbac/v3/rbac.upb.c \ src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.c \ src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.c \ + src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb.c \ + src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/wrr_locality/v3/wrr_locality.upb.c \ src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/cert.upb.c \ src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/common.upb.c \ src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/secret.upb.c \ @@ -433,6 +435,7 @@ if test "$PHP_GRPC" != "no"; then src/core/ext/xds/xds_http_fault_filter.cc \ src/core/ext/xds/xds_http_filters.cc \ src/core/ext/xds/xds_http_rbac_filter.cc \ + src/core/ext/xds/xds_lb_policy_registry.cc \ src/core/ext/xds/xds_listener.cc \ src/core/ext/xds/xds_resource_type.cc \ src/core/ext/xds/xds_route_config.cc \ @@ -1221,6 +1224,8 @@ if test "$PHP_GRPC" != "no"; then PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/extensions/filters/http/rbac/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3) + PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/ring_hash/v3) + PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/wrr_locality/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/service/discovery/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/service/load_stats/v3) diff --git a/config.w32 b/config.w32 index d56635606a6..a06bb24de93 100644 --- a/config.w32 +++ b/config.w32 @@ -174,6 +174,8 @@ if (PHP_GRPC != "no") { "src\\core\\ext\\upb-generated\\envoy\\extensions\\filters\\http\\rbac\\v3\\rbac.upb.c " + "src\\core\\ext\\upb-generated\\envoy\\extensions\\filters\\http\\router\\v3\\router.upb.c " + "src\\core\\ext\\upb-generated\\envoy\\extensions\\filters\\network\\http_connection_manager\\v3\\http_connection_manager.upb.c " + + "src\\core\\ext\\upb-generated\\envoy\\extensions\\load_balancing_policies\\ring_hash\\v3\\ring_hash.upb.c " + + "src\\core\\ext\\upb-generated\\envoy\\extensions\\load_balancing_policies\\wrr_locality\\v3\\wrr_locality.upb.c " + "src\\core\\ext\\upb-generated\\envoy\\extensions\\transport_sockets\\tls\\v3\\cert.upb.c " + "src\\core\\ext\\upb-generated\\envoy\\extensions\\transport_sockets\\tls\\v3\\common.upb.c " + "src\\core\\ext\\upb-generated\\envoy\\extensions\\transport_sockets\\tls\\v3\\secret.upb.c " + @@ -399,6 +401,7 @@ if (PHP_GRPC != "no") { "src\\core\\ext\\xds\\xds_http_fault_filter.cc " + "src\\core\\ext\\xds\\xds_http_filters.cc " + "src\\core\\ext\\xds\\xds_http_rbac_filter.cc " + + "src\\core\\ext\\xds\\xds_lb_policy_registry.cc " + "src\\core\\ext\\xds\\xds_listener.cc " + "src\\core\\ext\\xds\\xds_resource_type.cc " + "src\\core\\ext\\xds\\xds_route_config.cc " + @@ -1251,6 +1254,11 @@ if (PHP_GRPC != "no") { FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\extensions\\filters\\network"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\extensions\\filters\\network\\http_connection_manager"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\extensions\\filters\\network\\http_connection_manager\\v3"); + FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\extensions\\load_balancing_policies"); + FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\extensions\\load_balancing_policies\\ring_hash"); + FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\extensions\\load_balancing_policies\\ring_hash\\v3"); + FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\extensions\\load_balancing_policies\\wrr_locality"); + FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\extensions\\load_balancing_policies\\wrr_locality\\v3"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\extensions\\transport_sockets"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\extensions\\transport_sockets\\tls"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\extensions\\transport_sockets\\tls\\v3"); diff --git a/gRPC-C++.podspec b/gRPC-C++.podspec index dac9ff4e1c4..6c0d7cfd4e6 100644 --- a/gRPC-C++.podspec +++ b/gRPC-C++.podspec @@ -411,6 +411,8 @@ Pod::Spec.new do |s| 'src/core/ext/upb-generated/envoy/extensions/filters/http/rbac/v3/rbac.upb.h', 'src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.h', 'src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.h', + 'src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb.h', + 'src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/wrr_locality/v3/wrr_locality.upb.h', 'src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/cert.upb.h', 'src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/common.upb.h', 'src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/secret.upb.h', @@ -639,6 +641,7 @@ Pod::Spec.new do |s| 'src/core/ext/xds/xds_http_fault_filter.h', 'src/core/ext/xds/xds_http_filters.h', 'src/core/ext/xds/xds_http_rbac_filter.h', + 'src/core/ext/xds/xds_lb_policy_registry.h', 'src/core/ext/xds/xds_listener.h', 'src/core/ext/xds/xds_resource_type.h', 'src/core/ext/xds/xds_resource_type_impl.h', @@ -1229,6 +1232,8 @@ Pod::Spec.new do |s| 'src/core/ext/upb-generated/envoy/extensions/filters/http/rbac/v3/rbac.upb.h', 'src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.h', 'src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.h', + 'src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb.h', + 'src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/wrr_locality/v3/wrr_locality.upb.h', 'src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/cert.upb.h', 'src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/common.upb.h', 'src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/secret.upb.h', @@ -1457,6 +1462,7 @@ Pod::Spec.new do |s| 'src/core/ext/xds/xds_http_fault_filter.h', 'src/core/ext/xds/xds_http_filters.h', 'src/core/ext/xds/xds_http_rbac_filter.h', + 'src/core/ext/xds/xds_lb_policy_registry.h', 'src/core/ext/xds/xds_listener.h', 'src/core/ext/xds/xds_resource_type.h', 'src/core/ext/xds/xds_resource_type_impl.h', diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index 9f99667e07b..6afb2a748dc 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -519,6 +519,10 @@ Pod::Spec.new do |s| 'src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.h', 'src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.c', 'src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.h', + 'src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb.c', + 'src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb.h', + 'src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/wrr_locality/v3/wrr_locality.upb.c', + 'src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/wrr_locality/v3/wrr_locality.upb.h', 'src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/cert.upb.c', 'src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/cert.upb.h', 'src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/common.upb.c', @@ -972,6 +976,8 @@ Pod::Spec.new do |s| 'src/core/ext/xds/xds_http_filters.h', 'src/core/ext/xds/xds_http_rbac_filter.cc', 'src/core/ext/xds/xds_http_rbac_filter.h', + 'src/core/ext/xds/xds_lb_policy_registry.cc', + 'src/core/ext/xds/xds_lb_policy_registry.h', 'src/core/ext/xds/xds_listener.cc', 'src/core/ext/xds/xds_listener.h', 'src/core/ext/xds/xds_resource_type.cc', @@ -1828,6 +1834,8 @@ Pod::Spec.new do |s| 'src/core/ext/upb-generated/envoy/extensions/filters/http/rbac/v3/rbac.upb.h', 'src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.h', 'src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.h', + 'src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb.h', + 'src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/wrr_locality/v3/wrr_locality.upb.h', 'src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/cert.upb.h', 'src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/common.upb.h', 'src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/secret.upb.h', @@ -2056,6 +2064,7 @@ Pod::Spec.new do |s| 'src/core/ext/xds/xds_http_fault_filter.h', 'src/core/ext/xds/xds_http_filters.h', 'src/core/ext/xds/xds_http_rbac_filter.h', + 'src/core/ext/xds/xds_lb_policy_registry.h', 'src/core/ext/xds/xds_listener.h', 'src/core/ext/xds/xds_resource_type.h', 'src/core/ext/xds/xds_resource_type_impl.h', diff --git a/grpc.gemspec b/grpc.gemspec index e694e5409df..5ab7231aede 100644 --- a/grpc.gemspec +++ b/grpc.gemspec @@ -432,6 +432,10 @@ Gem::Specification.new do |s| s.files += %w( src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.h ) s.files += %w( src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.c ) s.files += %w( src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.h ) + s.files += %w( src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb.c ) + s.files += %w( src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb.h ) + s.files += %w( src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/wrr_locality/v3/wrr_locality.upb.c ) + s.files += %w( src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/wrr_locality/v3/wrr_locality.upb.h ) s.files += %w( src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/cert.upb.c ) s.files += %w( src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/cert.upb.h ) s.files += %w( src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/common.upb.c ) @@ -885,6 +889,8 @@ Gem::Specification.new do |s| s.files += %w( src/core/ext/xds/xds_http_filters.h ) s.files += %w( src/core/ext/xds/xds_http_rbac_filter.cc ) s.files += %w( src/core/ext/xds/xds_http_rbac_filter.h ) + s.files += %w( src/core/ext/xds/xds_lb_policy_registry.cc ) + s.files += %w( src/core/ext/xds/xds_lb_policy_registry.h ) s.files += %w( src/core/ext/xds/xds_listener.cc ) s.files += %w( src/core/ext/xds/xds_listener.h ) s.files += %w( src/core/ext/xds/xds_resource_type.cc ) diff --git a/grpc.gyp b/grpc.gyp index 700a2370f6f..8733b3611c7 100644 --- a/grpc.gyp +++ b/grpc.gyp @@ -543,6 +543,8 @@ 'src/core/ext/upb-generated/envoy/extensions/filters/http/rbac/v3/rbac.upb.c', 'src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.c', 'src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.c', + 'src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb.c', + 'src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/wrr_locality/v3/wrr_locality.upb.c', 'src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/cert.upb.c', 'src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/common.upb.c', 'src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/secret.upb.c', @@ -768,6 +770,7 @@ 'src/core/ext/xds/xds_http_fault_filter.cc', 'src/core/ext/xds/xds_http_filters.cc', 'src/core/ext/xds/xds_http_rbac_filter.cc', + 'src/core/ext/xds/xds_lb_policy_registry.cc', 'src/core/ext/xds/xds_listener.cc', 'src/core/ext/xds/xds_resource_type.cc', 'src/core/ext/xds/xds_route_config.cc', diff --git a/package.xml b/package.xml index 13a7318908f..ffc854f0731 100644 --- a/package.xml +++ b/package.xml @@ -414,6 +414,10 @@ + + + + @@ -867,6 +871,8 @@ + + diff --git a/src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb.c b/src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb.c new file mode 100644 index 00000000000..23a52cab893 --- /dev/null +++ b/src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb.c @@ -0,0 +1,52 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#include +#include "upb/msg_internal.h" +#include "envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb.h" +#include "google/protobuf/wrappers.upb.h" +#include "udpa/annotations/status.upb.h" +#include "validate/validate.upb.h" + +#include "upb/port_def.inc" + +static const upb_MiniTable_Sub envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_submsgs[3] = { + {.submsg = &google_protobuf_UInt64Value_msginit}, + {.submsg = &google_protobuf_UInt64Value_msginit}, + {.submsg = &google_protobuf_UInt32Value_msginit}, +}; + +static const upb_MiniTable_Field envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash__fields[5] = { + {1, UPB_SIZE(4, 4), UPB_SIZE(0, 0), kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {2, UPB_SIZE(12, 16), UPB_SIZE(1, 1), 0, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)}, + {3, UPB_SIZE(16, 24), UPB_SIZE(2, 2), 1, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)}, + {4, UPB_SIZE(8, 8), UPB_SIZE(0, 0), kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {5, UPB_SIZE(20, 32), UPB_SIZE(3, 3), 2, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_msginit = { + &envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_submsgs[0], + &envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash__fields[0], + UPB_SIZE(24, 40), 5, kUpb_ExtMode_NonExtendable, 5, 255, 0, +}; + +static const upb_MiniTable *messages_layout[1] = { + &envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_msginit, +}; + +const upb_MiniTable_File envoy_extensions_load_balancing_policies_ring_hash_v3_ring_hash_proto_upb_file_layout = { + messages_layout, + NULL, + NULL, + 1, + 0, + 0, +}; + +#include "upb/port_undef.inc" + diff --git a/src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb.h b/src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb.h new file mode 100644 index 00000000000..88ace25ead5 --- /dev/null +++ b/src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb.h @@ -0,0 +1,164 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#ifndef ENVOY_EXTENSIONS_LOAD_BALANCING_POLICIES_RING_HASH_V3_RING_HASH_PROTO_UPB_H_ +#define ENVOY_EXTENSIONS_LOAD_BALANCING_POLICIES_RING_HASH_V3_RING_HASH_PROTO_UPB_H_ + +#include "upb/msg_internal.h" +#include "upb/decode.h" +#include "upb/decode_fast.h" +#include "upb/encode.h" + +#include "upb/port_def.inc" + +#ifdef __cplusplus +extern "C" { +#endif + +struct envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash; +typedef struct envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash; +extern const upb_MiniTable envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_msginit; +struct google_protobuf_UInt32Value; +struct google_protobuf_UInt64Value; +extern const upb_MiniTable google_protobuf_UInt32Value_msginit; +extern const upb_MiniTable google_protobuf_UInt64Value_msginit; + +typedef enum { + envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_DEFAULT_HASH = 0, + envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_XX_HASH = 1, + envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_MURMUR_HASH_2 = 2 +} envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_HashFunction; + + + +/* envoy.extensions.load_balancing_policies.ring_hash.v3.RingHash */ + +UPB_INLINE envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash* envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_new(upb_Arena* arena) { + return (envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash*)_upb_Message_New(&envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_msginit, arena); +} +UPB_INLINE envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash* envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_parse(const char* buf, size_t size, upb_Arena* arena) { + envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash* ret = envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_new(arena); + if (!ret) return NULL; + if (upb_Decode(buf, size, ret, &envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) { + return NULL; + } + return ret; +} +UPB_INLINE envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash* envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_parse_ex(const char* buf, size_t size, + const upb_ExtensionRegistry* extreg, + int options, upb_Arena* arena) { + envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash* ret = envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_new(arena); + if (!ret) return NULL; + if (upb_Decode(buf, size, ret, &envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_msginit, extreg, options, arena) != + kUpb_DecodeStatus_Ok) { + return NULL; + } + return ret; +} +UPB_INLINE char* envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_serialize(const envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash* msg, upb_Arena* arena, size_t* len) { + return upb_Encode(msg, &envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_msginit, 0, arena, len); +} +UPB_INLINE char* envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_serialize_ex(const envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash* msg, int options, + upb_Arena* arena, size_t* len) { + return upb_Encode(msg, &envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_msginit, options, arena, len); +} +UPB_INLINE void envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_clear_hash_function(const envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash* msg) { + *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = 0; +} +UPB_INLINE int32_t envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_hash_function(const envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash* msg) { + return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); +} +UPB_INLINE bool envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_has_minimum_ring_size(const envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash* msg) { + return _upb_hasbit(msg, 1); +} +UPB_INLINE void envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_clear_minimum_ring_size(const envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash* msg) { + *UPB_PTR_AT(msg, UPB_SIZE(12, 16), const upb_Message*) = NULL; +} +UPB_INLINE const struct google_protobuf_UInt64Value* envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_minimum_ring_size(const envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash* msg) { + return *UPB_PTR_AT(msg, UPB_SIZE(12, 16), const struct google_protobuf_UInt64Value*); +} +UPB_INLINE bool envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_has_maximum_ring_size(const envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash* msg) { + return _upb_hasbit(msg, 2); +} +UPB_INLINE void envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_clear_maximum_ring_size(const envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash* msg) { + *UPB_PTR_AT(msg, UPB_SIZE(16, 24), const upb_Message*) = NULL; +} +UPB_INLINE const struct google_protobuf_UInt64Value* envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_maximum_ring_size(const envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash* msg) { + return *UPB_PTR_AT(msg, UPB_SIZE(16, 24), const struct google_protobuf_UInt64Value*); +} +UPB_INLINE void envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_clear_use_hostname_for_hashing(const envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash* msg) { + *UPB_PTR_AT(msg, UPB_SIZE(8, 8), bool) = 0; +} +UPB_INLINE bool envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_use_hostname_for_hashing(const envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash* msg) { + return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), bool); +} +UPB_INLINE bool envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_has_hash_balance_factor(const envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash* msg) { + return _upb_hasbit(msg, 3); +} +UPB_INLINE void envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_clear_hash_balance_factor(const envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash* msg) { + *UPB_PTR_AT(msg, UPB_SIZE(20, 32), const upb_Message*) = NULL; +} +UPB_INLINE const struct google_protobuf_UInt32Value* envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_hash_balance_factor(const envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash* msg) { + return *UPB_PTR_AT(msg, UPB_SIZE(20, 32), const struct google_protobuf_UInt32Value*); +} + +UPB_INLINE void envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_set_hash_function(envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash *msg, int32_t value) { + *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value; +} +UPB_INLINE void envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_set_minimum_ring_size(envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash *msg, struct google_protobuf_UInt64Value* value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(12, 16), struct google_protobuf_UInt64Value*) = value; +} +UPB_INLINE struct google_protobuf_UInt64Value* envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_mutable_minimum_ring_size(envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash* msg, upb_Arena* arena) { + struct google_protobuf_UInt64Value* sub = (struct google_protobuf_UInt64Value*)envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_minimum_ring_size(msg); + if (sub == NULL) { + sub = (struct google_protobuf_UInt64Value*)_upb_Message_New(&google_protobuf_UInt64Value_msginit, arena); + if (!sub) return NULL; + envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_set_minimum_ring_size(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_set_maximum_ring_size(envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash *msg, struct google_protobuf_UInt64Value* value) { + _upb_sethas(msg, 2); + *UPB_PTR_AT(msg, UPB_SIZE(16, 24), struct google_protobuf_UInt64Value*) = value; +} +UPB_INLINE struct google_protobuf_UInt64Value* envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_mutable_maximum_ring_size(envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash* msg, upb_Arena* arena) { + struct google_protobuf_UInt64Value* sub = (struct google_protobuf_UInt64Value*)envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_maximum_ring_size(msg); + if (sub == NULL) { + sub = (struct google_protobuf_UInt64Value*)_upb_Message_New(&google_protobuf_UInt64Value_msginit, arena); + if (!sub) return NULL; + envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_set_maximum_ring_size(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_set_use_hostname_for_hashing(envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash *msg, bool value) { + *UPB_PTR_AT(msg, UPB_SIZE(8, 8), bool) = value; +} +UPB_INLINE void envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_set_hash_balance_factor(envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash *msg, struct google_protobuf_UInt32Value* value) { + _upb_sethas(msg, 3); + *UPB_PTR_AT(msg, UPB_SIZE(20, 32), struct google_protobuf_UInt32Value*) = value; +} +UPB_INLINE struct google_protobuf_UInt32Value* envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_mutable_hash_balance_factor(envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash* msg, upb_Arena* arena) { + struct google_protobuf_UInt32Value* sub = (struct google_protobuf_UInt32Value*)envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_hash_balance_factor(msg); + if (sub == NULL) { + sub = (struct google_protobuf_UInt32Value*)_upb_Message_New(&google_protobuf_UInt32Value_msginit, arena); + if (!sub) return NULL; + envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_set_hash_balance_factor(msg, sub); + } + return sub; +} + +extern const upb_MiniTable_File envoy_extensions_load_balancing_policies_ring_hash_v3_ring_hash_proto_upb_file_layout; + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#include "upb/port_undef.inc" + +#endif /* ENVOY_EXTENSIONS_LOAD_BALANCING_POLICIES_RING_HASH_V3_RING_HASH_PROTO_UPB_H_ */ diff --git a/src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/wrr_locality/v3/wrr_locality.upb.c b/src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/wrr_locality/v3/wrr_locality.upb.c new file mode 100644 index 00000000000..4e798231c59 --- /dev/null +++ b/src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/wrr_locality/v3/wrr_locality.upb.c @@ -0,0 +1,46 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * envoy/extensions/load_balancing_policies/wrr_locality/v3/wrr_locality.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#include +#include "upb/msg_internal.h" +#include "envoy/extensions/load_balancing_policies/wrr_locality/v3/wrr_locality.upb.h" +#include "envoy/config/cluster/v3/cluster.upb.h" +#include "udpa/annotations/status.upb.h" +#include "validate/validate.upb.h" + +#include "upb/port_def.inc" + +static const upb_MiniTable_Sub envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality_submsgs[1] = { + {.submsg = &envoy_config_cluster_v3_LoadBalancingPolicy_msginit}, +}; + +static const upb_MiniTable_Field envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality__fields[1] = { + {1, UPB_SIZE(4, 8), UPB_SIZE(1, 1), 0, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality_msginit = { + &envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality_submsgs[0], + &envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality__fields[0], + UPB_SIZE(8, 24), 1, kUpb_ExtMode_NonExtendable, 1, 255, 0, +}; + +static const upb_MiniTable *messages_layout[1] = { + &envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality_msginit, +}; + +const upb_MiniTable_File envoy_extensions_load_balancing_policies_wrr_locality_v3_wrr_locality_proto_upb_file_layout = { + messages_layout, + NULL, + NULL, + 1, + 0, + 0, +}; + +#include "upb/port_undef.inc" + diff --git a/src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/wrr_locality/v3/wrr_locality.upb.h b/src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/wrr_locality/v3/wrr_locality.upb.h new file mode 100644 index 00000000000..76e5ab36882 --- /dev/null +++ b/src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/wrr_locality/v3/wrr_locality.upb.h @@ -0,0 +1,94 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * envoy/extensions/load_balancing_policies/wrr_locality/v3/wrr_locality.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#ifndef ENVOY_EXTENSIONS_LOAD_BALANCING_POLICIES_WRR_LOCALITY_V3_WRR_LOCALITY_PROTO_UPB_H_ +#define ENVOY_EXTENSIONS_LOAD_BALANCING_POLICIES_WRR_LOCALITY_V3_WRR_LOCALITY_PROTO_UPB_H_ + +#include "upb/msg_internal.h" +#include "upb/decode.h" +#include "upb/decode_fast.h" +#include "upb/encode.h" + +#include "upb/port_def.inc" + +#ifdef __cplusplus +extern "C" { +#endif + +struct envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality; +typedef struct envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality; +extern const upb_MiniTable envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality_msginit; +struct envoy_config_cluster_v3_LoadBalancingPolicy; +extern const upb_MiniTable envoy_config_cluster_v3_LoadBalancingPolicy_msginit; + + + +/* envoy.extensions.load_balancing_policies.wrr_locality.v3.WrrLocality */ + +UPB_INLINE envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality* envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality_new(upb_Arena* arena) { + return (envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality*)_upb_Message_New(&envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality_msginit, arena); +} +UPB_INLINE envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality* envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality_parse(const char* buf, size_t size, upb_Arena* arena) { + envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality* ret = envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality_new(arena); + if (!ret) return NULL; + if (upb_Decode(buf, size, ret, &envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) { + return NULL; + } + return ret; +} +UPB_INLINE envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality* envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality_parse_ex(const char* buf, size_t size, + const upb_ExtensionRegistry* extreg, + int options, upb_Arena* arena) { + envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality* ret = envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality_new(arena); + if (!ret) return NULL; + if (upb_Decode(buf, size, ret, &envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality_msginit, extreg, options, arena) != + kUpb_DecodeStatus_Ok) { + return NULL; + } + return ret; +} +UPB_INLINE char* envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality_serialize(const envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality* msg, upb_Arena* arena, size_t* len) { + return upb_Encode(msg, &envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality_msginit, 0, arena, len); +} +UPB_INLINE char* envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality_serialize_ex(const envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality* msg, int options, + upb_Arena* arena, size_t* len) { + return upb_Encode(msg, &envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality_msginit, options, arena, len); +} +UPB_INLINE bool envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality_has_endpoint_picking_policy(const envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality* msg) { + return _upb_hasbit(msg, 1); +} +UPB_INLINE void envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality_clear_endpoint_picking_policy(const envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality* msg) { + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), const upb_Message*) = NULL; +} +UPB_INLINE const struct envoy_config_cluster_v3_LoadBalancingPolicy* envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality_endpoint_picking_policy(const envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality* msg) { + return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), const struct envoy_config_cluster_v3_LoadBalancingPolicy*); +} + +UPB_INLINE void envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality_set_endpoint_picking_policy(envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality *msg, struct envoy_config_cluster_v3_LoadBalancingPolicy* value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), struct envoy_config_cluster_v3_LoadBalancingPolicy*) = value; +} +UPB_INLINE struct envoy_config_cluster_v3_LoadBalancingPolicy* envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality_mutable_endpoint_picking_policy(envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality* msg, upb_Arena* arena) { + struct envoy_config_cluster_v3_LoadBalancingPolicy* sub = (struct envoy_config_cluster_v3_LoadBalancingPolicy*)envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality_endpoint_picking_policy(msg); + if (sub == NULL) { + sub = (struct envoy_config_cluster_v3_LoadBalancingPolicy*)_upb_Message_New(&envoy_config_cluster_v3_LoadBalancingPolicy_msginit, arena); + if (!sub) return NULL; + envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality_set_endpoint_picking_policy(msg, sub); + } + return sub; +} + +extern const upb_MiniTable_File envoy_extensions_load_balancing_policies_wrr_locality_v3_wrr_locality_proto_upb_file_layout; + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#include "upb/port_undef.inc" + +#endif /* ENVOY_EXTENSIONS_LOAD_BALANCING_POLICIES_WRR_LOCALITY_V3_WRR_LOCALITY_PROTO_UPB_H_ */ diff --git a/src/core/ext/xds/xds_common_types.cc b/src/core/ext/xds/xds_common_types.cc index b4389d7c672..7942c35da75 100644 --- a/src/core/ext/xds/xds_common_types.cc +++ b/src/core/ext/xds/xds_common_types.cc @@ -30,7 +30,6 @@ #include "absl/strings/str_cat.h" #include "absl/strings/str_format.h" #include "absl/strings/str_join.h" -#include "absl/strings/strip.h" #include "envoy/extensions/transport_sockets/tls/v3/common.upb.h" #include "envoy/extensions/transport_sockets/tls/v3/tls.upb.h" #include "envoy/type/matcher/v3/regex.upb.h" @@ -376,24 +375,29 @@ grpc_error_handle CommonTlsContext::Parse( &errors); } -grpc_error_handle ExtractExtensionTypeName(const XdsEncodingContext& context, - const google_protobuf_Any* any, - absl::string_view* extension_type) { - *extension_type = UpbStringToAbsl(google_protobuf_Any_type_url(any)); - if (*extension_type == "type.googleapis.com/xds.type.v3.TypedStruct" || - *extension_type == "type.googleapis.com/udpa.type.v1.TypedStruct") { +absl::StatusOr ExtractExtensionTypeName( + const XdsEncodingContext& context, const google_protobuf_Any* any) { + ExtractExtensionTypeNameResult result; + result.type = UpbStringToAbsl(google_protobuf_Any_type_url(any)); + if (result.type == "type.googleapis.com/xds.type.v3.TypedStruct" || + result.type == "type.googleapis.com/udpa.type.v1.TypedStruct") { upb_StringView any_value = google_protobuf_Any_value(any); - const auto* typed_struct = xds_type_v3_TypedStruct_parse( + result.typed_struct = xds_type_v3_TypedStruct_parse( any_value.data, any_value.size, context.arena); - if (typed_struct == nullptr) { - return GRPC_ERROR_CREATE_FROM_STATIC_STRING( + if (result.typed_struct == nullptr) { + return absl::InvalidArgumentError( "could not parse TypedStruct from extension"); } - *extension_type = - UpbStringToAbsl(xds_type_v3_TypedStruct_type_url(typed_struct)); + result.type = + UpbStringToAbsl(xds_type_v3_TypedStruct_type_url(result.typed_struct)); } - *extension_type = absl::StripPrefix(*extension_type, "type.googleapis.com/"); - return GRPC_ERROR_NONE; + size_t pos = result.type.rfind('/'); + if (pos == absl::string_view::npos || pos == result.type.size() - 1) { + return absl::InvalidArgumentError( + absl::StrCat("Invalid type_url ", result.type)); + } + result.type = result.type.substr(pos + 1); + return result; } } // namespace grpc_core diff --git a/src/core/ext/xds/xds_common_types.h b/src/core/ext/xds/xds_common_types.h index 19704a1d5fc..fe258417e58 100644 --- a/src/core/ext/xds/xds_common_types.h +++ b/src/core/ext/xds/xds_common_types.h @@ -22,10 +22,12 @@ #include #include +#include "absl/status/statusor.h" #include "absl/strings/string_view.h" #include "envoy/extensions/transport_sockets/tls/v3/tls.upb.h" #include "google/protobuf/any.upb.h" #include "google/protobuf/duration.upb.h" +#include "xds/type/v3/typed_struct.upb.h" #include "src/core/ext/xds/upb_utils.h" #include "src/core/lib/gprpp/time.h" @@ -88,9 +90,13 @@ struct CommonTlsContext { CommonTlsContext* common_tls_context); }; -grpc_error_handle ExtractExtensionTypeName(const XdsEncodingContext& context, - const google_protobuf_Any* any, - absl::string_view* extension_type); +struct ExtractExtensionTypeNameResult { + absl::string_view type; + xds_type_v3_TypedStruct* typed_struct = nullptr; +}; + +absl::StatusOr ExtractExtensionTypeName( + const XdsEncodingContext& context, const google_protobuf_Any* any); } // namespace grpc_core diff --git a/src/core/ext/xds/xds_lb_policy_registry.cc b/src/core/ext/xds/xds_lb_policy_registry.cc new file mode 100644 index 00000000000..097cc416691 --- /dev/null +++ b/src/core/ext/xds/xds_lb_policy_registry.cc @@ -0,0 +1,291 @@ +// +// Copyright 2022 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#include + +#include "src/core/ext/xds/xds_lb_policy_registry.h" + +#include + +#include +#include +#include +#include + +#include "absl/memory/memory.h" +#include "absl/status/status.h" +#include "absl/strings/str_cat.h" +#include "absl/strings/str_format.h" +#include "envoy/config/core/v3/extension.upb.h" +#include "envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb.h" +#include "envoy/extensions/load_balancing_policies/wrr_locality/v3/wrr_locality.upb.h" +#include "google/protobuf/any.upb.h" +#include "google/protobuf/struct.upb.h" +#include "google/protobuf/struct.upbdefs.h" +#include "google/protobuf/wrappers.upb.h" +#include "upb/json_encode.h" +#include "upb/upb.h" +#include "upb/upb.hpp" +#include "xds/type/v3/typed_struct.upb.h" + +#include "src/core/ext/filters/client_channel/lb_policy_registry.h" +#include "src/core/ext/xds/upb_utils.h" +#include "src/core/ext/xds/xds_common_types.h" +#include "src/core/lib/iomgr/error.h" + +namespace grpc_core { + +namespace { + +class RingHashLbPolicyConfigFactory + : public XdsLbPolicyRegistry::ConfigFactory { + public: + absl::StatusOr ConvertXdsLbPolicyConfig( + const XdsEncodingContext& context, absl::string_view configuration, + int /* recursion_depth */) override { + const auto* resource = + envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_parse( + configuration.data(), configuration.size(), context.arena); + if (resource == nullptr) { + return absl::InvalidArgumentError( + "Can't decode RingHash loadbalancing policy"); + } + if (envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_hash_function( + resource) != + envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_XX_HASH) { + return absl::InvalidArgumentError( + "Invalid hash function provided for RingHash loadbalancing policy. " + "Only XX_HASH is supported."); + } + Json::Object json; + const auto* min_ring_size = + envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_minimum_ring_size( + resource); + if (min_ring_size != nullptr) { + json.emplace("minRingSize", + google_protobuf_UInt64Value_value(min_ring_size)); + } + const auto* max_ring_size = + envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_maximum_ring_size( + resource); + if (max_ring_size != nullptr) { + json.emplace("maxRingSize", + google_protobuf_UInt64Value_value(max_ring_size)); + } + return Json::Object{{"ring_hash_experimental", std::move(json)}}; + } + + absl::string_view type() override { return Type(); } + + static absl::string_view Type() { + return "envoy.extensions.load_balancing_policies.ring_hash.v3.RingHash"; + } +}; + +class RoundRobinLbPolicyConfigFactory + : public XdsLbPolicyRegistry::ConfigFactory { + public: + absl::StatusOr ConvertXdsLbPolicyConfig( + const XdsEncodingContext& /* context */, + absl::string_view /* configuration */, + int /* recursion_depth */) override { + return Json::Object{{"round_robin", Json::Object()}}; + } + + absl::string_view type() override { return Type(); } + + static absl::string_view Type() { + return "envoy.extensions.load_balancing_policies.round_robin.v3.RoundRobin"; + } +}; + +class WrrLocalityLbPolicyConfigFactory + : public XdsLbPolicyRegistry::ConfigFactory { + public: + absl::StatusOr ConvertXdsLbPolicyConfig( + const XdsEncodingContext& context, absl::string_view configuration, + int recursion_depth) override { + const auto* resource = + envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality_parse( + configuration.data(), configuration.size(), context.arena); + if (resource == nullptr) { + return absl::InvalidArgumentError( + "Can't decode WrrLocality loadbalancing policy"); + } + const auto* endpoint_picking_policy = + envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality_endpoint_picking_policy( + resource); + if (endpoint_picking_policy == nullptr) { + return absl::InvalidArgumentError( + "WrrLocality: endpoint_picking_policy not found"); + } + auto child_policy = XdsLbPolicyRegistry::ConvertXdsLbPolicyConfig( + context, endpoint_picking_policy, recursion_depth + 1); + if (!child_policy.ok()) { + return absl::InvalidArgumentError( + absl::StrCat("Error parsing WrrLocality load balancing policy: ", + child_policy.status().message())); + } + return Json::Object{ + {"xds_wrr_locality_experimental", + Json::Object{{"child_policy", *std::move(child_policy)}}}}; + } + + absl::string_view type() override { return Type(); } + + static absl::string_view Type() { + return "envoy.extensions.load_balancing_policies.wrr_locality.v3." + "WrrLocality"; + } +}; + +absl::StatusOr ParseStructToJson(const XdsEncodingContext& context, + const google_protobuf_Struct* resource) { + upb::Status status; + const auto* msg_def = google_protobuf_Struct_getmsgdef(context.symtab); + size_t json_size = upb_JsonEncode(resource, msg_def, context.symtab, 0, + nullptr, 0, status.ptr()); + if (json_size == static_cast(-1)) { + return absl::InvalidArgumentError( + absl::StrCat("Error parsing google::Protobuf::Struct: ", + upb_Status_ErrorMessage(status.ptr()))); + } + void* buf = upb_Arena_Malloc(context.arena, json_size + 1); + upb_JsonEncode(resource, msg_def, context.symtab, 0, + reinterpret_cast(buf), json_size + 1, status.ptr()); + grpc_error_handle error = GRPC_ERROR_NONE; + auto json = Json::Parse(reinterpret_cast(buf), &error); + if (error != GRPC_ERROR_NONE) { + // This should not happen + auto ret_status = absl::InternalError( + absl::StrCat("Error parsing JSON form of google::Protobuf::Struct " + "produced by upb library: ", + grpc_error_std_string(error))); + GRPC_ERROR_UNREF(error); + return ret_status; + } + return json; +} + +} // namespace + +// +// XdsLbPolicyRegistry +// + +absl::StatusOr XdsLbPolicyRegistry::ConvertXdsLbPolicyConfig( + const XdsEncodingContext& context, + const envoy_config_cluster_v3_LoadBalancingPolicy* lb_policy, + int recursion_depth) { + constexpr int kMaxRecursionDepth = 16; + if (recursion_depth >= kMaxRecursionDepth) { + return absl::InvalidArgumentError( + absl::StrFormat("LoadBalancingPolicy configuration has a recursion " + "depth of more than %d.", + kMaxRecursionDepth)); + } + size_t size = 0; + const auto* policies = + envoy_config_cluster_v3_LoadBalancingPolicy_policies(lb_policy, &size); + for (size_t i = 0; i < size; ++i) { + absl::StatusOr policy; + const auto* typed_extension_config = + envoy_config_cluster_v3_LoadBalancingPolicy_Policy_typed_extension_config( + policies[i]); + if (typed_extension_config == nullptr) { + return absl::InvalidArgumentError( + "Error parsing LoadBalancingPolicy::Policy - Missing " + "typed_extension_config field"); + } + const auto* typed_config = + envoy_config_core_v3_TypedExtensionConfig_typed_config( + typed_extension_config); + if (typed_config == nullptr) { + return absl::InvalidArgumentError( + "Error parsing LoadBalancingPolicy::Policy - Missing " + "TypedExtensionConfig::typed_config field"); + } + auto type = ExtractExtensionTypeName(context, typed_config); + if (!type.ok()) { + return absl::InvalidArgumentError(absl::StrCat( + "Error parsing " + "LoadBalancingPolicy::Policy::TypedExtensionConfig::typed_config: ", + type.status().message())); + } + absl::string_view value = + UpbStringToAbsl(google_protobuf_Any_value(typed_config)); + auto config_factory_it = Get()->policy_config_factories_.find(type->type); + if (config_factory_it != Get()->policy_config_factories_.end()) { + policy = config_factory_it->second->ConvertXdsLbPolicyConfig( + context, value, recursion_depth); + if (!policy.ok()) { + return absl::InvalidArgumentError( + absl::StrCat("Error parsing " + "LoadBalancingPolicy::Policy::TypedExtensionConfig::" + "typed_config to JSON: ", + policy.status().message())); + } + } else if (type->typed_struct != nullptr) { + // Custom lb policy config + std::string custom_type = std::string(type->type); + if (!LoadBalancingPolicyRegistry::LoadBalancingPolicyExists( + custom_type.c_str(), nullptr)) { + // Skip unsupported custom lb policy. + continue; + } + // Convert typed struct to json. + auto value = xds_type_v3_TypedStruct_value(type->typed_struct); + if (value == nullptr) { + policy = Json::Object{{std::move(custom_type), Json() /* null */}}; + } else { + auto parsed_value = ParseStructToJson(context, value); + if (!parsed_value.ok()) { + return absl::InvalidArgumentError(absl::StrCat( + "Error parsing LoadBalancingPolicy: Custom Policy: ", custom_type, + ": ", parsed_value.status().message())); + } + policy = + Json::Object{{std::move(custom_type), *(std::move(parsed_value))}}; + } + } else { + // Unsupported type. Skipping entry. + continue; + } + return Json::Array{std::move(policy.value())}; + } + return absl::InvalidArgumentError( + "No supported load balancing policy config found."); +} + +XdsLbPolicyRegistry::XdsLbPolicyRegistry() { + policy_config_factories_.emplace( + RingHashLbPolicyConfigFactory::Type(), + absl::make_unique()); + policy_config_factories_.emplace( + RoundRobinLbPolicyConfigFactory::Type(), + absl::make_unique()); + policy_config_factories_.emplace( + WrrLocalityLbPolicyConfigFactory::Type(), + absl::make_unique()); +} + +XdsLbPolicyRegistry* XdsLbPolicyRegistry::Get() { + // This is thread-safe since C++11 + static XdsLbPolicyRegistry* instance = new XdsLbPolicyRegistry(); + return instance; +} + +} // namespace grpc_core diff --git a/src/core/ext/xds/xds_lb_policy_registry.h b/src/core/ext/xds/xds_lb_policy_registry.h new file mode 100644 index 00000000000..4f1ba9f65e0 --- /dev/null +++ b/src/core/ext/xds/xds_lb_policy_registry.h @@ -0,0 +1,72 @@ +// +// Copyright 2022 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#ifndef GRPC_CORE_EXT_XDS_XDS_LB_POLICY_REGISTRY_H +#define GRPC_CORE_EXT_XDS_XDS_LB_POLICY_REGISTRY_H + +#include + +#include +#include + +#include "absl/status/statusor.h" +#include "absl/strings/string_view.h" +#include "envoy/config/cluster/v3/cluster.upb.h" + +#include "src/core/ext/xds/upb_utils.h" +#include "src/core/lib/json/json.h" + +namespace grpc_core { + +// A registry that maintans a set of converters that are able to map xDS +// loadbalancing policy configurations to gRPC's JSON format. +class XdsLbPolicyRegistry { + public: + class ConfigFactory { + public: + virtual ~ConfigFactory() {} + virtual absl::StatusOr ConvertXdsLbPolicyConfig( + const XdsEncodingContext& context, absl::string_view configuration, + int recursion_depth) = 0; + + virtual absl::string_view type() = 0; + }; + + // Converts an xDS cluster load balancing policy message to gRPC's JSON + // format. An error is returned if none of the lb policies in the list are + // supported, or if a supported lb policy configuration conversion fails. \a + // recursion_depth indicates the current depth of the tree if lb_policy + // configuration recursively holds other lb policies. + static absl::StatusOr ConvertXdsLbPolicyConfig( + const XdsEncodingContext& context, + const envoy_config_cluster_v3_LoadBalancingPolicy* lb_policy, + int recursion_depth = 0); + + private: + XdsLbPolicyRegistry(); + + static XdsLbPolicyRegistry* Get(); + + // A map of config factories that goes from the type of the lb policy config + // to the config factory. + std::map> + policy_config_factories_; +}; + +} // namespace grpc_core + +#endif // GRPC_CORE_EXT_XDS_XDS_LB_POLICY_REGISTRY_H diff --git a/src/core/ext/xds/xds_listener.cc b/src/core/ext/xds/xds_listener.cc index 7b983472201..a8bfa81772c 100644 --- a/src/core/ext/xds/xds_listener.cc +++ b/src/core/ext/xds/xds_listener.cc @@ -60,6 +60,7 @@ #include "src/core/lib/iomgr/error.h" #include "src/core/lib/iomgr/sockaddr.h" #include "src/core/lib/json/json.h" +#include "src/core/lib/transport/error_utils.h" namespace grpc_core { @@ -350,30 +351,30 @@ grpc_error_handle HttpConnectionManagerParse( return GRPC_ERROR_CREATE_FROM_CPP_STRING( absl::StrCat("no filter config specified for filter name ", name)); } - absl::string_view filter_type; - grpc_error_handle error = - ExtractExtensionTypeName(context, any, &filter_type); - if (error != GRPC_ERROR_NONE) return error; + auto filter_type = ExtractExtensionTypeName(context, any); + if (!filter_type.ok()) { + return absl_status_to_grpc_error(filter_type.status()); + } const XdsHttpFilterImpl* filter_impl = - XdsHttpFilterRegistry::GetFilterForType(filter_type); + XdsHttpFilterRegistry::GetFilterForType(filter_type->type); if (filter_impl == nullptr) { if (is_optional) continue; - return GRPC_ERROR_CREATE_FROM_CPP_STRING( - absl::StrCat("no filter registered for config type ", filter_type)); + return GRPC_ERROR_CREATE_FROM_CPP_STRING(absl::StrCat( + "no filter registered for config type ", filter_type->type)); } if ((is_client && !filter_impl->IsSupportedOnClients()) || (!is_client && !filter_impl->IsSupportedOnServers())) { if (is_optional) continue; - return GRPC_ERROR_CREATE_FROM_CPP_STRING( - absl::StrFormat("Filter %s is not supported on %s", filter_type, - is_client ? "clients" : "servers")); + return GRPC_ERROR_CREATE_FROM_CPP_STRING(absl::StrFormat( + "Filter %s is not supported on %s", filter_type->type, + is_client ? "clients" : "servers")); } absl::StatusOr filter_config = filter_impl->GenerateFilterConfig(google_protobuf_Any_value(any), context.arena); if (!filter_config.ok()) { return GRPC_ERROR_CREATE_FROM_CPP_STRING(absl::StrCat( - "filter config for type ", filter_type, + "filter config for type ", filter_type->type, " failed to parse: ", StatusToString(filter_config.status()))); } http_connection_manager->http_filters.emplace_back( diff --git a/src/core/ext/xds/xds_route_config.cc b/src/core/ext/xds/xds_route_config.cc index 24c407a272d..af83037eda2 100644 --- a/src/core/ext/xds/xds_route_config.cc +++ b/src/core/ext/xds/xds_route_config.cc @@ -364,19 +364,19 @@ grpc_error_handle ClusterSpecifierPluginParse( return GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Could not obtrain TypedExtensionConfig for plugin config."); } - absl::string_view plugin_type; - grpc_error_handle error = - ExtractExtensionTypeName(context, any, &plugin_type); - if (error != GRPC_ERROR_NONE) return error; + auto plugin_type = ExtractExtensionTypeName(context, any); + if (!plugin_type.ok()) { + return absl_status_to_grpc_error(plugin_type.status()); + } bool is_optional = envoy_config_route_v3_ClusterSpecifierPlugin_is_optional( cluster_specifier_plugin[i]); const XdsClusterSpecifierPluginImpl* cluster_specifier_plugin_impl = - XdsClusterSpecifierPluginRegistry::GetPluginForType(plugin_type); + XdsClusterSpecifierPluginRegistry::GetPluginForType(plugin_type->type); std::string lb_policy_config; if (cluster_specifier_plugin_impl == nullptr) { if (!is_optional) { - return GRPC_ERROR_CREATE_FROM_CPP_STRING( - absl::StrCat("Unknown ClusterSpecifierPlugin type ", plugin_type)); + return GRPC_ERROR_CREATE_FROM_CPP_STRING(absl::StrCat( + "Unknown ClusterSpecifierPlugin type ", plugin_type->type)); } // Optional plugin, leave lb_policy_config empty. } else { @@ -629,22 +629,23 @@ grpc_error_handle ParseTypedPerFilterConfig( absl::StrCat("no filter config specified for filter name ", key)); } } - grpc_error_handle error = - ExtractExtensionTypeName(context, any, &filter_type); - if (error != GRPC_ERROR_NONE) return error; + auto type = ExtractExtensionTypeName(context, any); + if (!type.ok()) { + return absl_status_to_grpc_error(type.status()); + } const XdsHttpFilterImpl* filter_impl = - XdsHttpFilterRegistry::GetFilterForType(filter_type); + XdsHttpFilterRegistry::GetFilterForType(type->type); if (filter_impl == nullptr) { if (is_optional) continue; return GRPC_ERROR_CREATE_FROM_CPP_STRING( - absl::StrCat("no filter registered for config type ", filter_type)); + absl::StrCat("no filter registered for config type ", type->type)); } absl::StatusOr filter_config = filter_impl->GenerateFilterConfigOverride( google_protobuf_Any_value(any), context.arena); if (!filter_config.ok()) { return GRPC_ERROR_CREATE_FROM_CPP_STRING(absl::StrCat( - "filter config for type ", filter_type, + "filter config for type ", type->type, " failed to parse: ", StatusToString(filter_config.status()))); } (*typed_per_filter_config)[std::string(key)] = std::move(*filter_config); diff --git a/src/proto/grpc/testing/xds/v3/BUILD b/src/proto/grpc/testing/xds/v3/BUILD index 4ef12c19a41..8fe155cba3b 100644 --- a/src/proto/grpc/testing/xds/v3/BUILD +++ b/src/proto/grpc/testing/xds/v3/BUILD @@ -92,6 +92,7 @@ grpc_proto_library( "base_proto", "config_source_proto", "endpoint_proto", + "extension_proto", "outlier_detection_proto", ], ) @@ -375,6 +376,49 @@ grpc_proto_library( ], ) +grpc_proto_library( + name = "ring_hash_proto", + srcs = [ + "ring_hash.proto", + ], + well_known_protos = True, +) + +grpc_proto_library( + name = "round_robin_proto", + srcs = [ + "round_robin.proto", + ], + well_known_protos = True, +) + +grpc_proto_library( + name = "wrr_locality_proto", + srcs = [ + "wrr_locality.proto", + ], + well_known_protos = True, + deps = [ + "cluster_proto", + ], +) + +grpc_proto_library( + name = "typed_struct_proto", + srcs = [ + "typed_struct.proto", + ], + well_known_protos = True, +) + +grpc_proto_library( + name = "udpa_typed_struct_proto", + srcs = [ + "udpa_typed_struct.proto", + ], + well_known_protos = True, +) + py_proto_library( name = "csds_py_pb2", deps = [":_csds_proto_only"], diff --git a/src/proto/grpc/testing/xds/v3/cluster.proto b/src/proto/grpc/testing/xds/v3/cluster.proto index 10ebe2780f6..dcdcc82a50d 100644 --- a/src/proto/grpc/testing/xds/v3/cluster.proto +++ b/src/proto/grpc/testing/xds/v3/cluster.proto @@ -21,6 +21,7 @@ package envoy.config.cluster.v3; import "src/proto/grpc/testing/xds/v3/base.proto"; import "src/proto/grpc/testing/xds/v3/config_source.proto"; import "src/proto/grpc/testing/xds/v3/endpoint.proto"; +import "src/proto/grpc/testing/xds/v3/extension.proto"; import "src/proto/grpc/testing/xds/v3/outlier_detection.proto"; import "google/protobuf/any.proto"; @@ -224,6 +225,10 @@ message Cluster { // will be set up with plaintext. core.v3.TransportSocket transport_socket = 24; + // If this field is set and is supported by the client, it will supersede the value of + // :ref:`lb_policy`. + LoadBalancingPolicy load_balancing_policy = 41; + // [#not-implemented-hide:] // If present, tells the client where to send load reports via LRS. If not present, the // client will fall back to a client-side default, which may be either (a) don't send any @@ -240,3 +245,37 @@ message Cluster { // from the LRS stream here.] core.v3.ConfigSource lrs_server = 42; } + +// Extensible load balancing policy configuration. +// +// Every LB policy defined via this mechanism will be identified via a unique name using reverse +// DNS notation. If the policy needs configuration parameters, it must define a message for its +// own configuration, which will be stored in the config field. The name of the policy will tell +// clients which type of message they should expect to see in the config field. +// +// Note that there are cases where it is useful to be able to independently select LB policies +// for choosing a locality and for choosing an endpoint within that locality. For example, a +// given deployment may always use the same policy to choose the locality, but for choosing the +// endpoint within the locality, some clusters may use weighted-round-robin, while others may +// use some sort of session-based balancing. +// +// This can be accomplished via hierarchical LB policies, where the parent LB policy creates a +// child LB policy for each locality. For each request, the parent chooses the locality and then +// delegates to the child policy for that locality to choose the endpoint within the locality. +// +// To facilitate this, the config message for the top-level LB policy may include a field of +// type LoadBalancingPolicy that specifies the child policy. +message LoadBalancingPolicy { + message Policy { + reserved 2, 1, 3; + + reserved "config", "name", "typed_config"; + + core.v3.TypedExtensionConfig typed_extension_config = 4; + } + + // Each client will iterate over the list in order and stop at the first policy that it + // supports. This provides a mechanism for starting to use new LB policies that are not yet + // supported by all clients. + repeated Policy policies = 1; +} diff --git a/src/proto/grpc/testing/xds/v3/ring_hash.proto b/src/proto/grpc/testing/xds/v3/ring_hash.proto new file mode 100644 index 00000000000..e8f61cfc7ac --- /dev/null +++ b/src/proto/grpc/testing/xds/v3/ring_hash.proto @@ -0,0 +1,59 @@ +// Copyright 2022 The gRPC Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Local copy of Envoy xDS proto file, used for testing only. + +syntax = "proto3"; + +package envoy.extensions.load_balancing_policies.ring_hash.v3; + +import "google/protobuf/wrappers.proto"; + +// [#protodoc-title: Ring Hash Load Balancing Policy] + +// This configuration allows the built-in RING_HASH LB policy to be configured via the LB policy +// extension point. See the :ref:`load balancing architecture overview +// ` for more information. +// [#extension: envoy.clusters.lb_policy] +// [#next-free-field: 6] +message RingHash { + // The hash function used to hash hosts onto the ketama ring. + enum HashFunction { + // Currently defaults to XX_HASH. + DEFAULT_HASH = 0; + + // Use `xxHash `_. + XX_HASH = 1; + + // Use `MurmurHash2 `_, this is compatible with + // std:hash in GNU libstdc++ 3.4.20 or above. This is typically the case when compiled + // on Linux and not macOS. + MURMUR_HASH_2 = 2; + } + + // The hash function used to hash hosts onto the ketama ring. The value defaults to + // :ref:`XX_HASH`. + HashFunction hash_function = 1; + + // Minimum hash ring size. The larger the ring is (that is, the more hashes there are for each + // provided host) the better the request distribution will reflect the desired weights. Defaults + // to 1024 entries, and limited to 8M entries. See also + // :ref:`maximum_ring_size`. + google.protobuf.UInt64Value minimum_ring_size = 2; + + // Maximum hash ring size. Defaults to 8M entries, and limited to 8M entries, but can be lowered + // to further constrain resource use. See also + // :ref:`minimum_ring_size`. + google.protobuf.UInt64Value maximum_ring_size = 3; +} diff --git a/src/proto/grpc/testing/xds/v3/round_robin.proto b/src/proto/grpc/testing/xds/v3/round_robin.proto new file mode 100644 index 00000000000..f4338401a7a --- /dev/null +++ b/src/proto/grpc/testing/xds/v3/round_robin.proto @@ -0,0 +1,28 @@ +// Copyright 2022 The gRPC Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Local copy of Envoy xDS proto file, used for testing only. + +syntax = "proto3"; + +package envoy.extensions.load_balancing_policies.round_robin.v3; + +// [#protodoc-title: Round Robin Load Balancing Policy] + +// This configuration allows the built-in ROUND_ROBIN LB policy to be configured via the LB policy +// extension point. See the :ref:`load balancing architecture overview +// ` for more information. +// [#extension: envoy.clusters.lb_policy] +message RoundRobin { +} diff --git a/src/proto/grpc/testing/xds/v3/typed_struct.proto b/src/proto/grpc/testing/xds/v3/typed_struct.proto new file mode 100644 index 00000000000..f7ba4c524cb --- /dev/null +++ b/src/proto/grpc/testing/xds/v3/typed_struct.proto @@ -0,0 +1,53 @@ +// Copyright 2022 The gRPC Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Local copy of xDS proto file, used for testing only. + +syntax = "proto3"; + +package xds.type.v3; + +import "google/protobuf/struct.proto"; + +// A TypedStruct contains an arbitrary JSON serialized protocol buffer message with a URL that +// describes the type of the serialized message. This is very similar to google.protobuf.Any, +// instead of having protocol buffer binary, this employs google.protobuf.Struct as value. +// +// This message is intended to be embedded inside Any, so it shouldn't be directly referred +// from other UDPA messages. +// +// When packing an opaque extension config, packing the expected type into Any is preferred +// wherever possible for its efficiency. TypedStruct should be used only if a proto descriptor +// is not available, for example if: +// - A control plane sends opaque message that is originally from external source in human readable +// format such as JSON or YAML. +// - The control plane doesn't have the knowledge of the protocol buffer schema hence it cannot +// serialize the message in protocol buffer binary format. +// - The DPLB doesn't have have the knowledge of the protocol buffer schema its plugin or extension +// uses. This has to be indicated in the DPLB capability negotiation. +// +// When a DPLB receives a TypedStruct in Any, it should: +// - Check if the type_url of the TypedStruct matches the type the extension expects. +// - Convert value to the type described in type_url and perform validation. +// TODO(lizan): Figure out how TypeStruct should be used with DPLB extensions that doesn't link +// protobuf descriptor with DPLB itself, (e.g. gRPC LB Plugin, Envoy WASM extensions). +message TypedStruct { + // A URL that uniquely identifies the type of the serialize protocol buffer message. + // This has same semantics and format described in google.protobuf.Any: + // https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/any.proto + string type_url = 1; + + // A JSON representation of the above specified type. + google.protobuf.Struct value = 2; +} diff --git a/src/proto/grpc/testing/xds/v3/udpa_typed_struct.proto b/src/proto/grpc/testing/xds/v3/udpa_typed_struct.proto new file mode 100644 index 00000000000..5a8ef1d32a3 --- /dev/null +++ b/src/proto/grpc/testing/xds/v3/udpa_typed_struct.proto @@ -0,0 +1,53 @@ +// Copyright 2022 The gRPC Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Local copy of xDS proto file, used for testing only. + +syntax = "proto3"; + +package udpa.type.v1; + +import "google/protobuf/struct.proto"; + +// A TypedStruct contains an arbitrary JSON serialized protocol buffer message with a URL that +// describes the type of the serialized message. This is very similar to google.protobuf.Any, +// instead of having protocol buffer binary, this employs google.protobuf.Struct as value. +// +// This message is intended to be embedded inside Any, so it shouldn't be directly referred +// from other UDPA messages. +// +// When packing an opaque extension config, packing the expected type into Any is preferred +// wherever possible for its efficiency. TypedStruct should be used only if a proto descriptor +// is not available, for example if: +// - A control plane sends opaque message that is originally from external source in human readable +// format such as JSON or YAML. +// - The control plane doesn't have the knowledge of the protocol buffer schema hence it cannot +// serialize the message in protocol buffer binary format. +// - The DPLB doesn't have have the knowledge of the protocol buffer schema its plugin or extension +// uses. This has to be indicated in the DPLB capability negotiation. +// +// When a DPLB receives a TypedStruct in Any, it should: +// - Check if the type_url of the TypedStruct matches the type the extension expects. +// - Convert value to the type described in type_url and perform validation. +// TODO(lizan): Figure out how TypeStruct should be used with DPLB extensions that doesn't link +// protobuf descriptor with DPLB itself, (e.g. gRPC LB Plugin, Envoy WASM extensions). +message TypedStruct { + // A URL that uniquely identifies the type of the serialize protocol buffer message. + // This has same semantics and format described in google.protobuf.Any: + // https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/any.proto + string type_url = 1; + + // A JSON representation of the above specified type. + google.protobuf.Struct value = 2; +} diff --git a/src/proto/grpc/testing/xds/v3/wrr_locality.proto b/src/proto/grpc/testing/xds/v3/wrr_locality.proto new file mode 100644 index 00000000000..5c19f407d52 --- /dev/null +++ b/src/proto/grpc/testing/xds/v3/wrr_locality.proto @@ -0,0 +1,31 @@ +// Copyright 2022 The gRPC Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Local copy of Envoy xDS proto file, used for testing only. + +syntax = "proto3"; + +package envoy.extensions.load_balancing_policies.wrr_locality.v3; + +import "src/proto/grpc/testing/xds/v3/cluster.proto"; + +// [#protodoc-title: Weighted Round Robin Locality-Picking Load Balancing Policy] + +// Configuration for the wrr_locality LB policy. See the :ref:`load balancing architecture overview +// ` for more information. +// [#extension: envoy.clusters.lb_policy] +message WrrLocality { + // The child LB policy to create for endpoint-picking within the chosen locality. + config.cluster.v3.LoadBalancingPolicy endpoint_picking_policy = 1; +} diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py index 9ff49129d6a..df1e41a52b8 100644 --- a/src/python/grpcio/grpc_core_dependencies.py +++ b/src/python/grpcio/grpc_core_dependencies.py @@ -183,6 +183,8 @@ CORE_SOURCE_FILES = [ 'src/core/ext/upb-generated/envoy/extensions/filters/http/rbac/v3/rbac.upb.c', 'src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.c', 'src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.c', + 'src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb.c', + 'src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/wrr_locality/v3/wrr_locality.upb.c', 'src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/cert.upb.c', 'src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/common.upb.c', 'src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/secret.upb.c', @@ -408,6 +410,7 @@ CORE_SOURCE_FILES = [ 'src/core/ext/xds/xds_http_fault_filter.cc', 'src/core/ext/xds/xds_http_filters.cc', 'src/core/ext/xds/xds_http_rbac_filter.cc', + 'src/core/ext/xds/xds_lb_policy_registry.cc', 'src/core/ext/xds/xds_listener.cc', 'src/core/ext/xds/xds_resource_type.cc', 'src/core/ext/xds/xds_route_config.cc', diff --git a/test/core/xds/BUILD b/test/core/xds/BUILD index 32ee2b2c0fa..6ba3dee3bf0 100644 --- a/test/core/xds/BUILD +++ b/test/core/xds/BUILD @@ -97,3 +97,23 @@ grpc_cc_test( "//test/core/util:grpc_test_util", ], ) + +grpc_cc_test( + name = "xds_lb_policy_registry_test", + srcs = ["xds_lb_policy_registry_test.cc"], + external_deps = ["gtest"], + language = "C++", + uses_polling = False, + deps = [ + "//:gpr", + "//:grpc", + "//src/proto/grpc/testing/xds/v3:cluster_proto", + "//src/proto/grpc/testing/xds/v3:ring_hash_proto", + "//src/proto/grpc/testing/xds/v3:round_robin_proto", + "//src/proto/grpc/testing/xds/v3:typed_struct_proto", + "//src/proto/grpc/testing/xds/v3:udpa_typed_struct_proto", + "//src/proto/grpc/testing/xds/v3:wrr_locality_proto", + "//test/core/util:grpc_test_util", + "//test/cpp/util:grpc_cli_utils", + ], +) diff --git a/test/core/xds/xds_lb_policy_registry_test.cc b/test/core/xds/xds_lb_policy_registry_test.cc new file mode 100644 index 00000000000..72e8bd41f8b --- /dev/null +++ b/test/core/xds/xds_lb_policy_registry_test.cc @@ -0,0 +1,534 @@ +// +// +// Copyright 2022 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// + +#include "src/core/ext/xds/xds_lb_policy_registry.h" + +#include +#include + +#include "absl/strings/str_format.h" +#include "upb/def.hpp" +#include "upb/upb.h" +#include "upb/upb.hpp" + +#include + +#include "src/core/ext/filters/client_channel/lb_policy_factory.h" +#include "src/core/ext/filters/client_channel/lb_policy_registry.h" +#include "src/proto/grpc/testing/xds/v3/cluster.grpc.pb.h" +#include "src/proto/grpc/testing/xds/v3/ring_hash.grpc.pb.h" +#include "src/proto/grpc/testing/xds/v3/round_robin.grpc.pb.h" +#include "src/proto/grpc/testing/xds/v3/typed_struct.grpc.pb.h" +#include "src/proto/grpc/testing/xds/v3/udpa_typed_struct.grpc.pb.h" +#include "src/proto/grpc/testing/xds/v3/wrr_locality.grpc.pb.h" +#include "test/core/util/test_config.h" +#include "test/cpp/util/config_grpc_cli.h" + +namespace grpc_core { +namespace testing { +namespace { + +using LoadBalancingPolicyProto = + ::envoy::config::cluster::v3::LoadBalancingPolicy; +using ::envoy::extensions::load_balancing_policies::ring_hash::v3::RingHash; +using ::envoy::extensions::load_balancing_policies::round_robin::v3::RoundRobin; +using ::envoy::extensions::load_balancing_policies::wrr_locality::v3:: + WrrLocality; +using ::xds::type::v3::TypedStruct; + +// Uses XdsLbPolicyRegistry to convert +// envoy::config::cluster::v3::LoadBalancingPolicy to gRPC's JSON form. +absl::StatusOr ConvertXdsPolicy(LoadBalancingPolicyProto policy) { + std::string serialized_policy = policy.SerializeAsString(); + upb::Arena arena; + upb::SymbolTable symtab; + XdsEncodingContext context = {nullptr, XdsBootstrap::XdsServer(), + nullptr, symtab.ptr(), + arena.ptr(), true, + nullptr}; + auto* upb_policy = envoy_config_cluster_v3_LoadBalancingPolicy_parse( + serialized_policy.data(), serialized_policy.size(), arena.ptr()); + return XdsLbPolicyRegistry::ConvertXdsLbPolicyConfig(context, upb_policy); +} + +TEST(XdsLbPolicyRegistryTest, EmptyLoadBalancingPolicy) { + auto result = ConvertXdsPolicy(LoadBalancingPolicyProto()); + EXPECT_EQ(result.status().code(), absl::StatusCode::kInvalidArgument); + EXPECT_THAT( + std::string(result.status().message()), + ::testing::HasSubstr("No supported load balancing policy config found")); +} + +TEST(XdsLbPolicyRegistryTest, UnsupportedBuiltinType) { + LoadBalancingPolicyProto policy; + auto* lb_policy = policy.add_policies(); + lb_policy->mutable_typed_extension_config()->mutable_typed_config()->PackFrom( + LoadBalancingPolicyProto()); + auto result = ConvertXdsPolicy(policy); + EXPECT_EQ(result.status().code(), absl::StatusCode::kInvalidArgument); + EXPECT_THAT( + std::string(result.status().message()), + ::testing::HasSubstr("No supported load balancing policy config found")); +} + +TEST(XdsLbPolicyRegistryTest, MissingTypedExtensionConfig) { + LoadBalancingPolicyProto policy; + policy.add_policies(); + auto result = ConvertXdsPolicy(policy); + EXPECT_EQ(result.status().code(), absl::StatusCode::kInvalidArgument); + EXPECT_THAT(std::string(result.status().message()), + ::testing::HasSubstr("Error parsing LoadBalancingPolicy::Policy " + "- Missing typed_extension_config field")); +} + +TEST(XdsLbPolicyRegistryTest, MissingTypedConfig) { + LoadBalancingPolicyProto policy; + auto* lb_policy = policy.add_policies(); + lb_policy->mutable_typed_extension_config(); + auto result = ConvertXdsPolicy(policy); + EXPECT_EQ(result.status().code(), absl::StatusCode::kInvalidArgument); + EXPECT_THAT( + std::string(result.status().message()), + ::testing::HasSubstr("Error parsing LoadBalancingPolicy::Policy - " + "Missing TypedExtensionConfig::typed_config field")); +} + +TEST(XdsLbPolicyRegistryTest, RingHashInvalidHash) { + RingHash ring_hash; + ring_hash.set_hash_function(RingHash::DEFAULT_HASH); + LoadBalancingPolicyProto policy; + auto* lb_policy = policy.add_policies(); + lb_policy->mutable_typed_extension_config()->mutable_typed_config()->PackFrom( + ring_hash); + auto result = ConvertXdsPolicy(policy); + EXPECT_EQ(result.status().code(), absl::StatusCode::kInvalidArgument); + EXPECT_THAT( + std::string(result.status().message()), + ::testing::HasSubstr("Invalid hash function provided for RingHash " + "loadbalancing policy. Only XX_HASH is supported")); +} + +TEST(XdsLbPolicyRegistryTest, RingHashRingSizeDefaults) { + RingHash ring_hash; + ring_hash.set_hash_function(RingHash::XX_HASH); + LoadBalancingPolicyProto policy; + auto* lb_policy = policy.add_policies(); + lb_policy->mutable_typed_extension_config()->mutable_typed_config()->PackFrom( + ring_hash); + auto result = ConvertXdsPolicy(policy); + EXPECT_TRUE(result.ok()); + EXPECT_EQ(result->size(), 1); + grpc_error_handle error = GRPC_ERROR_NONE; + EXPECT_EQ((*result)[0], Json::Parse("{" + "\"ring_hash_experimental\": {" + "}}", + &error)); +} + +TEST(XdsLbPolicyRegistryTest, RingHashRingSizeCustom) { + RingHash ring_hash; + ring_hash.set_hash_function(RingHash::XX_HASH); + ring_hash.mutable_minimum_ring_size()->set_value(1234); + ring_hash.mutable_maximum_ring_size()->set_value(4567); + LoadBalancingPolicyProto policy; + auto* lb_policy = policy.add_policies(); + lb_policy->mutable_typed_extension_config()->mutable_typed_config()->PackFrom( + ring_hash); + auto result = ConvertXdsPolicy(policy); + EXPECT_TRUE(result.ok()); + EXPECT_EQ(result->size(), 1); + grpc_error_handle error = GRPC_ERROR_NONE; + EXPECT_EQ((*result)[0], Json::Parse("{" + "\"ring_hash_experimental\": {" + " \"minRingSize\": 1234," + " \"maxRingSize\": 4567" + "}}", + &error)); +} + +TEST(XdsLbPolicyRegistryTest, RoundRobin) { + LoadBalancingPolicyProto policy; + auto* lb_policy = policy.add_policies(); + lb_policy->mutable_typed_extension_config()->mutable_typed_config()->PackFrom( + RoundRobin()); + auto result = ConvertXdsPolicy(policy); + EXPECT_TRUE(result.ok()); + EXPECT_EQ(result->size(), 1); + grpc_error_handle error = GRPC_ERROR_NONE; + EXPECT_EQ((*result)[0], Json::Parse("{" + "\"round_robin\": {}" + "}", + &error)); +} + +TEST(XdsLbPolicyRegistryTest, WrrLocality) { + WrrLocality wrr_locality; + wrr_locality.mutable_endpoint_picking_policy() + ->add_policies() + ->mutable_typed_extension_config() + ->mutable_typed_config() + ->PackFrom(RoundRobin()); + LoadBalancingPolicyProto policy; + auto* lb_policy = policy.add_policies(); + lb_policy->mutable_typed_extension_config()->mutable_typed_config()->PackFrom( + wrr_locality); + auto result = ConvertXdsPolicy(policy); + EXPECT_TRUE(result.ok()); + EXPECT_EQ(result->size(), 1); + grpc_error_handle error = GRPC_ERROR_NONE; + EXPECT_EQ((*result)[0], Json::Parse("{" + "\"xds_wrr_locality_experimental\": {" + " \"child_policy\": [{" + " \"round_robin\": {}" + " }]" + "}}", + &error)); +} + +TEST(XdsLbPolicyRegistryTest, WrrLocalityMissingEndpointPickingPolicy) { + LoadBalancingPolicyProto policy; + auto* lb_policy = policy.add_policies(); + lb_policy->mutable_typed_extension_config()->mutable_typed_config()->PackFrom( + WrrLocality()); + auto result = ConvertXdsPolicy(policy); + EXPECT_EQ(result.status().code(), absl::StatusCode::kInvalidArgument); + EXPECT_THAT(std::string(result.status().message()), + ::testing::ContainsRegex( + "Error parsing LoadBalancingPolicy.*WrrLocality: " + "endpoint_picking_policy not found")); +} + +TEST(XdsLbPolicyRegistryTest, WrrLocalityChildPolicyError) { + WrrLocality wrr_locality; + wrr_locality.mutable_endpoint_picking_policy() + ->add_policies() + ->mutable_typed_extension_config() + ->mutable_typed_config() + ->PackFrom(RingHash()); + LoadBalancingPolicyProto policy; + auto* lb_policy = policy.add_policies(); + lb_policy->mutable_typed_extension_config()->mutable_typed_config()->PackFrom( + wrr_locality); + auto result = ConvertXdsPolicy(policy); + EXPECT_EQ(result.status().code(), absl::StatusCode::kInvalidArgument); + EXPECT_THAT(std::string(result.status().message()), + ::testing::ContainsRegex( + "Error parsing LoadBalancingPolicy.*Error parsing " + "WrrLocality load balancing policy.*Error parsing " + "LoadBalancingPolicy.*Invalid hash function provided for " + "RingHash loadbalancing policy. Only XX_HASH is supported.")); +} + +TEST(XdsLbPolicyRegistryTest, WrrLocalityUnsupportedTypeSkipped) { + // Create WrrLocality policy and add two policies to its list, an unsupported + // type and then a known RoundRobin type. Expect that the unsupported type is + // skipped and RoundRobin is selected. + WrrLocality wrr_locality; + wrr_locality.mutable_endpoint_picking_policy() + ->add_policies() + ->mutable_typed_extension_config() + ->mutable_typed_config() + ->PackFrom(LoadBalancingPolicyProto()); + wrr_locality.mutable_endpoint_picking_policy() + ->add_policies() + ->mutable_typed_extension_config() + ->mutable_typed_config() + ->PackFrom(RoundRobin()); + LoadBalancingPolicyProto policy; + auto* lb_policy = policy.add_policies(); + lb_policy->mutable_typed_extension_config()->mutable_typed_config()->PackFrom( + wrr_locality); + auto result = ConvertXdsPolicy(policy); + EXPECT_TRUE(result.ok()); + EXPECT_EQ(result->size(), 1); + grpc_error_handle error = GRPC_ERROR_NONE; + EXPECT_EQ((*result)[0], Json::Parse("{" + "\"xds_wrr_locality_experimental\": {" + " \"child_policy\": [{" + " \"round_robin\": {}" + " }]" + "}}", + &error)); +} + +class CustomLbPolicyFactory : public LoadBalancingPolicyFactory { + public: + OrphanablePtr CreateLoadBalancingPolicy( + LoadBalancingPolicy::Args /* args */) const override { + GPR_ASSERT(false); + return nullptr; + } + + const char* name() const override { return "test.CustomLb"; } + + RefCountedPtr ParseLoadBalancingConfig( + const Json& /* json */, grpc_error_handle* /* error */) const override { + return nullptr; + } +}; + +TEST(XdsLbPolicyRegistryTest, CustomLbPolicy) { + TypedStruct typed_struct; + typed_struct.set_type_url("type.googleapis.com/test.CustomLb"); + LoadBalancingPolicyProto policy; + auto* lb_policy = policy.add_policies(); + lb_policy->mutable_typed_extension_config()->mutable_typed_config()->PackFrom( + typed_struct); + auto result = ConvertXdsPolicy(policy); + EXPECT_TRUE(result.ok()); + EXPECT_EQ(result->size(), 1); + grpc_error_handle error = GRPC_ERROR_NONE; + EXPECT_EQ((*result)[0], Json::Parse("{" + "\"test.CustomLb\": null}", + &error)); +} + +TEST(XdsLbPolicyRegistryTest, CustomLbPolicyUdpaTyped) { + ::udpa::type::v1::TypedStruct typed_struct; + typed_struct.set_type_url("type.googleapis.com/test.CustomLb"); + LoadBalancingPolicyProto policy; + auto* lb_policy = policy.add_policies(); + lb_policy->mutable_typed_extension_config()->mutable_typed_config()->PackFrom( + typed_struct); + auto result = ConvertXdsPolicy(policy); + EXPECT_TRUE(result.ok()); + EXPECT_EQ(result->size(), 1); + grpc_error_handle error = GRPC_ERROR_NONE; + EXPECT_EQ((*result)[0], Json::Parse("{" + "\"test.CustomLb\": null}", + &error)); +} + +TEST(XdsLbPolicyRegistryTest, UnsupportedCustomTypeError) { + TypedStruct typed_struct; + typed_struct.set_type_url("myorg/foo/bar/test.UnknownLb"); + LoadBalancingPolicyProto policy; + auto* lb_policy = policy.add_policies(); + lb_policy->mutable_typed_extension_config()->mutable_typed_config()->PackFrom( + typed_struct); + auto result = ConvertXdsPolicy(policy); + EXPECT_EQ(result.status().code(), absl::StatusCode::kInvalidArgument); + EXPECT_THAT( + std::string(result.status().message()), + ::testing::HasSubstr("No supported load balancing policy config found")); +} + +TEST(XdsLbPolicyRegistryTest, CustomTypeInvalidUrlMissingSlash) { + TypedStruct typed_struct; + typed_struct.set_type_url("test.UnknownLb"); + LoadBalancingPolicyProto policy; + auto* lb_policy = policy.add_policies(); + lb_policy->mutable_typed_extension_config()->mutable_typed_config()->PackFrom( + typed_struct); + auto result = ConvertXdsPolicy(policy); + EXPECT_EQ(result.status().code(), absl::StatusCode::kInvalidArgument); + EXPECT_THAT( + std::string(result.status().message()), + ::testing::HasSubstr("Error parsing " + "LoadBalancingPolicy::Policy::TypedExtensionConfig::" + "typed_config: Invalid type_url test.UnknownLb")); +} + +TEST(XdsLbPolicyRegistryTest, CustomTypeInvalidUrlEmptyType) { + TypedStruct typed_struct; + typed_struct.set_type_url("myorg/"); + LoadBalancingPolicyProto policy; + auto* lb_policy = policy.add_policies(); + lb_policy->mutable_typed_extension_config()->mutable_typed_config()->PackFrom( + typed_struct); + auto result = ConvertXdsPolicy(policy); + EXPECT_EQ(result.status().code(), absl::StatusCode::kInvalidArgument); + EXPECT_THAT( + std::string(result.status().message()), + ::testing::HasSubstr("Error parsing " + "LoadBalancingPolicy::Policy::TypedExtensionConfig::" + "typed_config: Invalid type_url myorg/")); +} + +TEST(XdsLbPolicyRegistryTest, CustomLbPolicyJsonConversion) { + TypedStruct typed_struct; + ASSERT_TRUE(grpc::protobuf::TextFormat::ParseFromString( + R"pb( + type_url: "type.googleapis.com/test.CustomLb" + value { + fields { + key: "key" + value { null_value: NULL_VALUE } + } + fields { + key: "number" + value { number_value: 123 } + } + fields { + key: "string" + value { string_value: "value" } + } + fields { + key: "struct" + value { + struct_value { + fields { + key: "key" + value { null_value: NULL_VALUE } + } + } + } + } + fields { + key: "list" + value { + list_value { + values { null_value: NULL_VALUE } + values { number_value: 234 } + } + } + } + } + )pb", + &typed_struct)); + LoadBalancingPolicyProto policy; + auto* lb_policy = policy.add_policies(); + lb_policy->mutable_typed_extension_config()->mutable_typed_config()->PackFrom( + typed_struct); + auto result = ConvertXdsPolicy(policy); + EXPECT_TRUE(result.ok()); + EXPECT_EQ(result->size(), 1); + grpc_error_handle error = GRPC_ERROR_NONE; + EXPECT_EQ((*result)[0], Json::Parse( + R"json({ + "test.CustomLb":{ + "key": null, + "number": 123, + "string": "value", + "struct": { + "key": null + }, + "list": [null, 234] + } + })json", + &error)); +} + +TEST(XdsLbPolicyRegistryTest, CustomLbPolicyListError) { + TypedStruct typed_struct; + typed_struct.set_type_url("type.googleapis.com/test.CustomLb"); + auto* fields = typed_struct.mutable_value()->mutable_fields(); + google::protobuf::Value value; + value.mutable_list_value()->add_values(); + (*fields)["key"] = value; + LoadBalancingPolicyProto policy; + auto* lb_policy = policy.add_policies(); + lb_policy->mutable_typed_extension_config()->mutable_typed_config()->PackFrom( + typed_struct); + auto result = ConvertXdsPolicy(policy); + EXPECT_EQ(result.status().code(), absl::StatusCode::kInvalidArgument); + EXPECT_THAT(std::string(result.status().message()), + ::testing::HasSubstr( + "Error parsing LoadBalancingPolicy: Custom Policy: " + "test.CustomLb: Error parsing google::Protobuf::Struct: No " + "value set in Value proto")); +} + +TEST(XdsLbPolicyRegistryTest, UnsupportedBuiltInTypeSkipped) { + // Add two policies to list, an unsupported type and then a known RoundRobin + // type. Expect that the unsupported type is skipped and RoundRobin is + // selected. + LoadBalancingPolicyProto policy; + auto* lb_policy = policy.add_policies(); + lb_policy->mutable_typed_extension_config()->mutable_typed_config()->PackFrom( + LoadBalancingPolicyProto()); + lb_policy = policy.add_policies(); + lb_policy->mutable_typed_extension_config()->mutable_typed_config()->PackFrom( + RoundRobin()); + auto result = ConvertXdsPolicy(policy); + EXPECT_TRUE(result.ok()); + EXPECT_EQ(result->size(), 1); + grpc_error_handle error = GRPC_ERROR_NONE; + EXPECT_EQ((*result)[0], Json::Parse("{" + "\"round_robin\": {}" + "}", + &error)); +} + +TEST(XdsLbPolicyRegistryTest, UnsupportedCustomTypeSkipped) { + // Add two policies to list, an unsupported custom type and then a known + // RoundRobin type. Expect that the unsupported type is skipped and RoundRobin + // is selected. + TypedStruct typed_struct; + typed_struct.set_type_url("myorg/foo/bar/test.UnknownLb"); + LoadBalancingPolicyProto policy; + auto* lb_policy = policy.add_policies(); + lb_policy->mutable_typed_extension_config()->mutable_typed_config()->PackFrom( + typed_struct); + lb_policy = policy.add_policies(); + lb_policy->mutable_typed_extension_config()->mutable_typed_config()->PackFrom( + RoundRobin()); + auto result = ConvertXdsPolicy(policy); + EXPECT_TRUE(result.ok()); + EXPECT_EQ(result->size(), 1); + grpc_error_handle error = GRPC_ERROR_NONE; + EXPECT_EQ((*result)[0], Json::Parse("{" + "\"round_robin\": {}" + "}", + &error)); +} + +// Build a recurse load balancing policy that goes beyond the max allowable +// depth of 16. +LoadBalancingPolicyProto BuildRecursiveLoadBalancingPolicy(int depth) { + LoadBalancingPolicyProto policy; + if (depth >= 16) { + policy.add_policies() + ->mutable_typed_extension_config() + ->mutable_typed_config() + ->PackFrom(RoundRobin()); + return policy; + } + WrrLocality wrr_locality; + *wrr_locality.mutable_endpoint_picking_policy() = + BuildRecursiveLoadBalancingPolicy(depth + 1); + policy.add_policies() + ->mutable_typed_extension_config() + ->mutable_typed_config() + ->PackFrom(wrr_locality); + return policy; +} + +TEST(XdsLbPolicyRegistryTest, MaxRecursion) { + auto result = ConvertXdsPolicy(BuildRecursiveLoadBalancingPolicy(0)); + EXPECT_EQ(result.status().code(), absl::StatusCode::kInvalidArgument); + EXPECT_THAT(std::string(result.status().message()), + ::testing::ContainsRegex("LoadBalancingPolicy configuration has " + "a recursion depth of more than 16")); +} + +} // namespace +} // namespace testing +} // namespace grpc_core + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + grpc::testing::TestEnvironment env(&argc, argv); + grpc_core::LoadBalancingPolicyRegistry::Builder:: + RegisterLoadBalancingPolicyFactory( + absl::make_unique()); + grpc_init(); + auto result = RUN_ALL_TESTS(); + grpc_shutdown(); + return result; +} diff --git a/test/cpp/end2end/xds/xds_end2end_test.cc b/test/cpp/end2end/xds/xds_end2end_test.cc index edaae4aaaf4..7ec83290c62 100644 --- a/test/cpp/end2end/xds/xds_end2end_test.cc +++ b/test/cpp/end2end/xds/xds_end2end_test.cc @@ -1168,7 +1168,7 @@ TEST_P(XdsEnabledServerTest, UnsupportedHttpFilter) { auto* http_filter = http_connection_manager.add_http_filters(); http_filter->set_name("grpc.testing.unsupported_http_filter"); http_filter->mutable_typed_config()->set_type_url( - "grpc.testing.unsupported_http_filter"); + "custom/grpc.testing.unsupported_http_filter"); http_filter = http_connection_manager.add_http_filters(); http_filter->set_name("router"); http_filter->mutable_typed_config()->PackFrom( @@ -1193,7 +1193,7 @@ TEST_P(XdsEnabledServerTest, HttpFilterNotSupportedOnServer) { auto* http_filter = http_connection_manager.add_http_filters(); http_filter->set_name("grpc.testing.client_only_http_filter"); http_filter->mutable_typed_config()->set_type_url( - "grpc.testing.client_only_http_filter"); + "custom/grpc.testing.client_only_http_filter"); http_filter = http_connection_manager.add_http_filters(); http_filter->set_name("router"); http_filter->mutable_typed_config()->PackFrom( @@ -1220,7 +1220,7 @@ TEST_P(XdsEnabledServerTest, auto* http_filter = http_connection_manager.add_http_filters(); http_filter->set_name("grpc.testing.client_only_http_filter"); http_filter->mutable_typed_config()->set_type_url( - "grpc.testing.client_only_http_filter"); + "custom/grpc.testing.client_only_http_filter"); http_filter->set_is_optional(true); http_filter = http_connection_manager.add_http_filters(); http_filter->set_name("router"); diff --git a/test/cpp/end2end/xds/xds_routing_end2end_test.cc b/test/cpp/end2end/xds/xds_routing_end2end_test.cc index f2a7a3b88f9..bf705c4f4b1 100644 --- a/test/cpp/end2end/xds/xds_routing_end2end_test.cc +++ b/test/cpp/end2end/xds/xds_routing_end2end_test.cc @@ -142,7 +142,7 @@ TEST_P(LdsTest, NacksNonTerminalHttpFilterAtEndOfList) { auto* filter = http_connection_manager.mutable_http_filters(0); filter->set_name("unknown"); filter->mutable_typed_config()->set_type_url( - "grpc.testing.client_only_http_filter"); + "custom/grpc.testing.client_only_http_filter"); listener.mutable_api_listener()->mutable_api_listener()->PackFrom( http_connection_manager); SetListenerAndRouteConfiguration(balancer_.get(), listener, @@ -166,7 +166,7 @@ TEST_P(LdsTest, NacksTerminalFilterBeforeEndOfList) { auto* filter = http_connection_manager.add_http_filters(); filter->set_name("grpc.testing.terminal_http_filter"); filter->mutable_typed_config()->set_type_url( - "grpc.testing.terminal_http_filter"); + "custom/grpc.testing.terminal_http_filter"); listener.mutable_api_listener()->mutable_api_listener()->PackFrom( http_connection_manager); SetListenerAndRouteConfiguration(balancer_.get(), listener, @@ -353,7 +353,7 @@ TEST_P(LdsTest, RejectsHttpFiltersNotSupportedOnClients) { auto* filter = http_connection_manager.mutable_http_filters(0); filter->set_name("grpc.testing.server_only_http_filter"); filter->mutable_typed_config()->set_type_url( - "grpc.testing.server_only_http_filter"); + "custom/grpc.testing.server_only_http_filter"); listener.mutable_api_listener()->mutable_api_listener()->PackFrom( http_connection_manager); SetListenerAndRouteConfiguration(balancer_.get(), listener, @@ -378,7 +378,7 @@ TEST_P(LdsTest, IgnoresOptionalHttpFiltersNotSupportedOnClients) { auto* filter = http_connection_manager.mutable_http_filters(0); filter->set_name("grpc.testing.server_only_http_filter"); filter->mutable_typed_config()->set_type_url( - "grpc.testing.server_only_http_filter"); + "custom/grpc.testing.server_only_http_filter"); filter->set_is_optional(true); listener.mutable_api_listener()->mutable_api_listener()->PackFrom( http_connection_manager); diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index 68941a86298..a30c23a5a1c 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -1415,6 +1415,10 @@ src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.c src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.h \ src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.c \ src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.h \ +src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb.c \ +src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb.h \ +src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/wrr_locality/v3/wrr_locality.upb.c \ +src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/wrr_locality/v3/wrr_locality.upb.h \ src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/cert.upb.c \ src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/cert.upb.h \ src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/common.upb.c \ @@ -1868,6 +1872,8 @@ src/core/ext/xds/xds_http_filters.cc \ src/core/ext/xds/xds_http_filters.h \ src/core/ext/xds/xds_http_rbac_filter.cc \ src/core/ext/xds/xds_http_rbac_filter.h \ +src/core/ext/xds/xds_lb_policy_registry.cc \ +src/core/ext/xds/xds_lb_policy_registry.h \ src/core/ext/xds/xds_listener.cc \ src/core/ext/xds/xds_listener.h \ src/core/ext/xds/xds_resource_type.cc \ diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index 89453f77184..6d42d7425ce 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -1204,6 +1204,10 @@ src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.c src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.h \ src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.c \ src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.h \ +src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb.c \ +src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb.h \ +src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/wrr_locality/v3/wrr_locality.upb.c \ +src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/wrr_locality/v3/wrr_locality.upb.h \ src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/cert.upb.c \ src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/cert.upb.h \ src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/common.upb.c \ @@ -1657,6 +1661,8 @@ src/core/ext/xds/xds_http_filters.cc \ src/core/ext/xds/xds_http_filters.h \ src/core/ext/xds/xds_http_rbac_filter.cc \ src/core/ext/xds/xds_http_rbac_filter.h \ +src/core/ext/xds/xds_lb_policy_registry.cc \ +src/core/ext/xds/xds_lb_policy_registry.h \ src/core/ext/xds/xds_listener.cc \ src/core/ext/xds/xds_listener.h \ src/core/ext/xds/xds_resource_type.cc \ diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json index 7915df81f25..011754afcec 100644 --- a/tools/run_tests/generated/tests.json +++ b/tools/run_tests/generated/tests.json @@ -7801,6 +7801,30 @@ ], "uses_polling": true }, + { + "args": [], + "benchmark": false, + "ci_platforms": [ + "linux", + "mac", + "posix", + "windows" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "gtest": true, + "language": "c++", + "name": "xds_lb_policy_registry_test", + "platforms": [ + "linux", + "mac", + "posix", + "windows" + ], + "uses_polling": false + }, { "args": [], "benchmark": false,