diff --git a/.bazelignore b/.bazelignore index 160716ea6e8..12c4c1349c6 100644 --- a/.bazelignore +++ b/.bazelignore @@ -21,6 +21,7 @@ third_party/upb third_party/xds bazel/test/python_test_repo +test/distrib/bazel/cpp # Directories generated by setuptools build containing BUILD files. src/python/grpcio_tests/src/ diff --git a/.github/ISSUE_TEMPLATE/bug_report_core.md b/.github/ISSUE_TEMPLATE/bug_report_core.md index 49dc54cd899..b85e850f16e 100644 --- a/.github/ISSUE_TEMPLATE/bug_report_core.md +++ b/.github/ISSUE_TEMPLATE/bug_report_core.md @@ -1,7 +1,7 @@ --- name: Report a gRPC Core bug about: Create a report to help us improve -labels: kind/bug, priority/P2, lang/core +labels: kind/bug, priority/P2, lang/core, untriaged assignees: markdroth --- diff --git a/.github/ISSUE_TEMPLATE/bug_report_cpp.md b/.github/ISSUE_TEMPLATE/bug_report_cpp.md index ede15a53bc4..9b14fb2022d 100644 --- a/.github/ISSUE_TEMPLATE/bug_report_cpp.md +++ b/.github/ISSUE_TEMPLATE/bug_report_cpp.md @@ -1,7 +1,7 @@ --- name: Report a gRPC C++ bug about: Create a report to help us improve -labels: kind/bug, priority/P2, lang/c++ +labels: kind/bug, priority/P2, lang/c++, untriaged assignees: markdroth --- diff --git a/BUILD b/BUILD index b8f07d53bdb..510a1d3a0f4 100644 --- a/BUILD +++ b/BUILD @@ -2883,6 +2883,7 @@ grpc_cc_library( "src/core/ext/xds/xds_client.cc", "src/core/ext/xds/xds_client_stats.cc", "src/core/ext/xds/xds_cluster.cc", + "src/core/ext/xds/xds_cluster_specifier_plugin.cc", "src/core/ext/xds/xds_common_types.cc", "src/core/ext/xds/xds_endpoint.cc", "src/core/ext/xds/xds_http_fault_filter.cc", @@ -2907,6 +2908,7 @@ grpc_cc_library( "src/core/ext/xds/xds_client.h", "src/core/ext/xds/xds_client_stats.h", "src/core/ext/xds/xds_cluster.h", + "src/core/ext/xds/xds_cluster_specifier_plugin.h", "src/core/ext/xds/xds_common_types.h", "src/core/ext/xds/xds_endpoint.h", "src/core/ext/xds/xds_http_fault_filter.h", @@ -2995,6 +2997,8 @@ grpc_cc_library( "protobuf_timestamp_upb", "protobuf_wrappers_upb", "ref_counted_ptr", + "rls_config_upb", + "rls_config_upbdefs", "slice", "slice_refcount", "sockaddr_utils", @@ -5371,6 +5375,16 @@ grpc_upb_proto_library( deps = ["//src/proto/grpc/lookup/v1:rls_proto_descriptor"], ) +grpc_upb_proto_library( + name = "rls_config_upb", + deps = ["//src/proto/grpc/lookup/v1:rls_config_proto_descriptor"], +) + +grpc_upb_proto_reflection_library( + name = "rls_config_upbdefs", + deps = ["//src/proto/grpc/lookup/v1:rls_config_proto_descriptor"], +) + WELL_KNOWN_PROTO_TARGETS = [ "any", "duration", diff --git a/CMakeLists.txt b/CMakeLists.txt index efa7230862a..bbb791db903 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -442,6 +442,9 @@ protobuf_generate_grpc_cpp( protobuf_generate_grpc_cpp( src/proto/grpc/lookup/v1/rls.proto ) +protobuf_generate_grpc_cpp( + src/proto/grpc/lookup/v1/rls_config.proto +) protobuf_generate_grpc_cpp( src/proto/grpc/reflection/v1alpha/reflection.proto ) @@ -1654,6 +1657,7 @@ add_library(grpc src/core/ext/upb-generated/src/proto/grpc/health/v1/health.upb.c src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls.upb.c + src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls_config.upb.c src/core/ext/upb-generated/udpa/annotations/migrate.upb.c src/core/ext/upb-generated/udpa/annotations/security.upb.c src/core/ext/upb-generated/udpa/annotations/sensitive.upb.c @@ -1788,6 +1792,7 @@ add_library(grpc src/core/ext/upbdefs-generated/google/protobuf/wrappers.upbdefs.c src/core/ext/upbdefs-generated/google/rpc/status.upbdefs.c src/core/ext/upbdefs-generated/opencensus/proto/trace/v1/trace_config.upbdefs.c + src/core/ext/upbdefs-generated/src/proto/grpc/lookup/v1/rls_config.upbdefs.c src/core/ext/upbdefs-generated/udpa/annotations/migrate.upbdefs.c src/core/ext/upbdefs-generated/udpa/annotations/security.upbdefs.c src/core/ext/upbdefs-generated/udpa/annotations/sensitive.upbdefs.c @@ -1820,6 +1825,7 @@ add_library(grpc src/core/ext/xds/xds_client.cc src/core/ext/xds/xds_client_stats.cc src/core/ext/xds/xds_cluster.cc + src/core/ext/xds/xds_cluster_specifier_plugin.cc src/core/ext/xds/xds_common_types.cc src/core/ext/xds/xds_endpoint.cc src/core/ext/xds/xds_http_fault_filter.cc @@ -3956,6 +3962,7 @@ add_library(upb third_party/upb/upb/decode.c third_party/upb/upb/def.c third_party/upb/upb/encode.c + third_party/upb/upb/json_encode.c third_party/upb/upb/msg.c third_party/upb/upb/reflection.c third_party/upb/upb/table.c @@ -14118,6 +14125,7 @@ add_executable(rls_end2end_test ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.h test/core/util/test_lb_policies.cc test/cpp/end2end/rls_end2end_test.cc + test/cpp/end2end/rls_server.cc test/cpp/end2end/test_service_impl.cc third_party/googletest/googletest/src/gtest-all.cc third_party/googletest/googlemock/src/gmock-all.cc @@ -16986,6 +16994,14 @@ if(gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(xds_end2end_test + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/lookup/v1/rls.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/lookup/v1/rls.grpc.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/lookup/v1/rls.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/lookup/v1/rls.grpc.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/lookup/v1/rls_config.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/lookup/v1/rls_config.grpc.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/lookup/v1/rls_config.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/lookup/v1/rls_config.grpc.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.pb.h @@ -17143,6 +17159,7 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/tls.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/tls.grpc.pb.h src/cpp/server/csds/csds.cc + test/cpp/end2end/rls_server.cc test/cpp/end2end/test_service_impl.cc test/cpp/end2end/xds/xds_end2end_test.cc test/cpp/end2end/xds/xds_server.cc diff --git a/Makefile b/Makefile index 9e8c78fb5b3..9fa48e9769a 100644 --- a/Makefile +++ b/Makefile @@ -1242,6 +1242,7 @@ LIBGRPC_SRC = \ src/core/ext/upb-generated/src/proto/grpc/health/v1/health.upb.c \ src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c \ src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls.upb.c \ + src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls_config.upb.c \ src/core/ext/upb-generated/udpa/annotations/migrate.upb.c \ src/core/ext/upb-generated/udpa/annotations/security.upb.c \ src/core/ext/upb-generated/udpa/annotations/sensitive.upb.c \ @@ -1376,6 +1377,7 @@ LIBGRPC_SRC = \ src/core/ext/upbdefs-generated/google/protobuf/wrappers.upbdefs.c \ src/core/ext/upbdefs-generated/google/rpc/status.upbdefs.c \ src/core/ext/upbdefs-generated/opencensus/proto/trace/v1/trace_config.upbdefs.c \ + src/core/ext/upbdefs-generated/src/proto/grpc/lookup/v1/rls_config.upbdefs.c \ src/core/ext/upbdefs-generated/udpa/annotations/migrate.upbdefs.c \ src/core/ext/upbdefs-generated/udpa/annotations/security.upbdefs.c \ src/core/ext/upbdefs-generated/udpa/annotations/sensitive.upbdefs.c \ @@ -1408,6 +1410,7 @@ LIBGRPC_SRC = \ src/core/ext/xds/xds_client.cc \ src/core/ext/xds/xds_client_stats.cc \ src/core/ext/xds/xds_cluster.cc \ + src/core/ext/xds/xds_cluster_specifier_plugin.cc \ src/core/ext/xds/xds_common_types.cc \ src/core/ext/xds/xds_endpoint.cc \ src/core/ext/xds/xds_http_fault_filter.cc \ @@ -2526,6 +2529,7 @@ LIBUPB_SRC = \ third_party/upb/upb/decode.c \ third_party/upb/upb/def.c \ third_party/upb/upb/encode.c \ + third_party/upb/upb/json_encode.c \ third_party/upb/upb/msg.c \ third_party/upb/upb/reflection.c \ third_party/upb/upb/table.c \ @@ -2943,6 +2947,7 @@ src/core/ext/upb-generated/opencensus/proto/trace/v1/trace_config.upb.c: $(OPENS src/core/ext/upb-generated/src/proto/grpc/gcp/altscontext.upb.c: $(OPENSSL_DEP) src/core/ext/upb-generated/src/proto/grpc/gcp/handshaker.upb.c: $(OPENSSL_DEP) src/core/ext/upb-generated/src/proto/grpc/gcp/transport_security_common.upb.c: $(OPENSSL_DEP) +src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls_config.upb.c: $(OPENSSL_DEP) src/core/ext/upb-generated/udpa/annotations/migrate.upb.c: $(OPENSSL_DEP) src/core/ext/upb-generated/udpa/annotations/security.upb.c: $(OPENSSL_DEP) src/core/ext/upb-generated/udpa/annotations/sensitive.upb.c: $(OPENSSL_DEP) @@ -3074,6 +3079,7 @@ src/core/ext/upbdefs-generated/google/protobuf/timestamp.upbdefs.c: $(OPENSSL_DE src/core/ext/upbdefs-generated/google/protobuf/wrappers.upbdefs.c: $(OPENSSL_DEP) src/core/ext/upbdefs-generated/google/rpc/status.upbdefs.c: $(OPENSSL_DEP) src/core/ext/upbdefs-generated/opencensus/proto/trace/v1/trace_config.upbdefs.c: $(OPENSSL_DEP) +src/core/ext/upbdefs-generated/src/proto/grpc/lookup/v1/rls_config.upbdefs.c: $(OPENSSL_DEP) src/core/ext/upbdefs-generated/udpa/annotations/migrate.upbdefs.c: $(OPENSSL_DEP) src/core/ext/upbdefs-generated/udpa/annotations/security.upbdefs.c: $(OPENSSL_DEP) src/core/ext/upbdefs-generated/udpa/annotations/sensitive.upbdefs.c: $(OPENSSL_DEP) @@ -3106,6 +3112,7 @@ src/core/ext/xds/xds_channel_stack_modifier.cc: $(OPENSSL_DEP) src/core/ext/xds/xds_client.cc: $(OPENSSL_DEP) src/core/ext/xds/xds_client_stats.cc: $(OPENSSL_DEP) src/core/ext/xds/xds_cluster.cc: $(OPENSSL_DEP) +src/core/ext/xds/xds_cluster_specifier_plugin.cc: $(OPENSSL_DEP) src/core/ext/xds/xds_common_types.cc: $(OPENSSL_DEP) src/core/ext/xds/xds_endpoint.cc: $(OPENSSL_DEP) src/core/ext/xds/xds_http_fault_filter.cc: $(OPENSSL_DEP) diff --git a/bazel/supported_versions.txt b/bazel/supported_versions.txt new file mode 100644 index 00000000000..97a43aa882d --- /dev/null +++ b/bazel/supported_versions.txt @@ -0,0 +1,3 @@ +5.0.0 +4.2.2 +3.7.2 diff --git a/bazel/test/python_test_repo/WORKSPACE b/bazel/test/python_test_repo/WORKSPACE index e704b8b0612..35cb1c8ed6b 100644 --- a/bazel/test/python_test_repo/WORKSPACE +++ b/bazel/test/python_test_repo/WORKSPACE @@ -1,3 +1,5 @@ +# TODO: Move to test/distrib/python. + local_repository( name = "com_github_grpc_grpc", path = "../../..", diff --git a/build_autogenerated.yaml b/build_autogenerated.yaml index f77ac520916..feec20d413a 100644 --- a/build_autogenerated.yaml +++ b/build_autogenerated.yaml @@ -513,6 +513,7 @@ libs: - src/core/ext/upb-generated/src/proto/grpc/health/v1/health.upb.h - src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.h - src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls.upb.h + - src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls_config.upb.h - src/core/ext/upb-generated/udpa/annotations/migrate.upb.h - src/core/ext/upb-generated/udpa/annotations/security.upb.h - src/core/ext/upb-generated/udpa/annotations/sensitive.upb.h @@ -647,6 +648,7 @@ libs: - src/core/ext/upbdefs-generated/google/protobuf/wrappers.upbdefs.h - src/core/ext/upbdefs-generated/google/rpc/status.upbdefs.h - src/core/ext/upbdefs-generated/opencensus/proto/trace/v1/trace_config.upbdefs.h + - src/core/ext/upbdefs-generated/src/proto/grpc/lookup/v1/rls_config.upbdefs.h - src/core/ext/upbdefs-generated/udpa/annotations/migrate.upbdefs.h - src/core/ext/upbdefs-generated/udpa/annotations/security.upbdefs.h - src/core/ext/upbdefs-generated/udpa/annotations/sensitive.upbdefs.h @@ -682,6 +684,7 @@ libs: - src/core/ext/xds/xds_client.h - src/core/ext/xds/xds_client_stats.h - src/core/ext/xds/xds_cluster.h + - src/core/ext/xds/xds_cluster_specifier_plugin.h - src/core/ext/xds/xds_common_types.h - src/core/ext/xds/xds_endpoint.h - src/core/ext/xds/xds_http_fault_filter.h @@ -1186,6 +1189,7 @@ libs: - src/core/ext/upb-generated/src/proto/grpc/health/v1/health.upb.c - src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c - src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls.upb.c + - src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls_config.upb.c - src/core/ext/upb-generated/udpa/annotations/migrate.upb.c - src/core/ext/upb-generated/udpa/annotations/security.upb.c - src/core/ext/upb-generated/udpa/annotations/sensitive.upb.c @@ -1320,6 +1324,7 @@ libs: - src/core/ext/upbdefs-generated/google/protobuf/wrappers.upbdefs.c - src/core/ext/upbdefs-generated/google/rpc/status.upbdefs.c - src/core/ext/upbdefs-generated/opencensus/proto/trace/v1/trace_config.upbdefs.c + - src/core/ext/upbdefs-generated/src/proto/grpc/lookup/v1/rls_config.upbdefs.c - src/core/ext/upbdefs-generated/udpa/annotations/migrate.upbdefs.c - src/core/ext/upbdefs-generated/udpa/annotations/security.upbdefs.c - src/core/ext/upbdefs-generated/udpa/annotations/sensitive.upbdefs.c @@ -1352,6 +1357,7 @@ libs: - src/core/ext/xds/xds_client.cc - src/core/ext/xds/xds_client_stats.cc - src/core/ext/xds/xds_cluster.cc + - src/core/ext/xds/xds_cluster_specifier_plugin.cc - src/core/ext/xds/xds_common_types.cc - src/core/ext/xds/xds_endpoint.cc - src/core/ext/xds/xds_http_fault_filter.cc @@ -7133,6 +7139,7 @@ targets: headers: - test/core/util/test_lb_policies.h - test/cpp/end2end/counted_service.h + - test/cpp/end2end/rls_server.h - test/cpp/end2end/test_service_impl.h src: - src/proto/grpc/lookup/v1/rls.proto @@ -7142,6 +7149,7 @@ targets: - src/proto/grpc/testing/simple_messages.proto - test/core/util/test_lb_policies.cc - test/cpp/end2end/rls_end2end_test.cc + - test/cpp/end2end/rls_server.cc - test/cpp/end2end/test_service_impl.cc deps: - grpc++_test_config @@ -8357,10 +8365,13 @@ targets: headers: - src/cpp/server/csds/csds.h - test/cpp/end2end/counted_service.h + - test/cpp/end2end/rls_server.h - test/cpp/end2end/test_service_impl.h - test/cpp/end2end/xds/xds_server.h - test/cpp/util/tls_test_utils.h src: + - src/proto/grpc/lookup/v1/rls.proto + - src/proto/grpc/lookup/v1/rls_config.proto - src/proto/grpc/testing/duplicate/echo_duplicate.proto - src/proto/grpc/testing/echo.proto - src/proto/grpc/testing/echo_messages.proto @@ -8401,6 +8412,7 @@ targets: - src/proto/grpc/testing/xds/v3/string.proto - src/proto/grpc/testing/xds/v3/tls.proto - src/cpp/server/csds/csds.cc + - test/cpp/end2end/rls_server.cc - test/cpp/end2end/test_service_impl.cc - test/cpp/end2end/xds/xds_end2end_test.cc - test/cpp/end2end/xds/xds_server.cc diff --git a/config.m4 b/config.m4 index aa1a9f3aae4..4a40af5382c 100644 --- a/config.m4 +++ b/config.m4 @@ -260,6 +260,7 @@ if test "$PHP_GRPC" != "no"; then src/core/ext/upb-generated/src/proto/grpc/health/v1/health.upb.c \ src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c \ src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls.upb.c \ + src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls_config.upb.c \ src/core/ext/upb-generated/udpa/annotations/migrate.upb.c \ src/core/ext/upb-generated/udpa/annotations/security.upb.c \ src/core/ext/upb-generated/udpa/annotations/sensitive.upb.c \ @@ -394,6 +395,7 @@ if test "$PHP_GRPC" != "no"; then src/core/ext/upbdefs-generated/google/protobuf/wrappers.upbdefs.c \ src/core/ext/upbdefs-generated/google/rpc/status.upbdefs.c \ src/core/ext/upbdefs-generated/opencensus/proto/trace/v1/trace_config.upbdefs.c \ + src/core/ext/upbdefs-generated/src/proto/grpc/lookup/v1/rls_config.upbdefs.c \ src/core/ext/upbdefs-generated/udpa/annotations/migrate.upbdefs.c \ src/core/ext/upbdefs-generated/udpa/annotations/security.upbdefs.c \ src/core/ext/upbdefs-generated/udpa/annotations/sensitive.upbdefs.c \ @@ -426,6 +428,7 @@ if test "$PHP_GRPC" != "no"; then src/core/ext/xds/xds_client.cc \ src/core/ext/xds/xds_client_stats.cc \ src/core/ext/xds/xds_cluster.cc \ + src/core/ext/xds/xds_cluster_specifier_plugin.cc \ src/core/ext/xds/xds_common_types.cc \ src/core/ext/xds/xds_endpoint.cc \ src/core/ext/xds/xds_http_fault_filter.cc \ @@ -1150,6 +1153,7 @@ if test "$PHP_GRPC" != "no"; then third_party/upb/upb/decode_fast.c \ third_party/upb/upb/def.c \ third_party/upb/upb/encode.c \ + third_party/upb/upb/json_encode.c \ third_party/upb/upb/msg.c \ third_party/upb/upb/reflection.c \ third_party/upb/upb/table.c \ @@ -1280,6 +1284,7 @@ if test "$PHP_GRPC" != "no"; then PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/google/protobuf) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/google/rpc) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/opencensus/proto/trace/v1) + PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/src/proto/grpc/lookup/v1) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/udpa/annotations) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/validate) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/xds/annotations/v3) diff --git a/config.w32 b/config.w32 index dfc72f7db81..990db857c7f 100644 --- a/config.w32 +++ b/config.w32 @@ -226,6 +226,7 @@ if (PHP_GRPC != "no") { "src\\core\\ext\\upb-generated\\src\\proto\\grpc\\health\\v1\\health.upb.c " + "src\\core\\ext\\upb-generated\\src\\proto\\grpc\\lb\\v1\\load_balancer.upb.c " + "src\\core\\ext\\upb-generated\\src\\proto\\grpc\\lookup\\v1\\rls.upb.c " + + "src\\core\\ext\\upb-generated\\src\\proto\\grpc\\lookup\\v1\\rls_config.upb.c " + "src\\core\\ext\\upb-generated\\udpa\\annotations\\migrate.upb.c " + "src\\core\\ext\\upb-generated\\udpa\\annotations\\security.upb.c " + "src\\core\\ext\\upb-generated\\udpa\\annotations\\sensitive.upb.c " + @@ -360,6 +361,7 @@ if (PHP_GRPC != "no") { "src\\core\\ext\\upbdefs-generated\\google\\protobuf\\wrappers.upbdefs.c " + "src\\core\\ext\\upbdefs-generated\\google\\rpc\\status.upbdefs.c " + "src\\core\\ext\\upbdefs-generated\\opencensus\\proto\\trace\\v1\\trace_config.upbdefs.c " + + "src\\core\\ext\\upbdefs-generated\\src\\proto\\grpc\\lookup\\v1\\rls_config.upbdefs.c " + "src\\core\\ext\\upbdefs-generated\\udpa\\annotations\\migrate.upbdefs.c " + "src\\core\\ext\\upbdefs-generated\\udpa\\annotations\\security.upbdefs.c " + "src\\core\\ext\\upbdefs-generated\\udpa\\annotations\\sensitive.upbdefs.c " + @@ -392,6 +394,7 @@ if (PHP_GRPC != "no") { "src\\core\\ext\\xds\\xds_client.cc " + "src\\core\\ext\\xds\\xds_client_stats.cc " + "src\\core\\ext\\xds\\xds_cluster.cc " + + "src\\core\\ext\\xds\\xds_cluster_specifier_plugin.cc " + "src\\core\\ext\\xds\\xds_common_types.cc " + "src\\core\\ext\\xds\\xds_endpoint.cc " + "src\\core\\ext\\xds\\xds_http_fault_filter.cc " + @@ -1116,6 +1119,7 @@ if (PHP_GRPC != "no") { "third_party\\upb\\upb\\decode_fast.c " + "third_party\\upb\\upb\\def.c " + "third_party\\upb\\upb\\encode.c " + + "third_party\\upb\\upb\\json_encode.c " + "third_party\\upb\\upb\\msg.c " + "third_party\\upb\\upb\\reflection.c " + "third_party\\upb\\upb\\table.c " + @@ -1386,6 +1390,11 @@ if (PHP_GRPC != "no") { FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\opencensus\\proto"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\opencensus\\proto\\trace"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\opencensus\\proto\\trace\\v1"); + FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\src"); + FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\src\\proto"); + FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\src\\proto\\grpc"); + FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\src\\proto\\grpc\\lookup"); + FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\src\\proto\\grpc\\lookup\\v1"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\udpa"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\udpa\\annotations"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\validate"); diff --git a/doc/bazel_support.md b/doc/bazel_support.md new file mode 100644 index 00000000000..5acbf136018 --- /dev/null +++ b/doc/bazel_support.md @@ -0,0 +1,44 @@ +# Bazel Support + +## Basic Usage + +The `grpc/grpc` repository's primary build system is Bazel. Rules are provided +for C++, Python, and Objective-C. While C++ supports other build systems such as +CMake, these rules are actually generated from the Bazel definitions. + +Projects built with Bazel may use the `grpc/grpc` repo not only to add a +dependency on the library itself, but also to generate protobuf, stub, and +servicer code. To do so, one must invoke the `grpc_deps` and `grpc_extra_deps` +repository rules in their `WORKSPACE` file: + +```starlark +workspace(name = "example_workspace") + +load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") + +http_archive( + name = "com_github_grpc_grpc", + strip_prefix = "grpc-1.45.0", + sha256 = "ec19657a677d49af59aa806ec299c070c882986c9fcc022b1c22c2a3caf01bcd"k + urls = ["https://github.com/grpc/grpc/archive/refs/tags/v1.45.0.tar.gz"], +) + +load("@com_github_grpc_grpc//bazel:grpc_deps.bzl", "grpc_deps") + +grpc_deps() + +load("@com_github_grpc_grpc//bazel:grpc_extra_deps.bzl", "grpc_extra_deps") + +grpc_extra_deps() +``` + +## Supported Versions + +In general, gRPC supports building with the latest patch release of the most +recent two major versions of Bazel. However individual releases may have a +broader compatibility range. The currently supported versions are captured by +the following list: + +- [`5.0.0`](https://github.com/bazelbuild/bazel/releases/tag/5.0.0) +- [`4.2.2`](https://github.com/bazelbuild/bazel/releases/tag/4.2.2) +- [`3.7.2`](https://github.com/bazelbuild/bazel/releases/tag/3.7.2) diff --git a/doc/environment_variables.md b/doc/environment_variables.md index ebf4f9aa45c..4f6201acf2b 100644 --- a/doc/environment_variables.md +++ b/doc/environment_variables.md @@ -53,9 +53,12 @@ some configuration as environment variables that can be set. - channel - traces operations on the C core channel stack - channel_stack - traces the set of filters in a channel stack upon construction - - client_channel_call - traces client channel call batch activity - - client_channel_routing - traces client channel call routing, including + - client_channel - traces client channel control plane activity, including resolver and load balancing policy interaction + - client_channel_call - traces client channel call activity related to name + resolution + - client_channel_lb_call - traces client channel call activity related + to load balancing picking - compression - traces compression operations - connectivity_state - traces connectivity state changes to channels - cronet - traces state in the cronet transport engine diff --git a/gRPC-C++.podspec b/gRPC-C++.podspec index 5b350c9accf..72abb249de7 100644 --- a/gRPC-C++.podspec +++ b/gRPC-C++.podspec @@ -453,6 +453,7 @@ Pod::Spec.new do |s| 'src/core/ext/upb-generated/src/proto/grpc/health/v1/health.upb.h', 'src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.h', 'src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls.upb.h', + 'src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls_config.upb.h', 'src/core/ext/upb-generated/udpa/annotations/migrate.upb.h', 'src/core/ext/upb-generated/udpa/annotations/security.upb.h', 'src/core/ext/upb-generated/udpa/annotations/sensitive.upb.h', @@ -587,6 +588,7 @@ Pod::Spec.new do |s| 'src/core/ext/upbdefs-generated/google/protobuf/wrappers.upbdefs.h', 'src/core/ext/upbdefs-generated/google/rpc/status.upbdefs.h', 'src/core/ext/upbdefs-generated/opencensus/proto/trace/v1/trace_config.upbdefs.h', + 'src/core/ext/upbdefs-generated/src/proto/grpc/lookup/v1/rls_config.upbdefs.h', 'src/core/ext/upbdefs-generated/udpa/annotations/migrate.upbdefs.h', 'src/core/ext/upbdefs-generated/udpa/annotations/security.upbdefs.h', 'src/core/ext/upbdefs-generated/udpa/annotations/sensitive.upbdefs.h', @@ -622,6 +624,7 @@ Pod::Spec.new do |s| 'src/core/ext/xds/xds_client.h', 'src/core/ext/xds/xds_client_stats.h', 'src/core/ext/xds/xds_cluster.h', + 'src/core/ext/xds/xds_cluster_specifier_plugin.h', 'src/core/ext/xds/xds_common_types.h', 'src/core/ext/xds/xds_endpoint.h', 'src/core/ext/xds/xds_http_fault_filter.h', @@ -1025,6 +1028,7 @@ Pod::Spec.new do |s| 'third_party/upb/upb/def.h', 'third_party/upb/upb/def.hpp', 'third_party/upb/upb/encode.h', + 'third_party/upb/upb/json_encode.h', 'third_party/upb/upb/msg.h', 'third_party/upb/upb/msg_internal.h', 'third_party/upb/upb/port_def.inc', @@ -1259,6 +1263,7 @@ Pod::Spec.new do |s| 'src/core/ext/upb-generated/src/proto/grpc/health/v1/health.upb.h', 'src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.h', 'src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls.upb.h', + 'src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls_config.upb.h', 'src/core/ext/upb-generated/udpa/annotations/migrate.upb.h', 'src/core/ext/upb-generated/udpa/annotations/security.upb.h', 'src/core/ext/upb-generated/udpa/annotations/sensitive.upb.h', @@ -1393,6 +1398,7 @@ Pod::Spec.new do |s| 'src/core/ext/upbdefs-generated/google/protobuf/wrappers.upbdefs.h', 'src/core/ext/upbdefs-generated/google/rpc/status.upbdefs.h', 'src/core/ext/upbdefs-generated/opencensus/proto/trace/v1/trace_config.upbdefs.h', + 'src/core/ext/upbdefs-generated/src/proto/grpc/lookup/v1/rls_config.upbdefs.h', 'src/core/ext/upbdefs-generated/udpa/annotations/migrate.upbdefs.h', 'src/core/ext/upbdefs-generated/udpa/annotations/security.upbdefs.h', 'src/core/ext/upbdefs-generated/udpa/annotations/sensitive.upbdefs.h', @@ -1428,6 +1434,7 @@ Pod::Spec.new do |s| 'src/core/ext/xds/xds_client.h', 'src/core/ext/xds/xds_client_stats.h', 'src/core/ext/xds/xds_cluster.h', + 'src/core/ext/xds/xds_cluster_specifier_plugin.h', 'src/core/ext/xds/xds_common_types.h', 'src/core/ext/xds/xds_endpoint.h', 'src/core/ext/xds/xds_http_fault_filter.h', @@ -1781,6 +1788,7 @@ Pod::Spec.new do |s| 'third_party/upb/upb/def.h', 'third_party/upb/upb/def.hpp', 'third_party/upb/upb/encode.h', + 'third_party/upb/upb/json_encode.h', 'third_party/upb/upb/msg.h', 'third_party/upb/upb/msg_internal.h', 'third_party/upb/upb/port_def.inc', diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index ed547ea0e36..554864e418f 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -612,6 +612,8 @@ Pod::Spec.new do |s| 'src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.h', 'src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls.upb.c', 'src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls.upb.h', + 'src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls_config.upb.c', + 'src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls_config.upb.h', 'src/core/ext/upb-generated/udpa/annotations/migrate.upb.c', 'src/core/ext/upb-generated/udpa/annotations/migrate.upb.h', 'src/core/ext/upb-generated/udpa/annotations/security.upb.c', @@ -880,6 +882,8 @@ Pod::Spec.new do |s| 'src/core/ext/upbdefs-generated/google/rpc/status.upbdefs.h', 'src/core/ext/upbdefs-generated/opencensus/proto/trace/v1/trace_config.upbdefs.c', 'src/core/ext/upbdefs-generated/opencensus/proto/trace/v1/trace_config.upbdefs.h', + 'src/core/ext/upbdefs-generated/src/proto/grpc/lookup/v1/rls_config.upbdefs.c', + 'src/core/ext/upbdefs-generated/src/proto/grpc/lookup/v1/rls_config.upbdefs.h', 'src/core/ext/upbdefs-generated/udpa/annotations/migrate.upbdefs.c', 'src/core/ext/upbdefs-generated/udpa/annotations/migrate.upbdefs.h', 'src/core/ext/upbdefs-generated/udpa/annotations/security.upbdefs.c', @@ -947,6 +951,8 @@ Pod::Spec.new do |s| 'src/core/ext/xds/xds_client_stats.h', 'src/core/ext/xds/xds_cluster.cc', 'src/core/ext/xds/xds_cluster.h', + 'src/core/ext/xds/xds_cluster_specifier_plugin.cc', + 'src/core/ext/xds/xds_cluster_specifier_plugin.h', 'src/core/ext/xds/xds_common_types.cc', 'src/core/ext/xds/xds_common_types.h', 'src/core/ext/xds/xds_endpoint.cc', @@ -1639,6 +1645,8 @@ Pod::Spec.new do |s| 'third_party/upb/upb/def.hpp', 'third_party/upb/upb/encode.c', 'third_party/upb/upb/encode.h', + 'third_party/upb/upb/json_encode.c', + 'third_party/upb/upb/json_encode.h', 'third_party/upb/upb/msg.c', 'third_party/upb/upb/msg.h', 'third_party/upb/upb/msg_internal.h', @@ -1857,6 +1865,7 @@ Pod::Spec.new do |s| 'src/core/ext/upb-generated/src/proto/grpc/health/v1/health.upb.h', 'src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.h', 'src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls.upb.h', + 'src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls_config.upb.h', 'src/core/ext/upb-generated/udpa/annotations/migrate.upb.h', 'src/core/ext/upb-generated/udpa/annotations/security.upb.h', 'src/core/ext/upb-generated/udpa/annotations/sensitive.upb.h', @@ -1991,6 +2000,7 @@ Pod::Spec.new do |s| 'src/core/ext/upbdefs-generated/google/protobuf/wrappers.upbdefs.h', 'src/core/ext/upbdefs-generated/google/rpc/status.upbdefs.h', 'src/core/ext/upbdefs-generated/opencensus/proto/trace/v1/trace_config.upbdefs.h', + 'src/core/ext/upbdefs-generated/src/proto/grpc/lookup/v1/rls_config.upbdefs.h', 'src/core/ext/upbdefs-generated/udpa/annotations/migrate.upbdefs.h', 'src/core/ext/upbdefs-generated/udpa/annotations/security.upbdefs.h', 'src/core/ext/upbdefs-generated/udpa/annotations/sensitive.upbdefs.h', @@ -2026,6 +2036,7 @@ Pod::Spec.new do |s| 'src/core/ext/xds/xds_client.h', 'src/core/ext/xds/xds_client_stats.h', 'src/core/ext/xds/xds_cluster.h', + 'src/core/ext/xds/xds_cluster_specifier_plugin.h', 'src/core/ext/xds/xds_common_types.h', 'src/core/ext/xds/xds_endpoint.h', 'src/core/ext/xds/xds_http_fault_filter.h', @@ -2369,6 +2380,7 @@ Pod::Spec.new do |s| 'third_party/upb/upb/def.h', 'third_party/upb/upb/def.hpp', 'third_party/upb/upb/encode.h', + 'third_party/upb/upb/json_encode.h', 'third_party/upb/upb/msg.h', 'third_party/upb/upb/msg_internal.h', 'third_party/upb/upb/port_def.inc', diff --git a/grpc.gemspec b/grpc.gemspec index f6346486b94..3bf58faa94d 100644 --- a/grpc.gemspec +++ b/grpc.gemspec @@ -531,6 +531,8 @@ Gem::Specification.new do |s| s.files += %w( src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.h ) s.files += %w( src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls.upb.c ) s.files += %w( src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls.upb.h ) + s.files += %w( src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls_config.upb.c ) + s.files += %w( src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls_config.upb.h ) s.files += %w( src/core/ext/upb-generated/udpa/annotations/migrate.upb.c ) s.files += %w( src/core/ext/upb-generated/udpa/annotations/migrate.upb.h ) s.files += %w( src/core/ext/upb-generated/udpa/annotations/security.upb.c ) @@ -799,6 +801,8 @@ Gem::Specification.new do |s| s.files += %w( src/core/ext/upbdefs-generated/google/rpc/status.upbdefs.h ) s.files += %w( src/core/ext/upbdefs-generated/opencensus/proto/trace/v1/trace_config.upbdefs.c ) s.files += %w( src/core/ext/upbdefs-generated/opencensus/proto/trace/v1/trace_config.upbdefs.h ) + s.files += %w( src/core/ext/upbdefs-generated/src/proto/grpc/lookup/v1/rls_config.upbdefs.c ) + s.files += %w( src/core/ext/upbdefs-generated/src/proto/grpc/lookup/v1/rls_config.upbdefs.h ) s.files += %w( src/core/ext/upbdefs-generated/udpa/annotations/migrate.upbdefs.c ) s.files += %w( src/core/ext/upbdefs-generated/udpa/annotations/migrate.upbdefs.h ) s.files += %w( src/core/ext/upbdefs-generated/udpa/annotations/security.upbdefs.c ) @@ -866,6 +870,8 @@ Gem::Specification.new do |s| s.files += %w( src/core/ext/xds/xds_client_stats.h ) s.files += %w( src/core/ext/xds/xds_cluster.cc ) s.files += %w( src/core/ext/xds/xds_cluster.h ) + s.files += %w( src/core/ext/xds/xds_cluster_specifier_plugin.cc ) + s.files += %w( src/core/ext/xds/xds_cluster_specifier_plugin.h ) s.files += %w( src/core/ext/xds/xds_common_types.cc ) s.files += %w( src/core/ext/xds/xds_common_types.h ) s.files += %w( src/core/ext/xds/xds_endpoint.cc ) @@ -2437,6 +2443,8 @@ Gem::Specification.new do |s| s.files += %w( third_party/upb/upb/def.hpp ) s.files += %w( third_party/upb/upb/encode.c ) s.files += %w( third_party/upb/upb/encode.h ) + s.files += %w( third_party/upb/upb/json_encode.c ) + s.files += %w( third_party/upb/upb/json_encode.h ) s.files += %w( third_party/upb/upb/msg.c ) s.files += %w( third_party/upb/upb/msg.h ) s.files += %w( third_party/upb/upb/msg_internal.h ) diff --git a/grpc.gyp b/grpc.gyp index ca719c20de5..3a796ce45b8 100644 --- a/grpc.gyp +++ b/grpc.gyp @@ -590,6 +590,7 @@ 'src/core/ext/upb-generated/src/proto/grpc/health/v1/health.upb.c', 'src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c', 'src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls.upb.c', + 'src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls_config.upb.c', 'src/core/ext/upb-generated/udpa/annotations/migrate.upb.c', 'src/core/ext/upb-generated/udpa/annotations/security.upb.c', 'src/core/ext/upb-generated/udpa/annotations/sensitive.upb.c', @@ -724,6 +725,7 @@ 'src/core/ext/upbdefs-generated/google/protobuf/wrappers.upbdefs.c', 'src/core/ext/upbdefs-generated/google/rpc/status.upbdefs.c', 'src/core/ext/upbdefs-generated/opencensus/proto/trace/v1/trace_config.upbdefs.c', + 'src/core/ext/upbdefs-generated/src/proto/grpc/lookup/v1/rls_config.upbdefs.c', 'src/core/ext/upbdefs-generated/udpa/annotations/migrate.upbdefs.c', 'src/core/ext/upbdefs-generated/udpa/annotations/security.upbdefs.c', 'src/core/ext/upbdefs-generated/udpa/annotations/sensitive.upbdefs.c', @@ -756,6 +758,7 @@ 'src/core/ext/xds/xds_client.cc', 'src/core/ext/xds/xds_client_stats.cc', 'src/core/ext/xds/xds_cluster.cc', + 'src/core/ext/xds/xds_cluster_specifier_plugin.cc', 'src/core/ext/xds/xds_common_types.cc', 'src/core/ext/xds/xds_endpoint.cc', 'src/core/ext/xds/xds_http_fault_filter.cc', @@ -2036,6 +2039,7 @@ 'third_party/upb/upb/decode.c', 'third_party/upb/upb/def.c', 'third_party/upb/upb/encode.c', + 'third_party/upb/upb/json_encode.c', 'third_party/upb/upb/msg.c', 'third_party/upb/upb/reflection.c', 'third_party/upb/upb/table.c', diff --git a/package.xml b/package.xml index b4c3e57fa2d..0a6950bce65 100644 --- a/package.xml +++ b/package.xml @@ -511,6 +511,8 @@ + + @@ -779,6 +781,8 @@ + + @@ -846,6 +850,8 @@ + + @@ -2353,6 +2359,8 @@ + + diff --git a/src/core/ext/filters/client_channel/client_channel.cc b/src/core/ext/filters/client_channel/client_channel.cc index 11c52d3a21b..c52f8a73e9d 100644 --- a/src/core/ext/filters/client_channel/client_channel.cc +++ b/src/core/ext/filters/client_channel/client_channel.cc @@ -54,6 +54,7 @@ #include "src/core/ext/filters/deadline/deadline_filter.h" #include "src/core/lib/backoff/backoff.h" #include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/channel/channel_stack.h" #include "src/core/lib/channel/connected_channel.h" #include "src/core/lib/channel/status_util.h" #include "src/core/lib/gpr/string.h" @@ -85,8 +86,9 @@ using internal::ClientChannelGlobalParsedConfig; using internal::ClientChannelMethodParsedConfig; using internal::ClientChannelServiceConfigParser; +TraceFlag grpc_client_channel_trace(false, "client_channel"); TraceFlag grpc_client_channel_call_trace(false, "client_channel_call"); -TraceFlag grpc_client_channel_routing_trace(false, "client_channel_routing"); +TraceFlag grpc_client_channel_lb_call_trace(false, "client_channel_lb_call"); // // ClientChannel::CallData definition @@ -175,8 +177,6 @@ class ClientChannel::CallData { static void RecvTrailingMetadataReadyForConfigSelectorCommitCallback( void* arg, grpc_error_handle error); - void InjectRecvTrailingMetadataReadyForConfigSelectorCommitCallback( - grpc_transport_stream_op_batch* batch); void CreateDynamicCall(grpc_call_element* elem); @@ -354,7 +354,7 @@ class DynamicTerminationFilter::CallData { args, pollent, nullptr, service_config_call_data->call_dispatch_controller(), /*is_transparent_retry=*/false); - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { gpr_log(GPR_INFO, "chand=%p dynamic_termination_calld=%p: create lb_call=%p", chand, client_channel, calld->lb_call_.get()); @@ -410,7 +410,7 @@ class ClientChannel::ResolverResultHandler : public Resolver::ResultHandler { } ~ResolverResultHandler() override { - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_trace)) { gpr_log(GPR_INFO, "chand=%p: resolver shutdown complete", chand_); } GRPC_CHANNEL_STACK_UNREF(chand_->owning_stack_, "ResolverResultHandler"); @@ -441,14 +441,13 @@ class ClientChannel::SubchannelWrapper : public SubchannelInterface { public: SubchannelWrapper(ClientChannel* chand, RefCountedPtr subchannel, absl::optional health_check_service_name) - : SubchannelInterface( - GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace) - ? "SubchannelWrapper" - : nullptr), + : SubchannelInterface(GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_trace) + ? "SubchannelWrapper" + : nullptr), chand_(chand), subchannel_(std::move(subchannel)), health_check_service_name_(std::move(health_check_service_name)) { - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_trace)) { gpr_log(GPR_INFO, "chand=%p: creating subchannel wrapper %p for subchannel %p", chand, this, subchannel_.get()); @@ -470,7 +469,7 @@ class ClientChannel::SubchannelWrapper : public SubchannelInterface { } ~SubchannelWrapper() override { - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_trace)) { gpr_log(GPR_INFO, "chand=%p: destroying subchannel wrapper %p for subchannel %p", chand_, this, subchannel_.get()); @@ -573,7 +572,7 @@ class ClientChannel::SubchannelWrapper : public SubchannelInterface { } void OnConnectivityStateChange() override { - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_trace)) { gpr_log(GPR_INFO, "chand=%p: connectivity change for subchannel wrapper %p " "subchannel %p; hopping into work_serializer", @@ -608,7 +607,7 @@ class ClientChannel::SubchannelWrapper : public SubchannelInterface { private: void ApplyUpdateInControlPlaneWorkSerializer() ABSL_EXCLUSIVE_LOCKS_REQUIRED(*parent_->chand_->work_serializer_) { - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_trace)) { gpr_log(GPR_INFO, "chand=%p: processing connectivity change in work serializer " "for subchannel wrapper %p subchannel %p " @@ -625,7 +624,7 @@ class ClientChannel::SubchannelWrapper : public SubchannelInterface { &new_keepalive_time)) { if (new_keepalive_time > parent_->chand_->keepalive_time_) { parent_->chand_->keepalive_time_ = new_keepalive_time; - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_trace)) { gpr_log(GPR_INFO, "chand=%p: throttling keepalive time to %d", parent_->chand_, parent_->chand_->keepalive_time_); } @@ -934,7 +933,7 @@ class ClientChannel::ClientChannelControlHelper std::unique_ptr picker) override ABSL_EXCLUSIVE_LOCKS_REQUIRED(*chand_->work_serializer_) { if (chand_->resolver_ == nullptr) return; // Shutting down. - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_trace)) { const char* extra = chand_->disconnect_error_ == GRPC_ERROR_NONE ? "" : " (ignoring -- channel shutting down)"; @@ -952,7 +951,7 @@ class ClientChannel::ClientChannelControlHelper void RequestReresolution() override ABSL_EXCLUSIVE_LOCKS_REQUIRED(*chand_->work_serializer_) { if (chand_->resolver_ == nullptr) return; // Shutting down. - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_trace)) { gpr_log(GPR_INFO, "chand=%p: started name re-resolving", chand_); } chand_->resolver_->RequestReresolutionLocked(); @@ -1041,7 +1040,7 @@ ClientChannel::ClientChannel(grpc_channel_element_args* args, work_serializer_(std::make_shared()), state_tracker_("client_channel", GRPC_CHANNEL_IDLE), subchannel_pool_(GetSubchannelPool(args->channel_args)) { - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_trace)) { gpr_log(GPR_INFO, "chand=%p: creating client_channel for channel stack %p", this, owning_stack_); } @@ -1116,7 +1115,7 @@ ClientChannel::ClientChannel(grpc_channel_element_args* args, } ClientChannel::~ClientChannel() { - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_trace)) { gpr_log(GPR_INFO, "chand=%p: destroying channel", this); } DestroyResolverAndLbPolicyLocked(); @@ -1203,7 +1202,7 @@ RefCountedPtr ChooseLbPolicy( void ClientChannel::OnResolverResultChangedLocked(Resolver::Result result) { // Handle race conditions. if (resolver_ == nullptr) return; - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_trace)) { gpr_log(GPR_INFO, "chand=%p: got resolver result", this); } // We only want to trace the address resolution in the follow cases: @@ -1236,14 +1235,14 @@ void ClientChannel::OnResolverResultChangedLocked(Resolver::Result result) { RefCountedPtr service_config; RefCountedPtr config_selector; if (!result.service_config.ok()) { - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_trace)) { gpr_log(GPR_INFO, "chand=%p: resolver returned service config error: %s", this, result.service_config.status().ToString().c_str()); } // If the service config was invalid, then fallback to the // previously returned service config. if (saved_service_config_ != nullptr) { - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_trace)) { gpr_log(GPR_INFO, "chand=%p: resolver returned invalid service config. " "Continuing to use previous service config.", @@ -1260,7 +1259,7 @@ void ClientChannel::OnResolverResultChangedLocked(Resolver::Result result) { } } else if (*result.service_config == nullptr) { // Resolver did not return any service config. - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_trace)) { gpr_log(GPR_INFO, "chand=%p: resolver returned no service config. Using default " "service config for channel.", @@ -1297,7 +1296,7 @@ void ClientChannel::OnResolverResultChangedLocked(Resolver::Result result) { UpdateServiceConfigInControlPlaneLocked(std::move(service_config), std::move(config_selector), lb_policy_config->name()); - } else if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { + } else if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_trace)) { gpr_log(GPR_INFO, "chand=%p: service config not changed", this); } // Create or update LB policy, as needed. @@ -1328,7 +1327,7 @@ void ClientChannel::OnResolverResultChangedLocked(Resolver::Result result) { void ClientChannel::OnResolverErrorLocked(absl::Status status) { if (resolver_ == nullptr) return; - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_trace)) { gpr_log(GPR_INFO, "chand=%p: resolver transient failure: %s", this, status.ToString().c_str()); } @@ -1387,7 +1386,7 @@ void ClientChannel::CreateOrUpdateLbPolicyLocked( lb_policy_ = CreateLbPolicyLocked(*update_args.args); } // Update the policy. - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_trace)) { gpr_log(GPR_INFO, "chand=%p: Updating child policy %p", this, lb_policy_.get()); } @@ -1404,8 +1403,8 @@ OrphanablePtr ClientChannel::CreateLbPolicyLocked( lb_policy_args.args = &args; OrphanablePtr lb_policy = MakeOrphanable(std::move(lb_policy_args), - &grpc_client_channel_routing_trace); - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { + &grpc_client_channel_trace); + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_trace)) { gpr_log(GPR_INFO, "chand=%p: created new LB policy %p", this, lb_policy.get()); } @@ -1442,7 +1441,7 @@ void ClientChannel::UpdateServiceConfigInControlPlaneLocked( RefCountedPtr service_config, RefCountedPtr config_selector, std::string lb_policy_name) { std::string service_config_json(service_config->json_string()); - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_trace)) { gpr_log(GPR_INFO, "chand=%p: resolver returned updated service config: \"%s\"", this, service_config_json.c_str()); @@ -1457,7 +1456,7 @@ void ClientChannel::UpdateServiceConfigInControlPlaneLocked( } // Save config selector. saved_config_selector_ = std::move(config_selector); - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_trace)) { gpr_log(GPR_INFO, "chand=%p: using ConfigSelector %p", this, saved_config_selector_.get()); } @@ -1468,7 +1467,7 @@ void ClientChannel::UpdateServiceConfigInDataPlaneLocked() { RefCountedPtr service_config = saved_service_config_; // Grab ref to config selector. Use default if resolver didn't supply one. RefCountedPtr config_selector = saved_config_selector_; - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_trace)) { gpr_log(GPR_INFO, "chand=%p: switching to ConfigSelector %p", this, saved_config_selector_.get()); } @@ -1539,7 +1538,7 @@ void ClientChannel::UpdateServiceConfigInDataPlaneLocked() { } void ClientChannel::CreateResolverLocked() { - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_trace)) { gpr_log(GPR_INFO, "chand=%p: starting name resolution", this); } resolver_ = CoreConfiguration::Get().resolver_registry().CreateResolver( @@ -1552,20 +1551,20 @@ void ClientChannel::CreateResolverLocked() { GRPC_CHANNEL_CONNECTING, absl::Status(), "started resolving", absl::make_unique(nullptr)); resolver_->StartLocked(); - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_trace)) { gpr_log(GPR_INFO, "chand=%p: created resolver=%p", this, resolver_.get()); } } void ClientChannel::DestroyResolverAndLbPolicyLocked() { if (resolver_ != nullptr) { - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_trace)) { gpr_log(GPR_INFO, "chand=%p: shutting down resolver=%p", this, resolver_.get()); } resolver_.reset(); if (lb_policy_ != nullptr) { - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_trace)) { gpr_log(GPR_INFO, "chand=%p: shutting down lb_policy=%p", this, lb_policy_.get()); } @@ -1733,7 +1732,7 @@ void ClientChannel::StartTransportOpLocked(grpc_transport_op* op) { } // Disconnect or enter IDLE. if (op->disconnect_with_error != GRPC_ERROR_NONE) { - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_trace)) { gpr_log(GPR_INFO, "chand=%p: disconnect_with_error: %s", this, grpc_error_std_string(op->disconnect_with_error).c_str()); } @@ -1911,6 +1910,11 @@ void ClientChannel::CallData::StartTransportStreamOpBatch( GPR_TIMER_SCOPE("cc_start_transport_stream_op_batch", 0); CallData* calld = static_cast(elem->call_data); ClientChannel* chand = static_cast(elem->channel_data); + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace) && + !GRPC_TRACE_FLAG_ENABLED(grpc_trace_channel)) { + gpr_log(GPR_INFO, "chand=%p calld=%p: batch started from above: %s", chand, + calld, grpc_transport_stream_op_batch_string(batch).c_str()); + } if (GPR_LIKELY(chand->deadline_checking_enabled_)) { grpc_deadline_state_client_start_transport_stream_op_batch(elem, batch); } @@ -1918,8 +1922,13 @@ void ClientChannel::CallData::StartTransportStreamOpBatch( // in case we wind up failing the call before we get down to the retry // or LB call layer. if (batch->recv_trailing_metadata) { - calld->InjectRecvTrailingMetadataReadyForConfigSelectorCommitCallback( - batch); + calld->original_recv_trailing_metadata_ready_ = + batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready; + GRPC_CLOSURE_INIT(&calld->recv_trailing_metadata_ready_, + RecvTrailingMetadataReadyForConfigSelectorCommitCallback, + elem, nullptr); + batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready = + &calld->recv_trailing_metadata_ready_; } // If we already have a dynamic call, pass the batch down to it. // Note that once we have done so, we do not need to acquire the channel's @@ -2144,7 +2153,7 @@ class ClientChannel::CallData::ResolverQueuedCallCanceller { auto* calld = static_cast(self->elem_->call_data); { MutexLock lock(&chand->resolution_mu_); - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { gpr_log(GPR_INFO, "chand=%p calld=%p: cancelling resolver queued pick: " "error=%s self=%p calld->resolver_pick_canceller=%p", @@ -2171,7 +2180,7 @@ void ClientChannel::CallData::MaybeRemoveCallFromResolverQueuedCallsLocked( grpc_call_element* elem) { if (!queued_pending_resolver_result_) return; auto* chand = static_cast(elem->channel_data); - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { gpr_log(GPR_INFO, "chand=%p calld=%p: removing from resolver queued picks list", chand, this); @@ -2186,7 +2195,7 @@ void ClientChannel::CallData::MaybeAddCallToResolverQueuedCallsLocked( grpc_call_element* elem) { if (queued_pending_resolver_result_) return; auto* chand = static_cast(elem->channel_data); - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { gpr_log(GPR_INFO, "chand=%p calld=%p: adding to resolver queued picks list", chand, this); } @@ -2200,7 +2209,7 @@ void ClientChannel::CallData::MaybeAddCallToResolverQueuedCallsLocked( grpc_error_handle ClientChannel::CallData::ApplyServiceConfigToCallLocked( grpc_call_element* elem, grpc_metadata_batch* initial_metadata) { ClientChannel* chand = static_cast(elem->channel_data); - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { gpr_log(GPR_INFO, "chand=%p calld=%p: applying service config to call", chand, this); } @@ -2261,30 +2270,27 @@ grpc_error_handle ClientChannel::CallData::ApplyServiceConfigToCallLocked( void ClientChannel::CallData:: RecvTrailingMetadataReadyForConfigSelectorCommitCallback( void* arg, grpc_error_handle error) { - auto* self = static_cast(arg); + auto* elem = static_cast(arg); + auto* chand = static_cast(elem->channel_data); + auto* calld = static_cast(elem->call_data); auto* service_config_call_data = static_cast( - self->call_context_[GRPC_CONTEXT_SERVICE_CONFIG_CALL_DATA].value); + calld->call_context_[GRPC_CONTEXT_SERVICE_CONFIG_CALL_DATA].value); + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { + gpr_log(GPR_INFO, + "chand=%p calld=%p: got recv_trailing_metadata_ready: error=%s " + "service_config_call_data=%p", + chand, calld, grpc_error_std_string(error).c_str(), + service_config_call_data); + } if (service_config_call_data != nullptr) { service_config_call_data->call_dispatch_controller()->Commit(); } // Chain to original callback. - Closure::Run(DEBUG_LOCATION, self->original_recv_trailing_metadata_ready_, + Closure::Run(DEBUG_LOCATION, calld->original_recv_trailing_metadata_ready_, GRPC_ERROR_REF(error)); } -void ClientChannel::CallData:: - InjectRecvTrailingMetadataReadyForConfigSelectorCommitCallback( - grpc_transport_stream_op_batch* batch) { - original_recv_trailing_metadata_ready_ = - batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready; - GRPC_CLOSURE_INIT(&recv_trailing_metadata_ready_, - RecvTrailingMetadataReadyForConfigSelectorCommitCallback, - this, nullptr); - batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready = - &recv_trailing_metadata_ready_; -} - void ClientChannel::CallData::AsyncResolutionDone(grpc_call_element* elem, grpc_error_handle error) { // TODO(roth): Does this callback need to hold a ref to the call stack? @@ -2298,7 +2304,7 @@ void ClientChannel::CallData::ResolutionDone(void* arg, ClientChannel* chand = static_cast(elem->channel_data); CallData* calld = static_cast(elem->call_data); if (error != GRPC_ERROR_NONE) { - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { gpr_log(GPR_INFO, "chand=%p calld=%p: error applying config to call: error=%s", chand, calld, grpc_error_std_string(error).c_str()); @@ -2330,6 +2336,9 @@ bool ClientChannel::CallData::CheckResolutionLocked(grpc_call_element* elem, ClientChannel* chand = static_cast(elem->channel_data); // If we're still in IDLE, we need to start resolving. if (GPR_UNLIKELY(chand->CheckConnectivityState(false) == GRPC_CHANNEL_IDLE)) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { + gpr_log(GPR_INFO, "chand=%p calld=%p: triggering exit idle", chand, this); + } // Bounce into the control plane work serializer to start resolving, // in case we are still in IDLE state. Since we are holding on to the // resolution mutex here, we offload it on the ExecCtx so that we don't @@ -2367,6 +2376,10 @@ bool ClientChannel::CallData::CheckResolutionLocked(grpc_call_element* elem, absl::Status resolver_error = chand->resolver_transient_failure_error_; if (!resolver_error.ok() && (send_initial_metadata_flags & GRPC_INITIAL_METADATA_WAIT_FOR_READY) == 0) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { + gpr_log(GPR_INFO, "chand=%p calld=%p: resolution failed, failing call", + chand, this); + } MaybeRemoveCallFromResolverQueuedCallsLocked(elem); *error = absl_status_to_grpc_error(resolver_error); return true; @@ -2374,6 +2387,10 @@ bool ClientChannel::CallData::CheckResolutionLocked(grpc_call_element* elem, // Either the resolver has not yet returned a result, or it has // returned transient failure but the call is wait_for_ready. In // either case, queue the call. + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { + gpr_log(GPR_INFO, "chand=%p calld=%p: queuing to wait for resolution", + chand, this); + } MaybeAddCallToResolverQueuedCallsLocked(elem); return false; } @@ -2398,7 +2415,7 @@ void ClientChannel::CallData::CreateDynamicCall(grpc_call_element* elem) { call_combiner_}; grpc_error_handle error = GRPC_ERROR_NONE; DynamicFilters* channel_stack = args.channel_stack.get(); - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { gpr_log( GPR_INFO, "chand=%p calld=%p: creating dynamic call stack on channel_stack=%p", @@ -2406,7 +2423,7 @@ void ClientChannel::CallData::CreateDynamicCall(grpc_call_element* elem) { } dynamic_call_ = channel_stack->CreateCall(std::move(args), &error); if (error != GRPC_ERROR_NONE) { - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { gpr_log(GPR_INFO, "chand=%p calld=%p: failed to create dynamic call: error=%s", chand, this, grpc_error_std_string(error).c_str()); @@ -2427,6 +2444,7 @@ class ClientChannel::LoadBalancedCall::Metadata explicit Metadata(grpc_metadata_batch* batch) : batch_(batch) {} void Add(absl::string_view key, absl::string_view value) override { + if (batch_ == nullptr) return; // Gross, egregious hack to support legacy grpclb behavior. // TODO(ctiller): Use a promise context for this once that plumbing is done. if (key == GrpcLbClientStatsMetadata::key()) { @@ -2447,6 +2465,7 @@ class ClientChannel::LoadBalancedCall::Metadata std::vector> TestOnlyCopyToVector() override { + if (batch_ == nullptr) return {}; Encoder encoder; batch_->Encode(&encoder); return encoder.Take(); @@ -2454,6 +2473,7 @@ class ClientChannel::LoadBalancedCall::Metadata absl::optional Lookup(absl::string_view key, std::string* buffer) const override { + if (batch_ == nullptr) return absl::nullopt; return batch_->GetStringValue(key, buffer); } @@ -2524,7 +2544,8 @@ class ClientChannel::LoadBalancedCall::BackendMetricAccessor : lb_call_(lb_call) {} const BackendMetricData* GetBackendMetricData() override { - if (lb_call_->backend_metric_data_ == nullptr) { + if (lb_call_->backend_metric_data_ == nullptr && + lb_call_->recv_trailing_metadata_ != nullptr) { if (const auto* md = lb_call_->recv_trailing_metadata_->get_pointer( XEndpointLoadMetricsBinMetadata())) { lb_call_->backend_metric_data_ = @@ -2560,7 +2581,7 @@ ClientChannel::LoadBalancedCall::LoadBalancedCall( ConfigSelector::CallDispatchController* call_dispatch_controller, bool is_transparent_retry) : InternallyRefCounted( - GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace) + GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace) ? "LoadBalancedCall" : nullptr), chand_(chand), @@ -2574,7 +2595,11 @@ ClientChannel::LoadBalancedCall::LoadBalancedCall( on_call_destruction_complete_(on_call_destruction_complete), call_dispatch_controller_(call_dispatch_controller), call_attempt_tracer_( - GetCallAttemptTracer(args.context, is_transparent_retry)) {} + GetCallAttemptTracer(args.context, is_transparent_retry)) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) { + gpr_log(GPR_INFO, "chand=%p lb_call=%p: created", chand_, this); + } +} ClientChannel::LoadBalancedCall::~LoadBalancedCall() { GRPC_ERROR_UNREF(cancel_error_); @@ -2594,6 +2619,12 @@ ClientChannel::LoadBalancedCall::~LoadBalancedCall() { } void ClientChannel::LoadBalancedCall::Orphan() { + // If the recv_trailing_metadata op was never started, then notify + // about call completion here, as best we can. We assume status + // CANCELLED in this case. + if (recv_trailing_metadata_ == nullptr) { + RecordCallCompletion(absl::CancelledError("call cancelled")); + } // Compute latency and report it to the tracer. if (call_attempt_tracer_ != nullptr) { gpr_timespec latency = @@ -2620,7 +2651,7 @@ size_t ClientChannel::LoadBalancedCall::GetBatchIndex( void ClientChannel::LoadBalancedCall::PendingBatchesAdd( grpc_transport_stream_op_batch* batch) { const size_t idx = GetBatchIndex(batch); - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) { gpr_log(GPR_INFO, "chand=%p lb_call=%p: adding pending batch at index %" PRIuPTR, chand_, this, idx); @@ -2647,7 +2678,7 @@ void ClientChannel::LoadBalancedCall::PendingBatchesFail( GPR_ASSERT(error != GRPC_ERROR_NONE); GRPC_ERROR_UNREF(failure_error_); failure_error_ = error; - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) { size_t num_batches = 0; for (size_t i = 0; i < GPR_ARRAY_SIZE(pending_batches_); ++i) { if (pending_batches_[i] != nullptr) ++num_batches; @@ -2689,7 +2720,7 @@ void ClientChannel::LoadBalancedCall::ResumePendingBatchInCallCombiner( // This is called via the call combiner, so access to calld is synchronized. void ClientChannel::LoadBalancedCall::PendingBatchesResume() { - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) { size_t num_batches = 0; for (size_t i = 0; i < GPR_ARRAY_SIZE(pending_batches_); ++i) { if (pending_batches_[i] != nullptr) ++num_batches; @@ -2718,6 +2749,14 @@ void ClientChannel::LoadBalancedCall::PendingBatchesResume() { void ClientChannel::LoadBalancedCall::StartTransportStreamOpBatch( grpc_transport_stream_op_batch* batch) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace) || + GRPC_TRACE_FLAG_ENABLED(grpc_trace_channel)) { + gpr_log(GPR_INFO, + "chand=%p lb_call=%p: batch started from above: %s, " + "call_attempt_tracer_=%p", + chand_, this, grpc_transport_stream_op_batch_string(batch).c_str(), + call_attempt_tracer_); + } // Handle call tracing. if (call_attempt_tracer_ != nullptr) { // Record send ops in tracer. @@ -2781,7 +2820,7 @@ void ClientChannel::LoadBalancedCall::StartTransportStreamOpBatch( // the channel's data plane mutex, which is more efficient (especially for // streaming calls). if (subchannel_call_ != nullptr) { - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) { gpr_log(GPR_INFO, "chand=%p lb_call=%p: starting batch on subchannel_call=%p", chand_, this, subchannel_call_.get()); @@ -2793,7 +2832,7 @@ void ClientChannel::LoadBalancedCall::StartTransportStreamOpBatch( // // If we've previously been cancelled, immediately fail any new batches. if (GPR_UNLIKELY(cancel_error_ != GRPC_ERROR_NONE)) { - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) { gpr_log(GPR_INFO, "chand=%p lb_call=%p: failing batch with error: %s", chand_, this, grpc_error_std_string(cancel_error_).c_str()); } @@ -2811,7 +2850,7 @@ void ClientChannel::LoadBalancedCall::StartTransportStreamOpBatch( // error to the caller when the first batch does get passed down. GRPC_ERROR_UNREF(cancel_error_); cancel_error_ = GRPC_ERROR_REF(batch->payload->cancel_stream.cancel_error); - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) { gpr_log(GPR_INFO, "chand=%p lb_call=%p: recording cancel_error=%s", chand_, this, grpc_error_std_string(cancel_error_).c_str()); } @@ -2827,7 +2866,7 @@ void ClientChannel::LoadBalancedCall::StartTransportStreamOpBatch( // For batches containing a send_initial_metadata op, acquire the // channel's data plane mutex to pick a subchannel. if (GPR_LIKELY(batch->send_initial_metadata)) { - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) { gpr_log(GPR_INFO, "chand=%p lb_call=%p: grabbing data plane mutex to perform pick", chand_, this); @@ -2835,7 +2874,7 @@ void ClientChannel::LoadBalancedCall::StartTransportStreamOpBatch( PickSubchannel(this, GRPC_ERROR_NONE); } else { // For all other batches, release the call combiner. - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) { gpr_log(GPR_INFO, "chand=%p lb_call=%p: saved batch, yielding call combiner", chand_, this); @@ -2848,6 +2887,12 @@ void ClientChannel::LoadBalancedCall::StartTransportStreamOpBatch( void ClientChannel::LoadBalancedCall::SendInitialMetadataOnComplete( void* arg, grpc_error_handle error) { auto* self = static_cast(arg); + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) { + gpr_log(GPR_INFO, + "chand=%p lb_call=%p: got on_complete for send_initial_metadata: " + "error=%s", + self->chand_, self, grpc_error_std_string(error).c_str()); + } self->call_attempt_tracer_->RecordOnDoneSendInitialMetadata( self->peer_string_); Closure::Run(DEBUG_LOCATION, @@ -2858,6 +2903,11 @@ void ClientChannel::LoadBalancedCall::SendInitialMetadataOnComplete( void ClientChannel::LoadBalancedCall::RecvInitialMetadataReady( void* arg, grpc_error_handle error) { auto* self = static_cast(arg); + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) { + gpr_log(GPR_INFO, + "chand=%p lb_call=%p: got recv_initial_metadata_ready: error=%s", + self->chand_, self, grpc_error_std_string(error).c_str()); + } if (error == GRPC_ERROR_NONE) { // recv_initial_metadata_flags is not populated for clients self->call_attempt_tracer_->RecordReceivedInitialMetadata( @@ -2870,6 +2920,10 @@ void ClientChannel::LoadBalancedCall::RecvInitialMetadataReady( void ClientChannel::LoadBalancedCall::RecvMessageReady( void* arg, grpc_error_handle error) { auto* self = static_cast(arg); + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) { + gpr_log(GPR_INFO, "chand=%p lb_call=%p: got recv_message_ready: error=%s", + self->chand_, self, grpc_error_std_string(error).c_str()); + } if (*self->recv_message_ != nullptr) { self->call_attempt_tracer_->RecordReceivedMessage(**self->recv_message_); } @@ -2880,6 +2934,15 @@ void ClientChannel::LoadBalancedCall::RecvMessageReady( void ClientChannel::LoadBalancedCall::RecvTrailingMetadataReady( void* arg, grpc_error_handle error) { auto* self = static_cast(arg); + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) { + gpr_log(GPR_INFO, + "chand=%p lb_call=%p: got recv_trailing_metadata_ready: error=%s " + "call_attempt_tracer_=%p lb_subchannel_call_tracker_=%p " + "failure_error_=%s", + self->chand_, self, grpc_error_std_string(error).c_str(), + self->call_attempt_tracer_, self->lb_subchannel_call_tracker_.get(), + grpc_error_std_string(self->failure_error_).c_str()); + } // Check if we have a tracer or an LB callback to invoke. if (self->call_attempt_tracer_ != nullptr || self->lb_subchannel_call_tracker_ != nullptr) { @@ -2905,22 +2968,7 @@ void ClientChannel::LoadBalancedCall::RecvTrailingMetadataReady( status = absl::Status(static_cast(code), message); } } - // If we have a tracer, notify it. - if (self->call_attempt_tracer_ != nullptr) { - self->call_attempt_tracer_->RecordReceivedTrailingMetadata( - status, self->recv_trailing_metadata_, - *self->transport_stream_stats_); - } - // If the LB policy requested a callback for trailing metadata, invoke - // the callback. - if (self->lb_subchannel_call_tracker_ != nullptr) { - Metadata trailing_metadata(self->recv_trailing_metadata_); - BackendMetricAccessor backend_metric_accessor(self); - LoadBalancingPolicy::SubchannelCallTrackerInterface::FinishArgs args = { - status, &trailing_metadata, &backend_metric_accessor}; - self->lb_subchannel_call_tracker_->Finish(args); - self->lb_subchannel_call_tracker_.reset(); - } + self->RecordCallCompletion(status); } // Chain to original callback. if (self->failure_error_ != GRPC_ERROR_NONE) { @@ -2933,6 +2981,25 @@ void ClientChannel::LoadBalancedCall::RecvTrailingMetadataReady( error); } +void ClientChannel::LoadBalancedCall::RecordCallCompletion( + absl::Status status) { + // If we have a tracer, notify it. + if (call_attempt_tracer_ != nullptr) { + call_attempt_tracer_->RecordReceivedTrailingMetadata( + status, recv_trailing_metadata_, transport_stream_stats_); + } + // If the LB policy requested a callback for trailing metadata, invoke + // the callback. + if (lb_subchannel_call_tracker_ != nullptr) { + Metadata trailing_metadata(recv_trailing_metadata_); + BackendMetricAccessor backend_metric_accessor(this); + LoadBalancingPolicy::SubchannelCallTrackerInterface::FinishArgs args = { + status, &trailing_metadata, &backend_metric_accessor}; + lb_subchannel_call_tracker_->Finish(args); + lb_subchannel_call_tracker_.reset(); + } +} + void ClientChannel::LoadBalancedCall::CreateSubchannelCall() { SubchannelCall::Args call_args = { std::move(connected_subchannel_), pollent_, path_.Ref(), /*start_time=*/0, @@ -2942,7 +3009,7 @@ void ClientChannel::LoadBalancedCall::CreateSubchannelCall() { call_context_, call_combiner_}; grpc_error_handle error = GRPC_ERROR_NONE; subchannel_call_ = SubchannelCall::Create(std::move(call_args), &error); - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) { gpr_log(GPR_INFO, "chand=%p lb_call=%p: create subchannel_call=%p: error=%s", chand_, this, subchannel_call_.get(), grpc_error_std_string(error).c_str()); @@ -2981,7 +3048,7 @@ class ClientChannel::LoadBalancedCall::LbQueuedCallCanceller { auto* chand = lb_call->chand_; { MutexLock lock(&chand->data_plane_mu_); - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) { gpr_log(GPR_INFO, "chand=%p lb_call=%p: cancelling queued pick: " "error=%s self=%p calld->pick_canceller=%p", @@ -3007,7 +3074,7 @@ class ClientChannel::LoadBalancedCall::LbQueuedCallCanceller { void ClientChannel::LoadBalancedCall::MaybeRemoveCallFromLbQueuedCallsLocked() { if (!queued_pending_lb_pick_) return; - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) { gpr_log(GPR_INFO, "chand=%p lb_call=%p: removing from queued picks list", chand_, this); } @@ -3019,7 +3086,7 @@ void ClientChannel::LoadBalancedCall::MaybeRemoveCallFromLbQueuedCallsLocked() { void ClientChannel::LoadBalancedCall::MaybeAddCallToLbQueuedCallsLocked() { if (queued_pending_lb_pick_) return; - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) { gpr_log(GPR_INFO, "chand=%p lb_call=%p: adding to queued picks list", chand_, this); } @@ -3040,7 +3107,7 @@ void ClientChannel::LoadBalancedCall::PickDone(void* arg, grpc_error_handle error) { auto* self = static_cast(arg); if (error != GRPC_ERROR_NONE) { - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) { gpr_log(GPR_INFO, "chand=%p lb_call=%p: failed to pick subchannel: error=%s", self->chand_, self, grpc_error_std_string(error).c_str()); @@ -3090,7 +3157,7 @@ bool ClientChannel::LoadBalancedCall::PickSubchannelLocked( // CompletePick [this](LoadBalancingPolicy::PickResult::Complete* complete_pick) ABSL_EXCLUSIVE_LOCKS_REQUIRED(&ClientChannel::data_plane_mu_) { - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) { gpr_log(GPR_INFO, "chand=%p lb_call=%p: LB pick succeeded: subchannel=%p", chand_, this, complete_pick->subchannel.get()); @@ -3106,7 +3173,7 @@ bool ClientChannel::LoadBalancedCall::PickSubchannelLocked( // yet seen that change and given us a new picker), then just // queue the pick. We'll try again as soon as we get a new picker. if (connected_subchannel_ == nullptr) { - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) { gpr_log(GPR_INFO, "chand=%p lb_call=%p: subchannel returned by LB picker " "has no connected subchannel; queueing pick", @@ -3126,7 +3193,7 @@ bool ClientChannel::LoadBalancedCall::PickSubchannelLocked( // QueuePick [this](LoadBalancingPolicy::PickResult::Queue* /*queue_pick*/) ABSL_EXCLUSIVE_LOCKS_REQUIRED(&ClientChannel::data_plane_mu_) { - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) { gpr_log(GPR_INFO, "chand=%p lb_call=%p: LB pick queued", chand_, this); } @@ -3137,7 +3204,7 @@ bool ClientChannel::LoadBalancedCall::PickSubchannelLocked( [this, send_initial_metadata_flags, &error](LoadBalancingPolicy::PickResult::Fail* fail_pick) ABSL_EXCLUSIVE_LOCKS_REQUIRED(&ClientChannel::data_plane_mu_) { - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) { gpr_log(GPR_INFO, "chand=%p lb_call=%p: LB pick failed: %s", chand_, this, fail_pick->status.ToString().c_str()); } @@ -3161,7 +3228,7 @@ bool ClientChannel::LoadBalancedCall::PickSubchannelLocked( // DropPick [this, &error](LoadBalancingPolicy::PickResult::Drop* drop_pick) ABSL_EXCLUSIVE_LOCKS_REQUIRED(&ClientChannel::data_plane_mu_) { - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) { gpr_log(GPR_INFO, "chand=%p lb_call=%p: LB pick dropped: %s", chand_, this, drop_pick->status.ToString().c_str()); } diff --git a/src/core/ext/filters/client_channel/client_channel.h b/src/core/ext/filters/client_channel/client_channel.h index b1f76f997d1..170d4a6813d 100644 --- a/src/core/ext/filters/client_channel/client_channel.h +++ b/src/core/ext/filters/client_channel/client_channel.h @@ -433,6 +433,8 @@ class ClientChannel::LoadBalancedCall static void RecvMessageReady(void* arg, grpc_error_handle error); static void RecvTrailingMetadataReady(void* arg, grpc_error_handle error); + void RecordCallCompletion(absl::Status status); + void CreateSubchannelCall(); // Invoked when a pick is completed, on both success or failure. static void PickDone(void* arg, grpc_error_handle error); diff --git a/src/core/ext/filters/client_channel/lb_policy/priority/priority.cc b/src/core/ext/filters/client_channel/lb_policy/priority/priority.cc index 257c36b4bea..d6816732a45 100644 --- a/src/core/ext/filters/client_channel/lb_policy/priority/priority.cc +++ b/src/core/ext/filters/client_channel/lb_policy/priority/priority.cc @@ -106,7 +106,6 @@ class PriorityLb : public LoadBalancingPolicy { void ResetBackoffLocked(); void DeactivateLocked(); void MaybeReactivateLocked(); - void MaybeCancelFailoverTimerLocked(); void Orphan() override; @@ -122,9 +121,7 @@ class PriorityLb : public LoadBalancingPolicy { return connectivity_status_; } - bool failover_timer_callback_pending() const { - return failover_timer_callback_pending_; - } + bool FailoverTimerPending() const { return failover_timer_ != nullptr; } private: // A simple wrapper for ref-counting a picker from the child policy. @@ -170,6 +167,38 @@ class PriorityLb : public LoadBalancingPolicy { RefCountedPtr priority_; }; + class DeactivationTimer : public InternallyRefCounted { + public: + explicit DeactivationTimer(RefCountedPtr child_priority); + + void Orphan() override; + + private: + static void OnTimer(void* arg, grpc_error_handle error); + void OnTimerLocked(grpc_error_handle); + + RefCountedPtr child_priority_; + grpc_timer timer_; + grpc_closure on_timer_; + bool timer_pending_ = true; + }; + + class FailoverTimer : public InternallyRefCounted { + public: + explicit FailoverTimer(RefCountedPtr child_priority); + + void Orphan() override; + + private: + static void OnTimer(void* arg, grpc_error_handle error); + void OnTimerLocked(grpc_error_handle); + + RefCountedPtr child_priority_; + grpc_timer timer_; + grpc_closure on_timer_; + bool timer_pending_ = true; + }; + // Methods for dealing with the child policy. OrphanablePtr CreateChildPolicyLocked( const grpc_channel_args* args); @@ -178,13 +207,6 @@ class PriorityLb : public LoadBalancingPolicy { grpc_connectivity_state state, const absl::Status& status, std::unique_ptr picker); - void StartFailoverTimerLocked(); - - static void OnFailoverTimer(void* arg, grpc_error_handle error); - void OnFailoverTimerLocked(grpc_error_handle error); - static void OnDeactivationTimer(void* arg, grpc_error_handle error); - void OnDeactivationTimerLocked(grpc_error_handle error); - RefCountedPtr priority_policy_; const std::string name_; bool ignore_reresolution_requests_ = false; @@ -195,15 +217,8 @@ class PriorityLb : public LoadBalancingPolicy { absl::Status connectivity_status_; RefCountedPtr picker_wrapper_; - // States for delayed removal. - grpc_timer deactivation_timer_; - grpc_closure on_deactivation_timer_; - bool deactivation_timer_callback_pending_ = false; - - // States of failover. - grpc_timer failover_timer_; - grpc_closure on_failover_timer_; - bool failover_timer_callback_pending_ = false; + OrphanablePtr deactivation_timer_; + OrphanablePtr failover_timer_; }; ~PriorityLb() override; @@ -451,7 +466,7 @@ void PriorityLb::TryNextPriorityLocked(bool report_connecting) { } // Child is not READY or IDLE. // If its failover timer is still pending, give it time to fire. - if (child->failover_timer_callback_pending()) { + if (child->FailoverTimerPending()) { if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_priority_trace)) { gpr_log(GPR_INFO, "[priority_lb %p] priority %u, child %s: child still " @@ -501,6 +516,132 @@ void PriorityLb::SelectPriorityLocked(uint32_t priority) { child->GetPicker()); } +// +// PriorityLb::ChildPriority::DeactivationTimer +// + +PriorityLb::ChildPriority::DeactivationTimer::DeactivationTimer( + RefCountedPtr child_priority) + : child_priority_(std::move(child_priority)) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_priority_trace)) { + gpr_log(GPR_INFO, + "[priority_lb %p] child %s (%p): deactivating -- will remove in " + "%" PRId64 "ms", + child_priority_->priority_policy_.get(), + child_priority_->name_.c_str(), child_priority_.get(), + kChildRetentionInterval.millis()); + } + GRPC_CLOSURE_INIT(&on_timer_, OnTimer, this, nullptr); + Ref(DEBUG_LOCATION, "Timer").release(); + grpc_timer_init(&timer_, ExecCtx::Get()->Now() + kChildRetentionInterval, + &on_timer_); +} + +void PriorityLb::ChildPriority::DeactivationTimer::Orphan() { + if (timer_pending_) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_priority_trace)) { + gpr_log(GPR_INFO, "[priority_lb %p] child %s (%p): reactivating", + child_priority_->priority_policy_.get(), + child_priority_->name_.c_str(), child_priority_.get()); + } + timer_pending_ = false; + grpc_timer_cancel(&timer_); + } + Unref(); +} + +void PriorityLb::ChildPriority::DeactivationTimer::OnTimer( + void* arg, grpc_error_handle error) { + auto* self = static_cast(arg); + (void)GRPC_ERROR_REF(error); // ref owned by lambda + self->child_priority_->priority_policy_->work_serializer()->Run( + [self, error]() { self->OnTimerLocked(error); }, DEBUG_LOCATION); +} + +void PriorityLb::ChildPriority::DeactivationTimer::OnTimerLocked( + grpc_error_handle error) { + if (error == GRPC_ERROR_NONE && timer_pending_) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_priority_trace)) { + gpr_log(GPR_INFO, + "[priority_lb %p] child %s (%p): deactivation timer fired, " + "deleting child", + child_priority_->priority_policy_.get(), + child_priority_->name_.c_str(), child_priority_.get()); + } + timer_pending_ = false; + child_priority_->priority_policy_->DeleteChild(child_priority_.get()); + } + Unref(DEBUG_LOCATION, "Timer"); + GRPC_ERROR_UNREF(error); +} + +// +// PriorityLb::ChildPriority::FailoverTimer +// + +PriorityLb::ChildPriority::FailoverTimer::FailoverTimer( + RefCountedPtr child_priority) + : child_priority_(std::move(child_priority)) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_priority_trace)) { + gpr_log( + GPR_INFO, + "[priority_lb %p] child %s (%p): starting failover timer for %" PRId64 + "ms", + child_priority_->priority_policy_.get(), child_priority_->name_.c_str(), + child_priority_.get(), + child_priority_->priority_policy_->child_failover_timeout_.millis()); + } + GRPC_CLOSURE_INIT(&on_timer_, OnTimer, this, nullptr); + Ref(DEBUG_LOCATION, "Timer").release(); + grpc_timer_init( + &timer_, + ExecCtx::Get()->Now() + + child_priority_->priority_policy_->child_failover_timeout_, + &on_timer_); +} + +void PriorityLb::ChildPriority::FailoverTimer::Orphan() { + if (timer_pending_) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_priority_trace)) { + gpr_log(GPR_INFO, + "[priority_lb %p] child %s (%p): cancelling failover timer", + child_priority_->priority_policy_.get(), + child_priority_->name_.c_str(), child_priority_.get()); + } + timer_pending_ = false; + grpc_timer_cancel(&timer_); + } + Unref(); +} + +void PriorityLb::ChildPriority::FailoverTimer::OnTimer( + void* arg, grpc_error_handle error) { + auto* self = static_cast(arg); + (void)GRPC_ERROR_REF(error); // ref owned by lambda + self->child_priority_->priority_policy_->work_serializer()->Run( + [self, error]() { self->OnTimerLocked(error); }, DEBUG_LOCATION); +} + +void PriorityLb::ChildPriority::FailoverTimer::OnTimerLocked( + grpc_error_handle error) { + if (error == GRPC_ERROR_NONE && timer_pending_) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_priority_trace)) { + gpr_log(GPR_INFO, + "[priority_lb %p] child %s (%p): failover timer fired, " + "reporting TRANSIENT_FAILURE", + child_priority_->priority_policy_.get(), + child_priority_->name_.c_str(), child_priority_.get()); + } + timer_pending_ = false; + child_priority_->OnConnectivityStateUpdateLocked( + GRPC_CHANNEL_TRANSIENT_FAILURE, + absl::Status(absl::StatusCode::kUnavailable, "failover timer fired"), + nullptr); + } + Unref(DEBUG_LOCATION, "Timer"); + GRPC_ERROR_UNREF(error); +} + // // PriorityLb::ChildPriority // @@ -512,12 +653,8 @@ PriorityLb::ChildPriority::ChildPriority( gpr_log(GPR_INFO, "[priority_lb %p] creating child %s (%p)", priority_policy_.get(), name_.c_str(), this); } - GRPC_CLOSURE_INIT(&on_failover_timer_, OnFailoverTimer, this, - grpc_schedule_on_exec_ctx); - GRPC_CLOSURE_INIT(&on_deactivation_timer_, OnDeactivationTimer, this, - grpc_schedule_on_exec_ctx); // Start the failover timer. - StartFailoverTimerLocked(); + failover_timer_ = MakeOrphanable(Ref()); } void PriorityLb::ChildPriority::Orphan() { @@ -525,10 +662,8 @@ void PriorityLb::ChildPriority::Orphan() { gpr_log(GPR_INFO, "[priority_lb %p] child %s (%p): orphaned", priority_policy_.get(), name_.c_str(), this); } - MaybeCancelFailoverTimerLocked(); - if (deactivation_timer_callback_pending_) { - grpc_timer_cancel(&deactivation_timer_); - } + failover_timer_.reset(); + deactivation_timer_.reset(); // Remove the child policy's interested_parties pollset_set from the // xDS policy. grpc_pollset_set_del_pollset_set(child_policy_->interested_parties(), @@ -537,9 +672,6 @@ void PriorityLb::ChildPriority::Orphan() { // Drop our ref to the child's picker, in case it's holding a ref to // the child. picker_wrapper_.reset(); - if (deactivation_timer_callback_pending_) { - grpc_timer_cancel(&deactivation_timer_); - } Unref(DEBUG_LOCATION, "ChildPriority+Orphan"); } @@ -600,9 +732,8 @@ PriorityLb::ChildPriority::CreateChildPolicyLocked( } void PriorityLb::ChildPriority::ExitIdleLocked() { - if (connectivity_state_ == GRPC_CHANNEL_IDLE && - !failover_timer_callback_pending_) { - StartFailoverTimerLocked(); + if (connectivity_state_ == GRPC_CHANNEL_IDLE && failover_timer_ == nullptr) { + failover_timer_ = MakeOrphanable(Ref()); } child_policy_->ExitIdleLocked(); } @@ -628,122 +759,21 @@ void PriorityLb::ChildPriority::OnConnectivityStateUpdateLocked( // If READY or IDLE or TRANSIENT_FAILURE, cancel failover timer. if (state == GRPC_CHANNEL_READY || state == GRPC_CHANNEL_IDLE || state == GRPC_CHANNEL_TRANSIENT_FAILURE) { - MaybeCancelFailoverTimerLocked(); + failover_timer_.reset(); } // Notify the parent policy. priority_policy_->HandleChildConnectivityStateChangeLocked(this); } -void PriorityLb::ChildPriority::StartFailoverTimerLocked() { - if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_priority_trace)) { - gpr_log( - GPR_INFO, - "[priority_lb %p] child %s (%p): starting failover timer for %" PRId64 - "ms", - priority_policy_.get(), name_.c_str(), this, - priority_policy_->child_failover_timeout_.millis()); - } - Ref(DEBUG_LOCATION, "ChildPriority+OnFailoverTimerLocked").release(); - grpc_timer_init( - &failover_timer_, - ExecCtx::Get()->Now() + priority_policy_->child_failover_timeout_, - &on_failover_timer_); - failover_timer_callback_pending_ = true; -} - -void PriorityLb::ChildPriority::MaybeCancelFailoverTimerLocked() { - if (failover_timer_callback_pending_) { - if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_priority_trace)) { - gpr_log(GPR_INFO, - "[priority_lb %p] child %s (%p): cancelling failover timer", - priority_policy_.get(), name_.c_str(), this); - } - grpc_timer_cancel(&failover_timer_); - failover_timer_callback_pending_ = false; - } -} - -void PriorityLb::ChildPriority::OnFailoverTimer(void* arg, - grpc_error_handle error) { - ChildPriority* self = static_cast(arg); - (void)GRPC_ERROR_REF(error); // ref owned by lambda - self->priority_policy_->work_serializer()->Run( - [self, error]() { self->OnFailoverTimerLocked(error); }, DEBUG_LOCATION); -} - -void PriorityLb::ChildPriority::OnFailoverTimerLocked(grpc_error_handle error) { - if (error == GRPC_ERROR_NONE && failover_timer_callback_pending_ && - !priority_policy_->shutting_down_) { - if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_priority_trace)) { - gpr_log(GPR_INFO, - "[priority_lb %p] child %s (%p): failover timer fired, " - "reporting TRANSIENT_FAILURE", - priority_policy_.get(), name_.c_str(), this); - } - failover_timer_callback_pending_ = false; - OnConnectivityStateUpdateLocked( - GRPC_CHANNEL_TRANSIENT_FAILURE, - absl::Status(absl::StatusCode::kUnavailable, "failover timer fired"), - nullptr); - } - Unref(DEBUG_LOCATION, "ChildPriority+OnFailoverTimerLocked"); - GRPC_ERROR_UNREF(error); -} - void PriorityLb::ChildPriority::DeactivateLocked() { // If already deactivated, don't do it again. - if (deactivation_timer_callback_pending_) return; - if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_priority_trace)) { - gpr_log(GPR_INFO, - "[priority_lb %p] child %s (%p): deactivating -- will remove in " - "%" PRId64 "ms.", - priority_policy_.get(), name_.c_str(), this, - kChildRetentionInterval.millis()); - } - MaybeCancelFailoverTimerLocked(); - // Start a timer to delete the child. - Ref(DEBUG_LOCATION, "ChildPriority+timer").release(); - grpc_timer_init(&deactivation_timer_, - ExecCtx::Get()->Now() + kChildRetentionInterval, - &on_deactivation_timer_); - deactivation_timer_callback_pending_ = true; + if (deactivation_timer_ != nullptr) return; + failover_timer_.reset(); + deactivation_timer_ = MakeOrphanable(Ref()); } void PriorityLb::ChildPriority::MaybeReactivateLocked() { - if (deactivation_timer_callback_pending_) { - if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_priority_trace)) { - gpr_log(GPR_INFO, "[priority_lb %p] child %s (%p): reactivating", - priority_policy_.get(), name_.c_str(), this); - } - deactivation_timer_callback_pending_ = false; - grpc_timer_cancel(&deactivation_timer_); - } -} - -void PriorityLb::ChildPriority::OnDeactivationTimer(void* arg, - grpc_error_handle error) { - ChildPriority* self = static_cast(arg); - (void)GRPC_ERROR_REF(error); // ref owned by lambda - self->priority_policy_->work_serializer()->Run( - [self, error]() { self->OnDeactivationTimerLocked(error); }, - DEBUG_LOCATION); -} - -void PriorityLb::ChildPriority::OnDeactivationTimerLocked( - grpc_error_handle error) { - if (error == GRPC_ERROR_NONE && deactivation_timer_callback_pending_ && - !priority_policy_->shutting_down_) { - if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_priority_trace)) { - gpr_log(GPR_INFO, - "[priority_lb %p] child %s (%p): deactivation timer fired, " - "deleting child", - priority_policy_.get(), name_.c_str(), this); - } - deactivation_timer_callback_pending_ = false; - priority_policy_->DeleteChild(this); - } - Unref(DEBUG_LOCATION, "ChildPriority+timer"); - GRPC_ERROR_UNREF(error); + deactivation_timer_.reset(); } // diff --git a/src/core/ext/filters/client_channel/lb_policy/rls/rls.cc b/src/core/ext/filters/client_channel/lb_policy/rls/rls.cc index 068af6102a1..e7bd80895f9 100644 --- a/src/core/ext/filters/client_channel/lb_policy/rls/rls.cc +++ b/src/core/ext/filters/client_channel/lb_policy/rls/rls.cc @@ -83,7 +83,7 @@ TraceFlag grpc_lb_rls_trace(false, "rls_lb"); namespace { -const char* kRls = "rls"; +const char* kRls = "rls_experimental"; const char kGrpc[] = "grpc"; const char* kRlsRequestPath = "/grpc.lookup.v1.RouteLookupService/RouteLookup"; const char* kFakeTargetFieldValue = "fake_target_field_value"; @@ -2530,18 +2530,9 @@ class RlsLbFactory : public LoadBalancingPolicyFactory { } }; -bool RlsEnabled() { - char* value = gpr_getenv("GRPC_EXPERIMENTAL_ENABLE_RLS_LB_POLICY"); - bool parsed_value; - bool parse_succeeded = gpr_parse_bool_value(value, &parsed_value); - gpr_free(value); - return parse_succeeded && parsed_value; -} - } // namespace void RlsLbPluginInit() { - if (!RlsEnabled()) return; LoadBalancingPolicyRegistry::Builder::RegisterLoadBalancingPolicyFactory( absl::make_unique()); } diff --git a/src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc b/src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc index d09f9fe1421..2aba42a730f 100644 --- a/src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc +++ b/src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc @@ -158,6 +158,23 @@ class WeightedTargetLb : public LoadBalancingPolicy { RefCountedPtr weighted_child_; }; + class DelayedRemovalTimer + : public InternallyRefCounted { + public: + explicit DelayedRemovalTimer(RefCountedPtr weighted_child); + + void Orphan() override; + + private: + static void OnTimer(void* arg, grpc_error_handle error); + void OnTimerLocked(grpc_error_handle error); + + RefCountedPtr weighted_child_; + grpc_timer timer_; + grpc_closure on_timer_; + bool timer_pending_ = true; + }; + // Methods for dealing with the child policy. OrphanablePtr CreateChildPolicyLocked( const grpc_channel_args* args); @@ -166,9 +183,6 @@ class WeightedTargetLb : public LoadBalancingPolicy { grpc_connectivity_state state, const absl::Status& status, std::unique_ptr picker); - static void OnDelayedRemovalTimer(void* arg, grpc_error_handle error); - void OnDelayedRemovalTimerLocked(grpc_error_handle error); - // The owning LB policy. RefCountedPtr weighted_target_policy_; @@ -182,11 +196,7 @@ class WeightedTargetLb : public LoadBalancingPolicy { grpc_connectivity_state connectivity_state_ = GRPC_CHANNEL_CONNECTING; bool seen_failure_since_ready_ = false; - // States for delayed removal. - grpc_timer delayed_removal_timer_; - grpc_closure on_delayed_removal_timer_; - bool delayed_removal_timer_callback_pending_ = false; - bool shutdown_ = false; + OrphanablePtr delayed_removal_timer_; }; ~WeightedTargetLb() override; @@ -401,6 +411,53 @@ void WeightedTargetLb::UpdateStateLocked() { std::move(picker)); } +// +// WeightedTargetLb::WeightedChild::DelayedRemovalTimer +// + +WeightedTargetLb::WeightedChild::DelayedRemovalTimer::DelayedRemovalTimer( + RefCountedPtr weighted_child) + : weighted_child_(std::move(weighted_child)) { + GRPC_CLOSURE_INIT(&on_timer_, OnTimer, this, nullptr); + Ref().release(); + grpc_timer_init(&timer_, ExecCtx::Get()->Now() + kChildRetentionInterval, + &on_timer_); +} + +void WeightedTargetLb::WeightedChild::DelayedRemovalTimer::Orphan() { + if (timer_pending_) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_weighted_target_trace)) { + gpr_log(GPR_INFO, + "[weighted_target_lb %p] WeightedChild %p %s: cancelling " + "delayed removal timer", + weighted_child_->weighted_target_policy_.get(), + weighted_child_.get(), weighted_child_->name_.c_str()); + } + timer_pending_ = false; + grpc_timer_cancel(&timer_); + } + Unref(); +} + +void WeightedTargetLb::WeightedChild::DelayedRemovalTimer::OnTimer( + void* arg, grpc_error_handle error) { + auto* self = static_cast(arg); + (void)GRPC_ERROR_REF(error); // ref owned by lambda + self->weighted_child_->weighted_target_policy_->work_serializer()->Run( + [self, error]() { self->OnTimerLocked(error); }, DEBUG_LOCATION); +} + +void WeightedTargetLb::WeightedChild::DelayedRemovalTimer::OnTimerLocked( + grpc_error_handle error) { + if (error == GRPC_ERROR_NONE && timer_pending_) { + timer_pending_ = false; + weighted_child_->weighted_target_policy_->targets_.erase( + weighted_child_->name_); + } + GRPC_ERROR_UNREF(error); + Unref(); +} + // // WeightedTargetLb::WeightedChild // @@ -413,8 +470,6 @@ WeightedTargetLb::WeightedChild::WeightedChild( gpr_log(GPR_INFO, "[weighted_target_lb %p] created WeightedChild %p for %s", weighted_target_policy_.get(), this, name_.c_str()); } - GRPC_CLOSURE_INIT(&on_delayed_removal_timer_, OnDelayedRemovalTimer, this, - grpc_schedule_on_exec_ctx); } WeightedTargetLb::WeightedChild::~WeightedChild() { @@ -441,11 +496,7 @@ void WeightedTargetLb::WeightedChild::Orphan() { // Drop our ref to the child's picker, in case it's holding a ref to // the child. picker_wrapper_.reset(); - if (delayed_removal_timer_callback_pending_) { - delayed_removal_timer_callback_pending_ = false; - grpc_timer_cancel(&delayed_removal_timer_); - } - shutdown_ = true; + delayed_removal_timer_.reset(); Unref(); } @@ -484,14 +535,13 @@ void WeightedTargetLb::WeightedChild::UpdateLocked( // Update child weight. weight_ = config.weight; // Reactivate if needed. - if (delayed_removal_timer_callback_pending_) { + if (delayed_removal_timer_ != nullptr) { if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_weighted_target_trace)) { gpr_log(GPR_INFO, "[weighted_target_lb %p] WeightedChild %p %s: reactivating", weighted_target_policy_.get(), this, name_.c_str()); } - delayed_removal_timer_callback_pending_ = false; - grpc_timer_cancel(&delayed_removal_timer_); + delayed_removal_timer_.reset(); } // Create child policy if needed. if (child_policy_ == nullptr) { @@ -561,31 +611,8 @@ void WeightedTargetLb::WeightedChild::DeactivateLocked() { // Set the child weight to 0 so that future picker won't contain this child. weight_ = 0; // Start a timer to delete the child. - Ref(DEBUG_LOCATION, "WeightedChild+timer").release(); - delayed_removal_timer_callback_pending_ = true; - grpc_timer_init(&delayed_removal_timer_, - ExecCtx::Get()->Now() + kChildRetentionInterval, - &on_delayed_removal_timer_); -} - -void WeightedTargetLb::WeightedChild::OnDelayedRemovalTimer( - void* arg, grpc_error_handle error) { - WeightedChild* self = static_cast(arg); - (void)GRPC_ERROR_REF(error); // ref owned by lambda - self->weighted_target_policy_->work_serializer()->Run( - [self, error]() { self->OnDelayedRemovalTimerLocked(error); }, - DEBUG_LOCATION); -} - -void WeightedTargetLb::WeightedChild::OnDelayedRemovalTimerLocked( - grpc_error_handle error) { - if (error == GRPC_ERROR_NONE && delayed_removal_timer_callback_pending_ && - !shutdown_ && weight_ == 0) { - delayed_removal_timer_callback_pending_ = false; - weighted_target_policy_->targets_.erase(name_); - } - Unref(DEBUG_LOCATION, "WeightedChild+timer"); - GRPC_ERROR_UNREF(error); + delayed_removal_timer_ = MakeOrphanable( + Ref(DEBUG_LOCATION, "DelayedRemovalTimer")); } // diff --git a/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_resolver.cc b/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_resolver.cc index 74e1bba6a72..7ce51aa9a06 100644 --- a/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_resolver.cc +++ b/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_resolver.cc @@ -131,24 +131,14 @@ class XdsClusterResolverLb : public LoadBalancingPolicy { RefCountedPtr xds_cluster_resolver_lb, size_t index) : parent_(std::move(xds_cluster_resolver_lb)), index_(index) {} - virtual void Start() = 0; - void Orphan() override = 0; - virtual Json::Array override_child_policy() = 0; - virtual bool disable_reresolution() = 0; - - // Returns a pair containing the cluster and eds_service_name - // to use for LRS load reporting. Caller must ensure that config_ is set - // before calling. - std::pair GetLrsClusterKey() const { - return { - parent_->config_->discovery_mechanisms()[index_].cluster_name, - parent_->config_->discovery_mechanisms()[index_].eds_service_name}; - } - protected: XdsClusterResolverLb* parent() const { return parent_.get(); } size_t index() const { return index_; } + virtual void Start() = 0; + virtual Json::Array override_child_policy() = 0; + virtual bool disable_reresolution() = 0; + private: RefCountedPtr parent_; // Stores its own index in the vector of DiscoveryMechanism. @@ -229,14 +219,9 @@ class XdsClusterResolverLb : public LoadBalancingPolicy { friend class EndpointWatcher; absl::string_view GetEdsResourceName() const { - if (!parent() - ->config_->discovery_mechanisms()[index()] - .eds_service_name.empty()) { - return parent() - ->config_->discovery_mechanisms()[index()] - .eds_service_name; - } - return parent()->config_->discovery_mechanisms()[index()].cluster_name; + auto& config = parent()->config_->discovery_mechanisms()[index()]; + if (!config.eds_service_name.empty()) return config.eds_service_name; + return config.cluster_name; } // Note that this is not owned, so this pointer must never be dereferenced. @@ -284,15 +269,15 @@ class XdsClusterResolverLb : public LoadBalancingPolicy { struct DiscoveryMechanismEntry { OrphanablePtr discovery_mechanism; - bool first_update_received = false; - // Number of priorities this mechanism has contributed to priority_list_. - // (The sum of this across all discovery mechanisms should always equal - // the number of priorities in priority_list_.) - uint32_t num_priorities = 0; - RefCountedPtr drop_config; - // Populated only when an update has been delivered by the mechanism - // but has not yet been applied to the LB policy's combined priority_list_. - absl::optional pending_priority_list; + // Most recent update reported by the discovery mechanism. + absl::optional latest_update; + // State used to retain child policy names for priority policy. + std::vector priority_child_numbers; + + const XdsClusterResolverLbConfig::DiscoveryMechanism& config() const; + + // Returns the child policy name for a given priority. + std::string GetChildPolicyName(size_t priority) const; }; class Helper : public ChannelControlHelper { @@ -331,7 +316,6 @@ class XdsClusterResolverLb : public LoadBalancingPolicy { void MaybeDestroyChildPolicyLocked(); - void UpdatePriorityList(XdsEndpointResource::PriorityList priority_list); void UpdateChildPolicyLocked(); OrphanablePtr CreateChildPolicyLocked( const grpc_channel_args* args); @@ -353,11 +337,6 @@ class XdsClusterResolverLb : public LoadBalancingPolicy { // Vector of discovery mechansism entries in priority order. std::vector discovery_mechanisms_; - // The latest data from the endpoint watcher. - XdsEndpointResource::PriorityList priority_list_; - // State used to retain child policy names for priority policy. - std::vector priority_child_numbers_; - OrphanablePtr child_policy_; }; @@ -510,6 +489,22 @@ void XdsClusterResolverLb::LogicalDNSDiscoveryMechanism::ResolverResultHandler:: discovery_mechanism_->index(), std::move(update)); } +// +// XdsClusterResolverLb::DiscoveryMechanismEntry +// + +const XdsClusterResolverLbConfig::DiscoveryMechanism& +XdsClusterResolverLb::DiscoveryMechanismEntry::config() const { + return discovery_mechanism->parent() + ->config_->discovery_mechanisms()[discovery_mechanism->index()]; +} + +std::string XdsClusterResolverLb::DiscoveryMechanismEntry::GetChildPolicyName( + size_t priority) const { + return absl::StrCat("{cluster=", config().cluster_name, + ", child_number=", priority_child_numbers[priority], "}"); +} + // // XdsClusterResolverLb public methods // @@ -613,99 +608,37 @@ void XdsClusterResolverLb::OnEndpointChanged(size_t index, " for discovery mechanism %" PRIuPTR "", this, index); } + DiscoveryMechanismEntry& discovery_entry = discovery_mechanisms_[index]; // We need at least one priority for each discovery mechanism, just so that we // have a child in which to create the xds_cluster_impl policy. This ensures // that we properly handle the case of a discovery mechanism dropping 100% of // calls, the OnError() case, and the OnResourceDoesNotExist() case. if (update.priorities.empty()) update.priorities.emplace_back(); - discovery_mechanisms_[index].drop_config = std::move(update.drop_config); - discovery_mechanisms_[index].pending_priority_list = - std::move(update.priorities); - discovery_mechanisms_[index].first_update_received = true; - // If any discovery mechanism has not received its first update, - // wait until that happens before creating the child policy. - // TODO(roth): If this becomes problematic in the future (e.g., a - // secondary discovery mechanism delaying us from starting up at all), - // we can consider some sort of optimization whereby we can create the - // priority policy with only a subset of its children. But we need to - // make sure not to get into a situation where the priority policy - // will put the channel into TRANSIENT_FAILURE instead of CONNECTING - // while we're still waiting for the other discovery mechanism(s). - for (DiscoveryMechanismEntry& mechanism : discovery_mechanisms_) { - if (!mechanism.first_update_received) return; - } - // Construct new priority list. - XdsEndpointResource::PriorityList priority_list; - size_t priority_index = 0; - for (DiscoveryMechanismEntry& mechanism : discovery_mechanisms_) { - // If the mechanism has a pending update, use that. - // Otherwise, use the priorities that it previously contributed to the - // combined list. - if (mechanism.pending_priority_list.has_value()) { - priority_list.insert(priority_list.end(), - mechanism.pending_priority_list->begin(), - mechanism.pending_priority_list->end()); - priority_index += mechanism.num_priorities; - mechanism.num_priorities = mechanism.pending_priority_list->size(); - mechanism.pending_priority_list.reset(); - } else { - priority_list.insert( - priority_list.end(), priority_list_.begin() + priority_index, - priority_list_.begin() + priority_index + mechanism.num_priorities); - priority_index += mechanism.num_priorities; - } - } - // Update child policy. - UpdatePriorityList(std::move(priority_list)); -} - -void XdsClusterResolverLb::OnError(size_t index, absl::Status status) { - gpr_log(GPR_ERROR, - "[xds_cluster_resolver_lb %p] discovery mechanism %" PRIuPTR - " xds watcher reported error: %s", - this, index, status.ToString().c_str()); - if (shutting_down_) return; - if (!discovery_mechanisms_[index].first_update_received) { - // Call OnEndpointChanged with an empty update just like - // OnResourceDoesNotExist. - OnEndpointChanged(index, XdsEndpointResource()); - } -} - -void XdsClusterResolverLb::OnResourceDoesNotExist(size_t index) { - gpr_log(GPR_ERROR, - "[xds_cluster_resolver_lb %p] discovery mechanism %" PRIuPTR - " resource does not exist", - this, index); - if (shutting_down_) return; - // Call OnEndpointChanged with an empty update. - OnEndpointChanged(index, XdsEndpointResource()); -} - -// -// child policy-related methods -// - -void XdsClusterResolverLb::UpdatePriorityList( - XdsEndpointResource::PriorityList priority_list) { - // Build some maps from locality to child number and the reverse from - // the old data in priority_list_ and priority_child_numbers_. + // Update priority_child_numbers, reusing old child numbers in an + // intelligent way to avoid unnecessary churn. + // First, build some maps from locality to child number and the reverse + // from the old data in the entry's update and priority_child_numbers. std::map locality_child_map; - std::map> child_locality_map; - for (size_t priority = 0; priority < priority_list_.size(); ++priority) { - size_t child_number = priority_child_numbers_[priority]; - const auto& localities = priority_list_[priority].localities; - for (const auto& p : localities) { - XdsLocalityName* locality_name = p.first; - locality_child_map[locality_name] = child_number; - child_locality_map[child_number].insert(locality_name); + std::map> + child_locality_map; + if (discovery_entry.latest_update.has_value()) { + const auto& prev_priority_list = discovery_entry.latest_update->priorities; + for (size_t priority = 0; priority < prev_priority_list.size(); + ++priority) { + size_t child_number = discovery_entry.priority_child_numbers[priority]; + const auto& localities = prev_priority_list[priority].localities; + for (const auto& p : localities) { + XdsLocalityName* locality_name = p.first; + locality_child_map[locality_name] = child_number; + child_locality_map[child_number].insert(locality_name); + } } } // Construct new list of children. std::vector priority_child_numbers; - for (size_t priority = 0; priority < priority_list.size(); ++priority) { - const auto& localities = priority_list[priority].localities; + for (size_t priority = 0; priority < update.priorities.size(); ++priority) { + const auto& localities = update.priorities[priority].localities; absl::optional child_number; // If one of the localities in this priority already existed, reuse its // child number. @@ -744,42 +677,87 @@ void XdsClusterResolverLb::UpdatePriorityList( priority_child_numbers.push_back(*child_number); } // Save update. - priority_list_ = std::move(priority_list); - priority_child_numbers_ = std::move(priority_child_numbers); + discovery_entry.latest_update = std::move(update); + discovery_entry.priority_child_numbers = std::move(priority_child_numbers); + // If any discovery mechanism has not received its first update, + // wait until that happens before creating the child policy. + // TODO(roth): If this becomes problematic in the future (e.g., a + // secondary discovery mechanism delaying us from starting up at all), + // we can consider some sort of optimization whereby we can create the + // priority policy with only a subset of its children. But we need to + // make sure not to get into a situation where the priority policy + // will put the channel into TRANSIENT_FAILURE instead of CONNECTING + // while we're still waiting for the other discovery mechanism(s). + for (DiscoveryMechanismEntry& mechanism : discovery_mechanisms_) { + if (!mechanism.latest_update.has_value()) return; + } // Update child policy. UpdateChildPolicyLocked(); } +void XdsClusterResolverLb::OnError(size_t index, absl::Status status) { + gpr_log(GPR_ERROR, + "[xds_cluster_resolver_lb %p] discovery mechanism %" PRIuPTR + " xds watcher reported error: %s", + this, index, status.ToString().c_str()); + if (shutting_down_) return; + if (!discovery_mechanisms_[index].latest_update.has_value()) { + // Call OnEndpointChanged with an empty update just like + // OnResourceDoesNotExist. + OnEndpointChanged(index, XdsEndpointResource()); + } +} + +void XdsClusterResolverLb::OnResourceDoesNotExist(size_t index) { + gpr_log(GPR_ERROR, + "[xds_cluster_resolver_lb %p] discovery mechanism %" PRIuPTR + " resource does not exist", + this, index); + if (shutting_down_) return; + // Call OnEndpointChanged with an empty update. + OnEndpointChanged(index, XdsEndpointResource()); +} + +// +// child policy-related methods +// + ServerAddressList XdsClusterResolverLb::CreateChildPolicyAddressesLocked() { ServerAddressList addresses; - for (size_t priority = 0; priority < priority_list_.size(); ++priority) { - const auto& localities = priority_list_[priority].localities; - std::string priority_child_name = - absl::StrCat("child", priority_child_numbers_[priority]); - for (const auto& p : localities) { - const auto& locality_name = p.first; - const auto& locality = p.second; - std::vector hierarchical_path = { - priority_child_name, locality_name->AsHumanReadableString()}; - for (const auto& endpoint : locality.endpoints) { - const ServerAddressWeightAttribute* weight_attribute = static_cast< - const ServerAddressWeightAttribute*>(endpoint.GetAttribute( - ServerAddressWeightAttribute::kServerAddressWeightAttributeKey)); - uint32_t weight = locality.lb_weight; - if (weight_attribute != nullptr) { - weight = locality.lb_weight * weight_attribute->weight(); + for (const auto& discovery_entry : discovery_mechanisms_) { + for (size_t priority = 0; + priority < discovery_entry.latest_update->priorities.size(); + ++priority) { + const auto& priority_entry = + discovery_entry.latest_update->priorities[priority]; + std::string priority_child_name = + discovery_entry.GetChildPolicyName(priority); + for (const auto& p : priority_entry.localities) { + const auto& locality_name = p.first; + const auto& locality = p.second; + std::vector hierarchical_path = { + priority_child_name, locality_name->AsHumanReadableString()}; + for (const auto& endpoint : locality.endpoints) { + const ServerAddressWeightAttribute* weight_attribute = static_cast< + const ServerAddressWeightAttribute*>(endpoint.GetAttribute( + ServerAddressWeightAttribute::kServerAddressWeightAttributeKey)); + uint32_t weight = locality.lb_weight; + if (weight_attribute != nullptr) { + weight = locality.lb_weight * weight_attribute->weight(); + } + addresses.emplace_back( + endpoint + .WithAttribute( + kHierarchicalPathAttributeKey, + MakeHierarchicalPathAttribute(hierarchical_path)) + .WithAttribute(kXdsLocalityNameAttributeKey, + absl::make_unique( + locality_name->Ref())) + .WithAttribute( + ServerAddressWeightAttribute:: + kServerAddressWeightAttributeKey, + absl::make_unique(weight))); } - addresses.emplace_back( - endpoint - .WithAttribute(kHierarchicalPathAttributeKey, - MakeHierarchicalPathAttribute(hierarchical_path)) - .WithAttribute(kXdsLocalityNameAttributeKey, - absl::make_unique( - locality_name->Ref())) - .WithAttribute( - ServerAddressWeightAttribute:: - kServerAddressWeightAttributeKey, - absl::make_unique(weight))); } } } @@ -790,139 +768,106 @@ RefCountedPtr XdsClusterResolverLb::CreateChildPolicyConfigLocked() { Json::Object priority_children; Json::Array priority_priorities; - // Setting up index to iterate through the discovery mechanisms and keeping - // track the discovery_mechanism each priority belongs to. - size_t discovery_index = 0; - // Setting up num_priorities_remaining to track the priorities in each - // discovery_mechanism. - size_t num_priorities_remaining_in_discovery = - discovery_mechanisms_[discovery_index].num_priorities; - for (size_t priority = 0; priority < priority_list_.size(); ++priority) { - Json child_policy; - if (!discovery_mechanisms_[discovery_index] - .discovery_mechanism->override_child_policy() - .empty()) { - child_policy = discovery_mechanisms_[discovery_index] - .discovery_mechanism->override_child_policy(); - } else { - const auto& xds_lb_policy = config_->xds_lb_policy().object_value(); - if (xds_lb_policy.find("ROUND_ROBIN") != xds_lb_policy.end()) { - const auto& localities = priority_list_[priority].localities; - Json::Object weighted_targets; - for (const auto& p : localities) { - XdsLocalityName* locality_name = p.first; - const auto& locality = p.second; - // Construct JSON object containing locality name. - Json::Object locality_name_json; - if (!locality_name->region().empty()) { - locality_name_json["region"] = locality_name->region(); - } - if (!locality_name->zone().empty()) { - locality_name_json["zone"] = locality_name->zone(); - } - if (!locality_name->sub_zone().empty()) { - locality_name_json["sub_zone"] = locality_name->sub_zone(); + for (const auto& discovery_entry : discovery_mechanisms_) { + const auto& discovery_config = discovery_entry.config(); + for (size_t priority = 0; + priority < discovery_entry.latest_update->priorities.size(); + ++priority) { + const auto& priority_entry = + discovery_entry.latest_update->priorities[priority]; + Json child_policy; + if (!discovery_entry.discovery_mechanism->override_child_policy() + .empty()) { + child_policy = + discovery_entry.discovery_mechanism->override_child_policy(); + } else { + const auto& xds_lb_policy = config_->xds_lb_policy().object_value(); + if (xds_lb_policy.find("ROUND_ROBIN") != xds_lb_policy.end()) { + const auto& localities = priority_entry.localities; + Json::Object weighted_targets; + for (const auto& p : localities) { + XdsLocalityName* locality_name = p.first; + const auto& locality = p.second; + // Add weighted target entry. + weighted_targets[locality_name->AsHumanReadableString()] = + Json::Object{ + {"weight", locality.lb_weight}, + {"childPolicy", + Json::Array{ + Json::Object{ + {"round_robin", Json::Object()}, + }, + }}, + }; } - // Add weighted target entry. - weighted_targets[locality_name->AsHumanReadableString()] = + // Construct locality-picking policy. + // Start with field from our config and add the "targets" field. + child_policy = Json::Array{ Json::Object{ - {"weight", locality.lb_weight}, - {"childPolicy", - Json::Array{ - Json::Object{ - {"round_robin", Json::Object()}, - }, + {"weighted_target_experimental", + Json::Object{ + {"targets", Json::Object()}, }}, - }; + }, + }; + Json::Object& config = + *(*child_policy.mutable_array())[0].mutable_object(); + auto it = config.begin(); + GPR_ASSERT(it != config.end()); + (*it->second.mutable_object())["targets"] = + std::move(weighted_targets); + } else { + auto it = xds_lb_policy.find("RING_HASH"); + GPR_ASSERT(it != xds_lb_policy.end()); + Json::Object ring_hash_experimental_policy = + it->second.object_value(); + child_policy = Json::Array{ + Json::Object{ + {"ring_hash_experimental", ring_hash_experimental_policy}, + }, + }; } - // Construct locality-picking policy. - // Start with field from our config and add the "targets" field. - child_policy = Json::Array{ - Json::Object{ - {"weighted_target_experimental", - Json::Object{ - {"targets", Json::Object()}, - }}, - }, - }; - Json::Object& config = - *(*child_policy.mutable_array())[0].mutable_object(); - auto it = config.begin(); - GPR_ASSERT(it != config.end()); - (*it->second.mutable_object())["targets"] = std::move(weighted_targets); - } else { - auto it = xds_lb_policy.find("RING_HASH"); - GPR_ASSERT(it != xds_lb_policy.end()); - Json::Object ring_hash_experimental_policy = it->second.object_value(); - child_policy = Json::Array{ - Json::Object{ - {"ring_hash_experimental", ring_hash_experimental_policy}, - }, - }; } - } - // Wrap it in the drop policy. - Json::Array drop_categories; - if (discovery_mechanisms_[discovery_index].drop_config != nullptr) { - for (const auto& category : discovery_mechanisms_[discovery_index] - .drop_config->drop_category_list()) { - drop_categories.push_back(Json::Object{ - {"category", category.name}, - {"requests_per_million", category.parts_per_million}, - }); + // Wrap it in the drop policy. + Json::Array drop_categories; + if (discovery_entry.latest_update->drop_config != nullptr) { + for (const auto& category : + discovery_entry.latest_update->drop_config->drop_category_list()) { + drop_categories.push_back(Json::Object{ + {"category", category.name}, + {"requests_per_million", category.parts_per_million}, + }); + } } - } - const auto lrs_key = discovery_mechanisms_[discovery_index] - .discovery_mechanism->GetLrsClusterKey(); - Json::Object xds_cluster_impl_config = { - {"clusterName", std::string(lrs_key.first)}, - {"childPolicy", std::move(child_policy)}, - {"dropCategories", std::move(drop_categories)}, - {"maxConcurrentRequests", - config_->discovery_mechanisms()[discovery_index] - .max_concurrent_requests}, - }; - if (!lrs_key.second.empty()) { - xds_cluster_impl_config["edsServiceName"] = std::string(lrs_key.second); - } - if (config_->discovery_mechanisms()[discovery_index] - .lrs_load_reporting_server.has_value()) { - xds_cluster_impl_config["lrsLoadReportingServer"] = - config_->discovery_mechanisms()[discovery_index] - .lrs_load_reporting_server->ToJson(); - } - Json locality_picking_policy = Json::Array{Json::Object{ - {"xds_cluster_impl_experimental", std::move(xds_cluster_impl_config)}, - }}; - // Add priority entry. - const size_t child_number = priority_child_numbers_[priority]; - std::string child_name = absl::StrCat("child", child_number); - priority_priorities.emplace_back(child_name); - Json::Object child_config = { - {"config", std::move(locality_picking_policy)}, - }; - if (discovery_mechanisms_[discovery_index] - .discovery_mechanism->disable_reresolution()) { - child_config["ignore_reresolution_requests"] = true; - } - priority_children[child_name] = std::move(child_config); - // Each priority in the priority_list_ should correspond to a priority in a - // discovery mechanism in discovery_mechanisms_ (both in the same order). - // Keeping track of the discovery_mechanism each priority belongs to. - --num_priorities_remaining_in_discovery; - while (num_priorities_remaining_in_discovery == 0 && - discovery_index < discovery_mechanisms_.size() - 1) { - ++discovery_index; - num_priorities_remaining_in_discovery = - discovery_mechanisms_[discovery_index].num_priorities; + Json::Object xds_cluster_impl_config = { + {"clusterName", discovery_config.cluster_name}, + {"childPolicy", std::move(child_policy)}, + {"dropCategories", std::move(drop_categories)}, + {"maxConcurrentRequests", discovery_config.max_concurrent_requests}, + }; + if (!discovery_config.eds_service_name.empty()) { + xds_cluster_impl_config["edsServiceName"] = + discovery_config.eds_service_name; + } + if (discovery_config.lrs_load_reporting_server.has_value()) { + xds_cluster_impl_config["lrsLoadReportingServer"] = + discovery_config.lrs_load_reporting_server->ToJson(); + } + Json locality_picking_policy = Json::Array{Json::Object{ + {"xds_cluster_impl_experimental", std::move(xds_cluster_impl_config)}, + }}; + // Add priority entry, with the appropriate child name. + std::string child_name = discovery_entry.GetChildPolicyName(priority); + priority_priorities.emplace_back(child_name); + Json::Object child_config = { + {"config", std::move(locality_picking_policy)}, + }; + if (discovery_entry.discovery_mechanism->disable_reresolution()) { + child_config["ignore_reresolution_requests"] = true; + } + priority_children[child_name] = std::move(child_config); } } - // There should be matching number of priorities in discovery_mechanisms_ and - // in priority_list_; therefore at the end of looping through all the - // priorities, num_priorities_remaining should be down to 0, and index should - // be the last index in discovery_mechanisms_. - GPR_ASSERT(num_priorities_remaining_in_discovery == 0); - GPR_ASSERT(discovery_index == discovery_mechanisms_.size() - 1); Json json = Json::Array{Json::Object{ {"priority_experimental", Json::Object{ diff --git a/src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc b/src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc index b30debc2652..5c3e0ef1c34 100644 --- a/src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc +++ b/src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc @@ -330,6 +330,9 @@ class XdsResolver : public Resolver { std::string route_config_name_; RouteConfigWatcher* route_config_watcher_ = nullptr; XdsRouteConfigResource::VirtualHost current_virtual_host_; + std::map + cluster_specifier_plugin_map_; ClusterState::ClusterStateMap cluster_state_map_; }; @@ -416,13 +419,23 @@ XdsResolver::XdsConfigSelector::XdsConfigSelector( resolver_->current_listener_.http_connection_manager .http_max_stream_duration; } - if (route_action->weighted_clusters.empty()) { + if (route_action->action.index() == + XdsRouteConfigResource::Route::RouteAction::kClusterIndex) { *error = CreateMethodConfig(route_entry.route, nullptr, &route_entry.method_config); - MaybeAddCluster(route_action->cluster_name); - } else { + MaybeAddCluster(absl::StrCat( + "cluster:", + absl::get< + XdsRouteConfigResource::Route::RouteAction::kClusterIndex>( + route_action->action))); + } else if (route_action->action.index() == + XdsRouteConfigResource::Route::RouteAction:: + kWeightedClustersIndex) { + auto& action_weighted_clusters = absl::get< + XdsRouteConfigResource::Route::RouteAction::kWeightedClustersIndex>( + route_action->action); uint32_t end = 0; - for (const auto& weighted_cluster : route_action->weighted_clusters) { + for (const auto& weighted_cluster : action_weighted_clusters) { Route::ClusterWeightState cluster_weight_state; *error = CreateMethodConfig(route_entry.route, &weighted_cluster, &cluster_weight_state.method_config); @@ -432,8 +445,18 @@ XdsResolver::XdsConfigSelector::XdsConfigSelector( cluster_weight_state.cluster = weighted_cluster.name; route_entry.weighted_cluster_state.push_back( std::move(cluster_weight_state)); - MaybeAddCluster(weighted_cluster.name); + MaybeAddCluster(absl::StrCat("cluster:", weighted_cluster.name)); } + } else if (route_action->action.index() == + XdsRouteConfigResource::Route::RouteAction:: + kClusterSpecifierPluginIndex) { + // cluster_specifier_plugin case: + *error = CreateMethodConfig(route_entry.route, nullptr, + &route_entry.method_config); + MaybeAddCluster(absl::StrCat( + "cluster_specifier_plugin:", + absl::get(route_action->action))); } } } @@ -612,12 +635,18 @@ ConfigSelector::CallConfig XdsResolver::XdsConfigSelector::GetCallConfig( GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE); return call_config; } - absl::string_view cluster_name; + std::string cluster_name; RefCountedPtr method_config; - if (route_action->weighted_clusters.empty()) { - cluster_name = route_action->cluster_name; + if (route_action->action.index() == + XdsRouteConfigResource::Route::RouteAction::kClusterIndex) { + cluster_name = absl::StrCat( + "cluster:", + absl::get( + route_action->action)); method_config = entry.method_config; - } else { + } else if (route_action->action.index() == + XdsRouteConfigResource::Route::RouteAction:: + kWeightedClustersIndex) { const uint32_t key = rand() % entry.weighted_cluster_state[entry.weighted_cluster_state.size() - 1] @@ -640,8 +669,17 @@ ConfigSelector::CallConfig XdsResolver::XdsConfigSelector::GetCallConfig( } if (index == 0) index = start_index; GPR_ASSERT(entry.weighted_cluster_state[index].range_end > key); - cluster_name = entry.weighted_cluster_state[index].cluster; + cluster_name = + absl::StrCat("cluster:", entry.weighted_cluster_state[index].cluster); method_config = entry.weighted_cluster_state[index].method_config; + } else if (route_action->action.index() == + XdsRouteConfigResource::Route::RouteAction:: + kClusterSpecifierPluginIndex) { + cluster_name = absl::StrCat( + "cluster_specifier_plugin:", + absl::get(route_action->action)); + method_config = entry.method_config; } auto it = clusters_.find(cluster_name); GPR_ASSERT(it != clusters_.end()); @@ -863,6 +901,8 @@ void XdsResolver::OnRouteConfigUpdate(XdsRouteConfigResource rds_update) { } // Save the virtual host in the resolver. current_virtual_host_ = std::move(rds_update.virtual_hosts[*vhost_index]); + cluster_specifier_plugin_map_ = + std::move(rds_update.cluster_specifier_plugin_map); // Send a new result to the channel. GenerateResult(); } @@ -900,15 +940,26 @@ absl::StatusOr> XdsResolver::CreateServiceConfig() { std::vector clusters; for (const auto& cluster : cluster_state_map_) { - clusters.push_back( - absl::StrFormat(" \"%s\":{\n" - " \"childPolicy\":[ {\n" - " \"cds_experimental\":{\n" - " \"cluster\": \"%s\"\n" - " }\n" - " } ]\n" - " }", - cluster.first, cluster.first)); + absl::string_view child_name = cluster.first; + if (absl::ConsumePrefix(&child_name, "cluster_specifier_plugin:")) { + clusters.push_back(absl::StrFormat( + " \"%s\":{\n" + " \"childPolicy\": %s\n" + " }", + cluster.first, + cluster_specifier_plugin_map_[std::string(child_name)])); + } else { + absl::ConsumePrefix(&child_name, "cluster:"); + clusters.push_back( + absl::StrFormat(" \"%s\":{\n" + " \"childPolicy\":[ {\n" + " \"cds_experimental\":{\n" + " \"cluster\": \"%s\"\n" + " }\n" + " } ]\n" + " }", + cluster.first, child_name)); + } } std::vector config_parts; config_parts.push_back( diff --git a/src/core/ext/filters/client_channel/retry_filter.cc b/src/core/ext/filters/client_channel/retry_filter.cc index 3397de8bb4f..e3907910e38 100644 --- a/src/core/ext/filters/client_channel/retry_filter.cc +++ b/src/core/ext/filters/client_channel/retry_filter.cc @@ -2163,7 +2163,8 @@ RetryFilter::CallData::~CallData() { void RetryFilter::CallData::StartTransportStreamOpBatch( grpc_transport_stream_op_batch* batch) { - if (GRPC_TRACE_FLAG_ENABLED(grpc_retry_trace)) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_retry_trace) && + !GRPC_TRACE_FLAG_ENABLED(grpc_trace_channel)) { gpr_log(GPR_INFO, "chand=%p calld=%p: batch started from surface: %s", chand_, this, grpc_transport_stream_op_batch_string(batch).c_str()); } diff --git a/src/core/ext/transport/binder/client/endpoint_binder_pool.cc b/src/core/ext/transport/binder/client/endpoint_binder_pool.cc index d90946ab756..14263536540 100644 --- a/src/core/ext/transport/binder/client/endpoint_binder_pool.cc +++ b/src/core/ext/transport/binder/client/endpoint_binder_pool.cc @@ -53,7 +53,7 @@ Java_io_grpc_binder_cpp_GrpcBinderConnection_notifyConnected__Ljava_lang_String_ namespace grpc_binder { -void EndpointBinderPool ::GetEndpointBinder( +void EndpointBinderPool::GetEndpointBinder( std::string conn_id, std::function)> cb) { gpr_log(GPR_INFO, "EndpointBinder requested. conn_id = %s", conn_id.c_str()); diff --git a/src/core/ext/transport/binder/utils/ndk_binder.cc b/src/core/ext/transport/binder/utils/ndk_binder.cc index 5c0aedd7d53..f5aafc053dd 100644 --- a/src/core/ext/transport/binder/utils/ndk_binder.cc +++ b/src/core/ext/transport/binder/utils/ndk_binder.cc @@ -24,6 +24,9 @@ #include +#include "src/core/lib/gpr/tls.h" +#include "src/core/lib/gprpp/sync.h" + namespace { void* GetNdkBinderHandle() { // TODO(mingcl): Consider using RTLD_NOLOAD to check if it is already loaded @@ -37,6 +40,53 @@ void* GetNdkBinderHandle() { } return handle; } + +JavaVM* g_jvm = nullptr; +grpc_core::Mutex g_jvm_mu; + +// Whether the thread has already attached to JVM (this is to prevent +// repeated attachment in `AttachJvm()`) +GPR_THREAD_LOCAL(bool) g_is_jvm_attached = false; + +void SetJvm(JNIEnv* env) { + // OK to lock here since this function will only be called once for each + // connection. + grpc_core::MutexLock lock(&g_jvm_mu); + if (g_jvm != nullptr) { + return; + } + JavaVM* jvm = nullptr; + jint error = env->GetJavaVM(&jvm); + if (error != JNI_OK) { + gpr_log(GPR_ERROR, "Failed to get JVM"); + } + g_jvm = jvm; + gpr_log(GPR_INFO, "JVM cached"); +} + +// `SetJvm` need to be called in the process before `AttachJvm`. This is always +// the case because one of `AIBinder_fromJavaBinder`/`AIBinder_toJavaBinder` +// will be called before we actually uses the binder. Return `false` if not able +// to attach to JVM. Return `true` if JVM is attached (or already attached). +bool AttachJvm() { + if (g_is_jvm_attached) { + return true; + } + // Note: The following code would be run at most once per thread. + grpc_core::MutexLock lock(&g_jvm_mu); + if (g_jvm == nullptr) { + gpr_log(GPR_ERROR, "JVM not cached yet"); + return false; + } + JNIEnv* env_unused; + // Note that attach a thread that is already attached is a no-op, so it is + // fine to call this again if the thread has already been attached by other. + g_jvm->AttachCurrentThread(&env_unused, /* thr_args= */ nullptr); + gpr_log(GPR_INFO, "JVM attached successfully"); + g_is_jvm_attached = true; + return true; +} + } // namespace namespace grpc_binder { @@ -67,6 +117,7 @@ void* AIBinder_getUserData(AIBinder* binder) { uid_t AIBinder_getCallingUid() { FORWARD(AIBinder_getCallingUid)(); } AIBinder* AIBinder_fromJavaBinder(JNIEnv* env, jobject binder) { + SetJvm(env); FORWARD(AIBinder_fromJavaBinder)(env, binder); } @@ -97,6 +148,9 @@ void AIBinder_decStrong(AIBinder* binder) { binder_status_t AIBinder_transact(AIBinder* binder, transaction_code_t code, AParcel** in, AParcel** out, binder_flags_t flags) { + if (!AttachJvm()) { + gpr_log(GPR_ERROR, "failed to attach JVM. AIBinder_transact might fail."); + } FORWARD(AIBinder_transact)(binder, code, in, out, flags); } @@ -155,6 +209,7 @@ binder_status_t AIBinder_prepareTransaction(AIBinder* binder, AParcel** in) { } jobject AIBinder_toJavaBinder(JNIEnv* env, AIBinder* binder) { + SetJvm(env); FORWARD(AIBinder_toJavaBinder)(env, binder); } diff --git a/src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls_config.upb.c b/src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls_config.upb.c new file mode 100644 index 00000000000..aa69eaf7f41 --- /dev/null +++ b/src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls_config.upb.c @@ -0,0 +1,172 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * src/proto/grpc/lookup/v1/rls_config.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#include +#include "upb/msg_internal.h" +#include "src/proto/grpc/lookup/v1/rls_config.upb.h" +#include "google/protobuf/duration.upb.h" + +#include "upb/port_def.inc" + +static const upb_MiniTable_Field grpc_lookup_v1_NameMatcher__fields[3] = { + {1, UPB_SIZE(4, 8), 0, 0, 9, kUpb_FieldMode_Scalar | (upb_FieldRep_StringView << upb_FieldRep_Shift)}, + {2, UPB_SIZE(12, 24), 0, 0, 9, kUpb_FieldMode_Array | (upb_FieldRep_Pointer << upb_FieldRep_Shift)}, + {3, UPB_SIZE(0, 0), 0, 0, 8, kUpb_FieldMode_Scalar | (upb_FieldRep_1Byte << upb_FieldRep_Shift)}, +}; + +const upb_MiniTable grpc_lookup_v1_NameMatcher_msginit = { + NULL, + &grpc_lookup_v1_NameMatcher__fields[0], + UPB_SIZE(16, 32), 3, upb_ExtMode_NonExtendable, 3, 255, 0, +}; + +static const upb_MiniTable_Sub grpc_lookup_v1_GrpcKeyBuilder_submsgs[4] = { + {.submsg = &grpc_lookup_v1_GrpcKeyBuilder_ConstantKeysEntry_msginit}, + {.submsg = &grpc_lookup_v1_GrpcKeyBuilder_ExtraKeys_msginit}, + {.submsg = &grpc_lookup_v1_GrpcKeyBuilder_Name_msginit}, + {.submsg = &grpc_lookup_v1_NameMatcher_msginit}, +}; + +static const upb_MiniTable_Field grpc_lookup_v1_GrpcKeyBuilder__fields[4] = { + {1, UPB_SIZE(8, 16), 0, 2, 11, kUpb_FieldMode_Array | (upb_FieldRep_Pointer << upb_FieldRep_Shift)}, + {2, UPB_SIZE(12, 24), 0, 3, 11, kUpb_FieldMode_Array | (upb_FieldRep_Pointer << upb_FieldRep_Shift)}, + {3, UPB_SIZE(4, 8), 1, 1, 11, kUpb_FieldMode_Scalar | (upb_FieldRep_Pointer << upb_FieldRep_Shift)}, + {4, UPB_SIZE(16, 32), 0, 0, 11, kUpb_FieldMode_Map | (upb_FieldRep_Pointer << upb_FieldRep_Shift)}, +}; + +const upb_MiniTable grpc_lookup_v1_GrpcKeyBuilder_msginit = { + &grpc_lookup_v1_GrpcKeyBuilder_submsgs[0], + &grpc_lookup_v1_GrpcKeyBuilder__fields[0], + UPB_SIZE(24, 40), 4, upb_ExtMode_NonExtendable, 4, 255, 0, +}; + +static const upb_MiniTable_Field grpc_lookup_v1_GrpcKeyBuilder_Name__fields[2] = { + {1, UPB_SIZE(0, 0), 0, 0, 9, kUpb_FieldMode_Scalar | (upb_FieldRep_StringView << upb_FieldRep_Shift)}, + {2, UPB_SIZE(8, 16), 0, 0, 9, kUpb_FieldMode_Scalar | (upb_FieldRep_StringView << upb_FieldRep_Shift)}, +}; + +const upb_MiniTable grpc_lookup_v1_GrpcKeyBuilder_Name_msginit = { + NULL, + &grpc_lookup_v1_GrpcKeyBuilder_Name__fields[0], + UPB_SIZE(16, 32), 2, upb_ExtMode_NonExtendable, 2, 255, 0, +}; + +static const upb_MiniTable_Field grpc_lookup_v1_GrpcKeyBuilder_ExtraKeys__fields[3] = { + {1, UPB_SIZE(0, 0), 0, 0, 9, kUpb_FieldMode_Scalar | (upb_FieldRep_StringView << upb_FieldRep_Shift)}, + {2, UPB_SIZE(8, 16), 0, 0, 9, kUpb_FieldMode_Scalar | (upb_FieldRep_StringView << upb_FieldRep_Shift)}, + {3, UPB_SIZE(16, 32), 0, 0, 9, kUpb_FieldMode_Scalar | (upb_FieldRep_StringView << upb_FieldRep_Shift)}, +}; + +const upb_MiniTable grpc_lookup_v1_GrpcKeyBuilder_ExtraKeys_msginit = { + NULL, + &grpc_lookup_v1_GrpcKeyBuilder_ExtraKeys__fields[0], + UPB_SIZE(24, 48), 3, upb_ExtMode_NonExtendable, 3, 255, 0, +}; + +static const upb_MiniTable_Field grpc_lookup_v1_GrpcKeyBuilder_ConstantKeysEntry__fields[2] = { + {1, UPB_SIZE(0, 0), 0, 0, 9, kUpb_FieldMode_Scalar | (upb_FieldRep_StringView << upb_FieldRep_Shift)}, + {2, UPB_SIZE(8, 16), 0, 0, 9, kUpb_FieldMode_Scalar | (upb_FieldRep_StringView << upb_FieldRep_Shift)}, +}; + +const upb_MiniTable grpc_lookup_v1_GrpcKeyBuilder_ConstantKeysEntry_msginit = { + NULL, + &grpc_lookup_v1_GrpcKeyBuilder_ConstantKeysEntry__fields[0], + UPB_SIZE(16, 32), 2, upb_ExtMode_NonExtendable, 2, 255, 0, +}; + +static const upb_MiniTable_Sub grpc_lookup_v1_HttpKeyBuilder_submsgs[2] = { + {.submsg = &grpc_lookup_v1_HttpKeyBuilder_ConstantKeysEntry_msginit}, + {.submsg = &grpc_lookup_v1_NameMatcher_msginit}, +}; + +static const upb_MiniTable_Field grpc_lookup_v1_HttpKeyBuilder__fields[5] = { + {1, UPB_SIZE(0, 0), 0, 0, 9, kUpb_FieldMode_Array | (upb_FieldRep_Pointer << upb_FieldRep_Shift)}, + {2, UPB_SIZE(4, 8), 0, 0, 9, kUpb_FieldMode_Array | (upb_FieldRep_Pointer << upb_FieldRep_Shift)}, + {3, UPB_SIZE(8, 16), 0, 1, 11, kUpb_FieldMode_Array | (upb_FieldRep_Pointer << upb_FieldRep_Shift)}, + {4, UPB_SIZE(12, 24), 0, 1, 11, kUpb_FieldMode_Array | (upb_FieldRep_Pointer << upb_FieldRep_Shift)}, + {5, UPB_SIZE(16, 32), 0, 0, 11, kUpb_FieldMode_Map | (upb_FieldRep_Pointer << upb_FieldRep_Shift)}, +}; + +const upb_MiniTable grpc_lookup_v1_HttpKeyBuilder_msginit = { + &grpc_lookup_v1_HttpKeyBuilder_submsgs[0], + &grpc_lookup_v1_HttpKeyBuilder__fields[0], + UPB_SIZE(24, 40), 5, upb_ExtMode_NonExtendable, 5, 255, 0, +}; + +static const upb_MiniTable_Field grpc_lookup_v1_HttpKeyBuilder_ConstantKeysEntry__fields[2] = { + {1, UPB_SIZE(0, 0), 0, 0, 9, kUpb_FieldMode_Scalar | (upb_FieldRep_StringView << upb_FieldRep_Shift)}, + {2, UPB_SIZE(8, 16), 0, 0, 9, kUpb_FieldMode_Scalar | (upb_FieldRep_StringView << upb_FieldRep_Shift)}, +}; + +const upb_MiniTable grpc_lookup_v1_HttpKeyBuilder_ConstantKeysEntry_msginit = { + NULL, + &grpc_lookup_v1_HttpKeyBuilder_ConstantKeysEntry__fields[0], + UPB_SIZE(16, 32), 2, upb_ExtMode_NonExtendable, 2, 255, 0, +}; + +static const upb_MiniTable_Sub grpc_lookup_v1_RouteLookupConfig_submsgs[3] = { + {.submsg = &google_protobuf_Duration_msginit}, + {.submsg = &grpc_lookup_v1_GrpcKeyBuilder_msginit}, + {.submsg = &grpc_lookup_v1_HttpKeyBuilder_msginit}, +}; + +static const upb_MiniTable_Field grpc_lookup_v1_RouteLookupConfig__fields[9] = { + {1, UPB_SIZE(44, 72), 0, 2, 11, kUpb_FieldMode_Array | (upb_FieldRep_Pointer << upb_FieldRep_Shift)}, + {2, UPB_SIZE(48, 80), 0, 1, 11, kUpb_FieldMode_Array | (upb_FieldRep_Pointer << upb_FieldRep_Shift)}, + {3, UPB_SIZE(16, 16), 0, 0, 9, kUpb_FieldMode_Scalar | (upb_FieldRep_StringView << upb_FieldRep_Shift)}, + {4, UPB_SIZE(32, 48), 1, 0, 11, kUpb_FieldMode_Scalar | (upb_FieldRep_Pointer << upb_FieldRep_Shift)}, + {5, UPB_SIZE(36, 56), 2, 0, 11, kUpb_FieldMode_Scalar | (upb_FieldRep_Pointer << upb_FieldRep_Shift)}, + {6, UPB_SIZE(40, 64), 3, 0, 11, kUpb_FieldMode_Scalar | (upb_FieldRep_Pointer << upb_FieldRep_Shift)}, + {7, UPB_SIZE(8, 8), 0, 0, 3, kUpb_FieldMode_Scalar | (upb_FieldRep_8Byte << upb_FieldRep_Shift)}, + {8, UPB_SIZE(52, 88), 0, 0, 9, kUpb_FieldMode_Array | (upb_FieldRep_Pointer << upb_FieldRep_Shift)}, + {9, UPB_SIZE(24, 32), 0, 0, 9, kUpb_FieldMode_Scalar | (upb_FieldRep_StringView << upb_FieldRep_Shift)}, +}; + +const upb_MiniTable grpc_lookup_v1_RouteLookupConfig_msginit = { + &grpc_lookup_v1_RouteLookupConfig_submsgs[0], + &grpc_lookup_v1_RouteLookupConfig__fields[0], + UPB_SIZE(56, 96), 9, upb_ExtMode_NonExtendable, 9, 255, 0, +}; + +static const upb_MiniTable_Sub grpc_lookup_v1_RouteLookupClusterSpecifier_submsgs[1] = { + {.submsg = &grpc_lookup_v1_RouteLookupConfig_msginit}, +}; + +static const upb_MiniTable_Field grpc_lookup_v1_RouteLookupClusterSpecifier__fields[1] = { + {1, UPB_SIZE(4, 8), 1, 0, 11, kUpb_FieldMode_Scalar | (upb_FieldRep_Pointer << upb_FieldRep_Shift)}, +}; + +const upb_MiniTable grpc_lookup_v1_RouteLookupClusterSpecifier_msginit = { + &grpc_lookup_v1_RouteLookupClusterSpecifier_submsgs[0], + &grpc_lookup_v1_RouteLookupClusterSpecifier__fields[0], + UPB_SIZE(8, 16), 1, upb_ExtMode_NonExtendable, 1, 255, 0, +}; + +static const upb_MiniTable *messages_layout[9] = { + &grpc_lookup_v1_NameMatcher_msginit, + &grpc_lookup_v1_GrpcKeyBuilder_msginit, + &grpc_lookup_v1_GrpcKeyBuilder_Name_msginit, + &grpc_lookup_v1_GrpcKeyBuilder_ExtraKeys_msginit, + &grpc_lookup_v1_GrpcKeyBuilder_ConstantKeysEntry_msginit, + &grpc_lookup_v1_HttpKeyBuilder_msginit, + &grpc_lookup_v1_HttpKeyBuilder_ConstantKeysEntry_msginit, + &grpc_lookup_v1_RouteLookupConfig_msginit, + &grpc_lookup_v1_RouteLookupClusterSpecifier_msginit, +}; + +const upb_MiniTable_File src_proto_grpc_lookup_v1_rls_config_proto_upb_file_layout = { + messages_layout, + NULL, + NULL, + 9, + 0, + 0, +}; + +#include "upb/port_undef.inc" + diff --git a/src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls_config.upb.h b/src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls_config.upb.h new file mode 100644 index 00000000000..fefd848cd8f --- /dev/null +++ b/src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls_config.upb.h @@ -0,0 +1,623 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * src/proto/grpc/lookup/v1/rls_config.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#ifndef SRC_PROTO_GRPC_LOOKUP_V1_RLS_CONFIG_PROTO_UPB_H_ +#define SRC_PROTO_GRPC_LOOKUP_V1_RLS_CONFIG_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 grpc_lookup_v1_NameMatcher; +struct grpc_lookup_v1_GrpcKeyBuilder; +struct grpc_lookup_v1_GrpcKeyBuilder_Name; +struct grpc_lookup_v1_GrpcKeyBuilder_ExtraKeys; +struct grpc_lookup_v1_GrpcKeyBuilder_ConstantKeysEntry; +struct grpc_lookup_v1_HttpKeyBuilder; +struct grpc_lookup_v1_HttpKeyBuilder_ConstantKeysEntry; +struct grpc_lookup_v1_RouteLookupConfig; +struct grpc_lookup_v1_RouteLookupClusterSpecifier; +typedef struct grpc_lookup_v1_NameMatcher grpc_lookup_v1_NameMatcher; +typedef struct grpc_lookup_v1_GrpcKeyBuilder grpc_lookup_v1_GrpcKeyBuilder; +typedef struct grpc_lookup_v1_GrpcKeyBuilder_Name grpc_lookup_v1_GrpcKeyBuilder_Name; +typedef struct grpc_lookup_v1_GrpcKeyBuilder_ExtraKeys grpc_lookup_v1_GrpcKeyBuilder_ExtraKeys; +typedef struct grpc_lookup_v1_GrpcKeyBuilder_ConstantKeysEntry grpc_lookup_v1_GrpcKeyBuilder_ConstantKeysEntry; +typedef struct grpc_lookup_v1_HttpKeyBuilder grpc_lookup_v1_HttpKeyBuilder; +typedef struct grpc_lookup_v1_HttpKeyBuilder_ConstantKeysEntry grpc_lookup_v1_HttpKeyBuilder_ConstantKeysEntry; +typedef struct grpc_lookup_v1_RouteLookupConfig grpc_lookup_v1_RouteLookupConfig; +typedef struct grpc_lookup_v1_RouteLookupClusterSpecifier grpc_lookup_v1_RouteLookupClusterSpecifier; +extern const upb_MiniTable grpc_lookup_v1_NameMatcher_msginit; +extern const upb_MiniTable grpc_lookup_v1_GrpcKeyBuilder_msginit; +extern const upb_MiniTable grpc_lookup_v1_GrpcKeyBuilder_Name_msginit; +extern const upb_MiniTable grpc_lookup_v1_GrpcKeyBuilder_ExtraKeys_msginit; +extern const upb_MiniTable grpc_lookup_v1_GrpcKeyBuilder_ConstantKeysEntry_msginit; +extern const upb_MiniTable grpc_lookup_v1_HttpKeyBuilder_msginit; +extern const upb_MiniTable grpc_lookup_v1_HttpKeyBuilder_ConstantKeysEntry_msginit; +extern const upb_MiniTable grpc_lookup_v1_RouteLookupConfig_msginit; +extern const upb_MiniTable grpc_lookup_v1_RouteLookupClusterSpecifier_msginit; +struct google_protobuf_Duration; +extern const upb_MiniTable google_protobuf_Duration_msginit; + + + +/* grpc.lookup.v1.NameMatcher */ + +UPB_INLINE grpc_lookup_v1_NameMatcher* grpc_lookup_v1_NameMatcher_new(upb_Arena* arena) { + return (grpc_lookup_v1_NameMatcher*)_upb_Message_New(&grpc_lookup_v1_NameMatcher_msginit, arena); +} +UPB_INLINE grpc_lookup_v1_NameMatcher* grpc_lookup_v1_NameMatcher_parse(const char* buf, size_t size, upb_Arena* arena) { + grpc_lookup_v1_NameMatcher* ret = grpc_lookup_v1_NameMatcher_new(arena); + if (!ret) return NULL; + if (upb_Decode(buf, size, ret, &grpc_lookup_v1_NameMatcher_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) { + return NULL; + } + return ret; +} +UPB_INLINE grpc_lookup_v1_NameMatcher* grpc_lookup_v1_NameMatcher_parse_ex(const char* buf, size_t size, + const upb_ExtensionRegistry* extreg, + int options, upb_Arena* arena) { + grpc_lookup_v1_NameMatcher* ret = grpc_lookup_v1_NameMatcher_new(arena); + if (!ret) return NULL; + if (upb_Decode(buf, size, ret, &grpc_lookup_v1_NameMatcher_msginit, extreg, options, arena) != + kUpb_DecodeStatus_Ok) { + return NULL; + } + return ret; +} +UPB_INLINE char* grpc_lookup_v1_NameMatcher_serialize(const grpc_lookup_v1_NameMatcher* msg, upb_Arena* arena, size_t* len) { + return upb_Encode(msg, &grpc_lookup_v1_NameMatcher_msginit, 0, arena, len); +} +UPB_INLINE char* grpc_lookup_v1_NameMatcher_serialize_ex(const grpc_lookup_v1_NameMatcher* msg, int options, + upb_Arena* arena, size_t* len) { + return upb_Encode(msg, &grpc_lookup_v1_NameMatcher_msginit, options, arena, len); +} +UPB_INLINE upb_StringView grpc_lookup_v1_NameMatcher_key(const grpc_lookup_v1_NameMatcher* msg) { + return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_StringView); +} +UPB_INLINE upb_StringView const* grpc_lookup_v1_NameMatcher_names(const grpc_lookup_v1_NameMatcher *msg, size_t *len) { return (upb_StringView const*)_upb_array_accessor(msg, UPB_SIZE(12, 24), len); } +UPB_INLINE bool grpc_lookup_v1_NameMatcher_required_match(const grpc_lookup_v1_NameMatcher* msg) { + return *UPB_PTR_AT(msg, UPB_SIZE(0, 0), bool); +} + +UPB_INLINE void grpc_lookup_v1_NameMatcher_set_key(grpc_lookup_v1_NameMatcher *msg, upb_StringView value) { + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_StringView) = value; +} +UPB_INLINE upb_StringView* grpc_lookup_v1_NameMatcher_mutable_names(grpc_lookup_v1_NameMatcher *msg, size_t *len) { + return (upb_StringView*)_upb_array_mutable_accessor(msg, UPB_SIZE(12, 24), len); +} +UPB_INLINE upb_StringView* grpc_lookup_v1_NameMatcher_resize_names(grpc_lookup_v1_NameMatcher *msg, size_t len, upb_Arena *arena) { + return (upb_StringView*)_upb_Array_Resize_accessor2(msg, UPB_SIZE(12, 24), len, UPB_SIZE(3, 4), arena); +} +UPB_INLINE bool grpc_lookup_v1_NameMatcher_add_names(grpc_lookup_v1_NameMatcher *msg, upb_StringView val, upb_Arena *arena) { + return _upb_Array_Append_accessor2(msg, UPB_SIZE(12, 24), UPB_SIZE(3, 4), &val, + arena); +} +UPB_INLINE void grpc_lookup_v1_NameMatcher_set_required_match(grpc_lookup_v1_NameMatcher *msg, bool value) { + *UPB_PTR_AT(msg, UPB_SIZE(0, 0), bool) = value; +} + +/* grpc.lookup.v1.GrpcKeyBuilder */ + +UPB_INLINE grpc_lookup_v1_GrpcKeyBuilder* grpc_lookup_v1_GrpcKeyBuilder_new(upb_Arena* arena) { + return (grpc_lookup_v1_GrpcKeyBuilder*)_upb_Message_New(&grpc_lookup_v1_GrpcKeyBuilder_msginit, arena); +} +UPB_INLINE grpc_lookup_v1_GrpcKeyBuilder* grpc_lookup_v1_GrpcKeyBuilder_parse(const char* buf, size_t size, upb_Arena* arena) { + grpc_lookup_v1_GrpcKeyBuilder* ret = grpc_lookup_v1_GrpcKeyBuilder_new(arena); + if (!ret) return NULL; + if (upb_Decode(buf, size, ret, &grpc_lookup_v1_GrpcKeyBuilder_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) { + return NULL; + } + return ret; +} +UPB_INLINE grpc_lookup_v1_GrpcKeyBuilder* grpc_lookup_v1_GrpcKeyBuilder_parse_ex(const char* buf, size_t size, + const upb_ExtensionRegistry* extreg, + int options, upb_Arena* arena) { + grpc_lookup_v1_GrpcKeyBuilder* ret = grpc_lookup_v1_GrpcKeyBuilder_new(arena); + if (!ret) return NULL; + if (upb_Decode(buf, size, ret, &grpc_lookup_v1_GrpcKeyBuilder_msginit, extreg, options, arena) != + kUpb_DecodeStatus_Ok) { + return NULL; + } + return ret; +} +UPB_INLINE char* grpc_lookup_v1_GrpcKeyBuilder_serialize(const grpc_lookup_v1_GrpcKeyBuilder* msg, upb_Arena* arena, size_t* len) { + return upb_Encode(msg, &grpc_lookup_v1_GrpcKeyBuilder_msginit, 0, arena, len); +} +UPB_INLINE char* grpc_lookup_v1_GrpcKeyBuilder_serialize_ex(const grpc_lookup_v1_GrpcKeyBuilder* msg, int options, + upb_Arena* arena, size_t* len) { + return upb_Encode(msg, &grpc_lookup_v1_GrpcKeyBuilder_msginit, options, arena, len); +} +UPB_INLINE bool grpc_lookup_v1_GrpcKeyBuilder_has_names(const grpc_lookup_v1_GrpcKeyBuilder *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(8, 16)); } +UPB_INLINE const grpc_lookup_v1_GrpcKeyBuilder_Name* const* grpc_lookup_v1_GrpcKeyBuilder_names(const grpc_lookup_v1_GrpcKeyBuilder *msg, size_t *len) { return (const grpc_lookup_v1_GrpcKeyBuilder_Name* const*)_upb_array_accessor(msg, UPB_SIZE(8, 16), len); } +UPB_INLINE bool grpc_lookup_v1_GrpcKeyBuilder_has_headers(const grpc_lookup_v1_GrpcKeyBuilder *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(12, 24)); } +UPB_INLINE const grpc_lookup_v1_NameMatcher* const* grpc_lookup_v1_GrpcKeyBuilder_headers(const grpc_lookup_v1_GrpcKeyBuilder *msg, size_t *len) { return (const grpc_lookup_v1_NameMatcher* const*)_upb_array_accessor(msg, UPB_SIZE(12, 24), len); } +UPB_INLINE bool grpc_lookup_v1_GrpcKeyBuilder_has_extra_keys(const grpc_lookup_v1_GrpcKeyBuilder *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE const grpc_lookup_v1_GrpcKeyBuilder_ExtraKeys* grpc_lookup_v1_GrpcKeyBuilder_extra_keys(const grpc_lookup_v1_GrpcKeyBuilder* msg) { + return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), const grpc_lookup_v1_GrpcKeyBuilder_ExtraKeys*); +} +UPB_INLINE bool grpc_lookup_v1_GrpcKeyBuilder_has_constant_keys(const grpc_lookup_v1_GrpcKeyBuilder *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(16, 32)); } +UPB_INLINE size_t grpc_lookup_v1_GrpcKeyBuilder_constant_keys_size(const grpc_lookup_v1_GrpcKeyBuilder *msg) {return _upb_msg_map_size(msg, UPB_SIZE(16, 32)); } +UPB_INLINE bool grpc_lookup_v1_GrpcKeyBuilder_constant_keys_get(const grpc_lookup_v1_GrpcKeyBuilder *msg, upb_StringView key, upb_StringView *val) { return _upb_msg_map_get(msg, UPB_SIZE(16, 32), &key, 0, val, 0); } +UPB_INLINE const grpc_lookup_v1_GrpcKeyBuilder_ConstantKeysEntry* grpc_lookup_v1_GrpcKeyBuilder_constant_keys_next(const grpc_lookup_v1_GrpcKeyBuilder *msg, size_t* iter) { return (const grpc_lookup_v1_GrpcKeyBuilder_ConstantKeysEntry*)_upb_msg_map_next(msg, UPB_SIZE(16, 32), iter); } + +UPB_INLINE grpc_lookup_v1_GrpcKeyBuilder_Name** grpc_lookup_v1_GrpcKeyBuilder_mutable_names(grpc_lookup_v1_GrpcKeyBuilder *msg, size_t *len) { + return (grpc_lookup_v1_GrpcKeyBuilder_Name**)_upb_array_mutable_accessor(msg, UPB_SIZE(8, 16), len); +} +UPB_INLINE grpc_lookup_v1_GrpcKeyBuilder_Name** grpc_lookup_v1_GrpcKeyBuilder_resize_names(grpc_lookup_v1_GrpcKeyBuilder *msg, size_t len, upb_Arena *arena) { + return (grpc_lookup_v1_GrpcKeyBuilder_Name**)_upb_Array_Resize_accessor2(msg, UPB_SIZE(8, 16), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct grpc_lookup_v1_GrpcKeyBuilder_Name* grpc_lookup_v1_GrpcKeyBuilder_add_names(grpc_lookup_v1_GrpcKeyBuilder *msg, upb_Arena *arena) { + struct grpc_lookup_v1_GrpcKeyBuilder_Name* sub = (struct grpc_lookup_v1_GrpcKeyBuilder_Name*)_upb_Message_New(&grpc_lookup_v1_GrpcKeyBuilder_Name_msginit, arena); + bool ok = _upb_Array_Append_accessor2( + msg, UPB_SIZE(8, 16), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} +UPB_INLINE grpc_lookup_v1_NameMatcher** grpc_lookup_v1_GrpcKeyBuilder_mutable_headers(grpc_lookup_v1_GrpcKeyBuilder *msg, size_t *len) { + return (grpc_lookup_v1_NameMatcher**)_upb_array_mutable_accessor(msg, UPB_SIZE(12, 24), len); +} +UPB_INLINE grpc_lookup_v1_NameMatcher** grpc_lookup_v1_GrpcKeyBuilder_resize_headers(grpc_lookup_v1_GrpcKeyBuilder *msg, size_t len, upb_Arena *arena) { + return (grpc_lookup_v1_NameMatcher**)_upb_Array_Resize_accessor2(msg, UPB_SIZE(12, 24), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct grpc_lookup_v1_NameMatcher* grpc_lookup_v1_GrpcKeyBuilder_add_headers(grpc_lookup_v1_GrpcKeyBuilder *msg, upb_Arena *arena) { + struct grpc_lookup_v1_NameMatcher* sub = (struct grpc_lookup_v1_NameMatcher*)_upb_Message_New(&grpc_lookup_v1_NameMatcher_msginit, arena); + bool ok = _upb_Array_Append_accessor2( + msg, UPB_SIZE(12, 24), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} +UPB_INLINE void grpc_lookup_v1_GrpcKeyBuilder_set_extra_keys(grpc_lookup_v1_GrpcKeyBuilder *msg, grpc_lookup_v1_GrpcKeyBuilder_ExtraKeys* value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), grpc_lookup_v1_GrpcKeyBuilder_ExtraKeys*) = value; +} +UPB_INLINE struct grpc_lookup_v1_GrpcKeyBuilder_ExtraKeys* grpc_lookup_v1_GrpcKeyBuilder_mutable_extra_keys(grpc_lookup_v1_GrpcKeyBuilder *msg, upb_Arena *arena) { + struct grpc_lookup_v1_GrpcKeyBuilder_ExtraKeys* sub = (struct grpc_lookup_v1_GrpcKeyBuilder_ExtraKeys*)grpc_lookup_v1_GrpcKeyBuilder_extra_keys(msg); + if (sub == NULL) { + sub = (struct grpc_lookup_v1_GrpcKeyBuilder_ExtraKeys*)_upb_Message_New(&grpc_lookup_v1_GrpcKeyBuilder_ExtraKeys_msginit, arena); + if (!sub) return NULL; + grpc_lookup_v1_GrpcKeyBuilder_set_extra_keys(msg, sub); + } + return sub; +} +UPB_INLINE void grpc_lookup_v1_GrpcKeyBuilder_constant_keys_clear(grpc_lookup_v1_GrpcKeyBuilder *msg) { _upb_msg_map_clear(msg, UPB_SIZE(16, 32)); } +UPB_INLINE bool grpc_lookup_v1_GrpcKeyBuilder_constant_keys_set(grpc_lookup_v1_GrpcKeyBuilder *msg, upb_StringView key, upb_StringView val, upb_Arena *a) { return _upb_msg_map_set(msg, UPB_SIZE(16, 32), &key, 0, &val, 0, a); } +UPB_INLINE bool grpc_lookup_v1_GrpcKeyBuilder_constant_keys_delete(grpc_lookup_v1_GrpcKeyBuilder *msg, upb_StringView key) { return _upb_msg_map_delete(msg, UPB_SIZE(16, 32), &key, 0); } +UPB_INLINE grpc_lookup_v1_GrpcKeyBuilder_ConstantKeysEntry* grpc_lookup_v1_GrpcKeyBuilder_constant_keys_nextmutable(grpc_lookup_v1_GrpcKeyBuilder *msg, size_t* iter) { return (grpc_lookup_v1_GrpcKeyBuilder_ConstantKeysEntry*)_upb_msg_map_next(msg, UPB_SIZE(16, 32), iter); } + +/* grpc.lookup.v1.GrpcKeyBuilder.Name */ + +UPB_INLINE grpc_lookup_v1_GrpcKeyBuilder_Name* grpc_lookup_v1_GrpcKeyBuilder_Name_new(upb_Arena* arena) { + return (grpc_lookup_v1_GrpcKeyBuilder_Name*)_upb_Message_New(&grpc_lookup_v1_GrpcKeyBuilder_Name_msginit, arena); +} +UPB_INLINE grpc_lookup_v1_GrpcKeyBuilder_Name* grpc_lookup_v1_GrpcKeyBuilder_Name_parse(const char* buf, size_t size, upb_Arena* arena) { + grpc_lookup_v1_GrpcKeyBuilder_Name* ret = grpc_lookup_v1_GrpcKeyBuilder_Name_new(arena); + if (!ret) return NULL; + if (upb_Decode(buf, size, ret, &grpc_lookup_v1_GrpcKeyBuilder_Name_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) { + return NULL; + } + return ret; +} +UPB_INLINE grpc_lookup_v1_GrpcKeyBuilder_Name* grpc_lookup_v1_GrpcKeyBuilder_Name_parse_ex(const char* buf, size_t size, + const upb_ExtensionRegistry* extreg, + int options, upb_Arena* arena) { + grpc_lookup_v1_GrpcKeyBuilder_Name* ret = grpc_lookup_v1_GrpcKeyBuilder_Name_new(arena); + if (!ret) return NULL; + if (upb_Decode(buf, size, ret, &grpc_lookup_v1_GrpcKeyBuilder_Name_msginit, extreg, options, arena) != + kUpb_DecodeStatus_Ok) { + return NULL; + } + return ret; +} +UPB_INLINE char* grpc_lookup_v1_GrpcKeyBuilder_Name_serialize(const grpc_lookup_v1_GrpcKeyBuilder_Name* msg, upb_Arena* arena, size_t* len) { + return upb_Encode(msg, &grpc_lookup_v1_GrpcKeyBuilder_Name_msginit, 0, arena, len); +} +UPB_INLINE char* grpc_lookup_v1_GrpcKeyBuilder_Name_serialize_ex(const grpc_lookup_v1_GrpcKeyBuilder_Name* msg, int options, + upb_Arena* arena, size_t* len) { + return upb_Encode(msg, &grpc_lookup_v1_GrpcKeyBuilder_Name_msginit, options, arena, len); +} +UPB_INLINE upb_StringView grpc_lookup_v1_GrpcKeyBuilder_Name_service(const grpc_lookup_v1_GrpcKeyBuilder_Name* msg) { + return *UPB_PTR_AT(msg, UPB_SIZE(0, 0), upb_StringView); +} +UPB_INLINE upb_StringView grpc_lookup_v1_GrpcKeyBuilder_Name_method(const grpc_lookup_v1_GrpcKeyBuilder_Name* msg) { + return *UPB_PTR_AT(msg, UPB_SIZE(8, 16), upb_StringView); +} + +UPB_INLINE void grpc_lookup_v1_GrpcKeyBuilder_Name_set_service(grpc_lookup_v1_GrpcKeyBuilder_Name *msg, upb_StringView value) { + *UPB_PTR_AT(msg, UPB_SIZE(0, 0), upb_StringView) = value; +} +UPB_INLINE void grpc_lookup_v1_GrpcKeyBuilder_Name_set_method(grpc_lookup_v1_GrpcKeyBuilder_Name *msg, upb_StringView value) { + *UPB_PTR_AT(msg, UPB_SIZE(8, 16), upb_StringView) = value; +} + +/* grpc.lookup.v1.GrpcKeyBuilder.ExtraKeys */ + +UPB_INLINE grpc_lookup_v1_GrpcKeyBuilder_ExtraKeys* grpc_lookup_v1_GrpcKeyBuilder_ExtraKeys_new(upb_Arena* arena) { + return (grpc_lookup_v1_GrpcKeyBuilder_ExtraKeys*)_upb_Message_New(&grpc_lookup_v1_GrpcKeyBuilder_ExtraKeys_msginit, arena); +} +UPB_INLINE grpc_lookup_v1_GrpcKeyBuilder_ExtraKeys* grpc_lookup_v1_GrpcKeyBuilder_ExtraKeys_parse(const char* buf, size_t size, upb_Arena* arena) { + grpc_lookup_v1_GrpcKeyBuilder_ExtraKeys* ret = grpc_lookup_v1_GrpcKeyBuilder_ExtraKeys_new(arena); + if (!ret) return NULL; + if (upb_Decode(buf, size, ret, &grpc_lookup_v1_GrpcKeyBuilder_ExtraKeys_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) { + return NULL; + } + return ret; +} +UPB_INLINE grpc_lookup_v1_GrpcKeyBuilder_ExtraKeys* grpc_lookup_v1_GrpcKeyBuilder_ExtraKeys_parse_ex(const char* buf, size_t size, + const upb_ExtensionRegistry* extreg, + int options, upb_Arena* arena) { + grpc_lookup_v1_GrpcKeyBuilder_ExtraKeys* ret = grpc_lookup_v1_GrpcKeyBuilder_ExtraKeys_new(arena); + if (!ret) return NULL; + if (upb_Decode(buf, size, ret, &grpc_lookup_v1_GrpcKeyBuilder_ExtraKeys_msginit, extreg, options, arena) != + kUpb_DecodeStatus_Ok) { + return NULL; + } + return ret; +} +UPB_INLINE char* grpc_lookup_v1_GrpcKeyBuilder_ExtraKeys_serialize(const grpc_lookup_v1_GrpcKeyBuilder_ExtraKeys* msg, upb_Arena* arena, size_t* len) { + return upb_Encode(msg, &grpc_lookup_v1_GrpcKeyBuilder_ExtraKeys_msginit, 0, arena, len); +} +UPB_INLINE char* grpc_lookup_v1_GrpcKeyBuilder_ExtraKeys_serialize_ex(const grpc_lookup_v1_GrpcKeyBuilder_ExtraKeys* msg, int options, + upb_Arena* arena, size_t* len) { + return upb_Encode(msg, &grpc_lookup_v1_GrpcKeyBuilder_ExtraKeys_msginit, options, arena, len); +} +UPB_INLINE upb_StringView grpc_lookup_v1_GrpcKeyBuilder_ExtraKeys_host(const grpc_lookup_v1_GrpcKeyBuilder_ExtraKeys* msg) { + return *UPB_PTR_AT(msg, UPB_SIZE(0, 0), upb_StringView); +} +UPB_INLINE upb_StringView grpc_lookup_v1_GrpcKeyBuilder_ExtraKeys_service(const grpc_lookup_v1_GrpcKeyBuilder_ExtraKeys* msg) { + return *UPB_PTR_AT(msg, UPB_SIZE(8, 16), upb_StringView); +} +UPB_INLINE upb_StringView grpc_lookup_v1_GrpcKeyBuilder_ExtraKeys_method(const grpc_lookup_v1_GrpcKeyBuilder_ExtraKeys* msg) { + return *UPB_PTR_AT(msg, UPB_SIZE(16, 32), upb_StringView); +} + +UPB_INLINE void grpc_lookup_v1_GrpcKeyBuilder_ExtraKeys_set_host(grpc_lookup_v1_GrpcKeyBuilder_ExtraKeys *msg, upb_StringView value) { + *UPB_PTR_AT(msg, UPB_SIZE(0, 0), upb_StringView) = value; +} +UPB_INLINE void grpc_lookup_v1_GrpcKeyBuilder_ExtraKeys_set_service(grpc_lookup_v1_GrpcKeyBuilder_ExtraKeys *msg, upb_StringView value) { + *UPB_PTR_AT(msg, UPB_SIZE(8, 16), upb_StringView) = value; +} +UPB_INLINE void grpc_lookup_v1_GrpcKeyBuilder_ExtraKeys_set_method(grpc_lookup_v1_GrpcKeyBuilder_ExtraKeys *msg, upb_StringView value) { + *UPB_PTR_AT(msg, UPB_SIZE(16, 32), upb_StringView) = value; +} + +/* grpc.lookup.v1.GrpcKeyBuilder.ConstantKeysEntry */ + +UPB_INLINE upb_StringView grpc_lookup_v1_GrpcKeyBuilder_ConstantKeysEntry_key(const grpc_lookup_v1_GrpcKeyBuilder_ConstantKeysEntry *msg) { + upb_StringView ret; + _upb_msg_map_key(msg, &ret, 0); + return ret; +} +UPB_INLINE upb_StringView grpc_lookup_v1_GrpcKeyBuilder_ConstantKeysEntry_value(const grpc_lookup_v1_GrpcKeyBuilder_ConstantKeysEntry *msg) { + upb_StringView ret; + _upb_msg_map_value(msg, &ret, 0); + return ret; +} + +UPB_INLINE void grpc_lookup_v1_GrpcKeyBuilder_ConstantKeysEntry_set_value(grpc_lookup_v1_GrpcKeyBuilder_ConstantKeysEntry *msg, upb_StringView value) { + _upb_msg_map_set_value(msg, &value, 0); +} + +/* grpc.lookup.v1.HttpKeyBuilder */ + +UPB_INLINE grpc_lookup_v1_HttpKeyBuilder* grpc_lookup_v1_HttpKeyBuilder_new(upb_Arena* arena) { + return (grpc_lookup_v1_HttpKeyBuilder*)_upb_Message_New(&grpc_lookup_v1_HttpKeyBuilder_msginit, arena); +} +UPB_INLINE grpc_lookup_v1_HttpKeyBuilder* grpc_lookup_v1_HttpKeyBuilder_parse(const char* buf, size_t size, upb_Arena* arena) { + grpc_lookup_v1_HttpKeyBuilder* ret = grpc_lookup_v1_HttpKeyBuilder_new(arena); + if (!ret) return NULL; + if (upb_Decode(buf, size, ret, &grpc_lookup_v1_HttpKeyBuilder_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) { + return NULL; + } + return ret; +} +UPB_INLINE grpc_lookup_v1_HttpKeyBuilder* grpc_lookup_v1_HttpKeyBuilder_parse_ex(const char* buf, size_t size, + const upb_ExtensionRegistry* extreg, + int options, upb_Arena* arena) { + grpc_lookup_v1_HttpKeyBuilder* ret = grpc_lookup_v1_HttpKeyBuilder_new(arena); + if (!ret) return NULL; + if (upb_Decode(buf, size, ret, &grpc_lookup_v1_HttpKeyBuilder_msginit, extreg, options, arena) != + kUpb_DecodeStatus_Ok) { + return NULL; + } + return ret; +} +UPB_INLINE char* grpc_lookup_v1_HttpKeyBuilder_serialize(const grpc_lookup_v1_HttpKeyBuilder* msg, upb_Arena* arena, size_t* len) { + return upb_Encode(msg, &grpc_lookup_v1_HttpKeyBuilder_msginit, 0, arena, len); +} +UPB_INLINE char* grpc_lookup_v1_HttpKeyBuilder_serialize_ex(const grpc_lookup_v1_HttpKeyBuilder* msg, int options, + upb_Arena* arena, size_t* len) { + return upb_Encode(msg, &grpc_lookup_v1_HttpKeyBuilder_msginit, options, arena, len); +} +UPB_INLINE upb_StringView const* grpc_lookup_v1_HttpKeyBuilder_host_patterns(const grpc_lookup_v1_HttpKeyBuilder *msg, size_t *len) { return (upb_StringView const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); } +UPB_INLINE upb_StringView const* grpc_lookup_v1_HttpKeyBuilder_path_patterns(const grpc_lookup_v1_HttpKeyBuilder *msg, size_t *len) { return (upb_StringView const*)_upb_array_accessor(msg, UPB_SIZE(4, 8), len); } +UPB_INLINE bool grpc_lookup_v1_HttpKeyBuilder_has_query_parameters(const grpc_lookup_v1_HttpKeyBuilder *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(8, 16)); } +UPB_INLINE const grpc_lookup_v1_NameMatcher* const* grpc_lookup_v1_HttpKeyBuilder_query_parameters(const grpc_lookup_v1_HttpKeyBuilder *msg, size_t *len) { return (const grpc_lookup_v1_NameMatcher* const*)_upb_array_accessor(msg, UPB_SIZE(8, 16), len); } +UPB_INLINE bool grpc_lookup_v1_HttpKeyBuilder_has_headers(const grpc_lookup_v1_HttpKeyBuilder *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(12, 24)); } +UPB_INLINE const grpc_lookup_v1_NameMatcher* const* grpc_lookup_v1_HttpKeyBuilder_headers(const grpc_lookup_v1_HttpKeyBuilder *msg, size_t *len) { return (const grpc_lookup_v1_NameMatcher* const*)_upb_array_accessor(msg, UPB_SIZE(12, 24), len); } +UPB_INLINE bool grpc_lookup_v1_HttpKeyBuilder_has_constant_keys(const grpc_lookup_v1_HttpKeyBuilder *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(16, 32)); } +UPB_INLINE size_t grpc_lookup_v1_HttpKeyBuilder_constant_keys_size(const grpc_lookup_v1_HttpKeyBuilder *msg) {return _upb_msg_map_size(msg, UPB_SIZE(16, 32)); } +UPB_INLINE bool grpc_lookup_v1_HttpKeyBuilder_constant_keys_get(const grpc_lookup_v1_HttpKeyBuilder *msg, upb_StringView key, upb_StringView *val) { return _upb_msg_map_get(msg, UPB_SIZE(16, 32), &key, 0, val, 0); } +UPB_INLINE const grpc_lookup_v1_HttpKeyBuilder_ConstantKeysEntry* grpc_lookup_v1_HttpKeyBuilder_constant_keys_next(const grpc_lookup_v1_HttpKeyBuilder *msg, size_t* iter) { return (const grpc_lookup_v1_HttpKeyBuilder_ConstantKeysEntry*)_upb_msg_map_next(msg, UPB_SIZE(16, 32), iter); } + +UPB_INLINE upb_StringView* grpc_lookup_v1_HttpKeyBuilder_mutable_host_patterns(grpc_lookup_v1_HttpKeyBuilder *msg, size_t *len) { + return (upb_StringView*)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len); +} +UPB_INLINE upb_StringView* grpc_lookup_v1_HttpKeyBuilder_resize_host_patterns(grpc_lookup_v1_HttpKeyBuilder *msg, size_t len, upb_Arena *arena) { + return (upb_StringView*)_upb_Array_Resize_accessor2(msg, UPB_SIZE(0, 0), len, UPB_SIZE(3, 4), arena); +} +UPB_INLINE bool grpc_lookup_v1_HttpKeyBuilder_add_host_patterns(grpc_lookup_v1_HttpKeyBuilder *msg, upb_StringView val, upb_Arena *arena) { + return _upb_Array_Append_accessor2(msg, UPB_SIZE(0, 0), UPB_SIZE(3, 4), &val, + arena); +} +UPB_INLINE upb_StringView* grpc_lookup_v1_HttpKeyBuilder_mutable_path_patterns(grpc_lookup_v1_HttpKeyBuilder *msg, size_t *len) { + return (upb_StringView*)_upb_array_mutable_accessor(msg, UPB_SIZE(4, 8), len); +} +UPB_INLINE upb_StringView* grpc_lookup_v1_HttpKeyBuilder_resize_path_patterns(grpc_lookup_v1_HttpKeyBuilder *msg, size_t len, upb_Arena *arena) { + return (upb_StringView*)_upb_Array_Resize_accessor2(msg, UPB_SIZE(4, 8), len, UPB_SIZE(3, 4), arena); +} +UPB_INLINE bool grpc_lookup_v1_HttpKeyBuilder_add_path_patterns(grpc_lookup_v1_HttpKeyBuilder *msg, upb_StringView val, upb_Arena *arena) { + return _upb_Array_Append_accessor2(msg, UPB_SIZE(4, 8), UPB_SIZE(3, 4), &val, + arena); +} +UPB_INLINE grpc_lookup_v1_NameMatcher** grpc_lookup_v1_HttpKeyBuilder_mutable_query_parameters(grpc_lookup_v1_HttpKeyBuilder *msg, size_t *len) { + return (grpc_lookup_v1_NameMatcher**)_upb_array_mutable_accessor(msg, UPB_SIZE(8, 16), len); +} +UPB_INLINE grpc_lookup_v1_NameMatcher** grpc_lookup_v1_HttpKeyBuilder_resize_query_parameters(grpc_lookup_v1_HttpKeyBuilder *msg, size_t len, upb_Arena *arena) { + return (grpc_lookup_v1_NameMatcher**)_upb_Array_Resize_accessor2(msg, UPB_SIZE(8, 16), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct grpc_lookup_v1_NameMatcher* grpc_lookup_v1_HttpKeyBuilder_add_query_parameters(grpc_lookup_v1_HttpKeyBuilder *msg, upb_Arena *arena) { + struct grpc_lookup_v1_NameMatcher* sub = (struct grpc_lookup_v1_NameMatcher*)_upb_Message_New(&grpc_lookup_v1_NameMatcher_msginit, arena); + bool ok = _upb_Array_Append_accessor2( + msg, UPB_SIZE(8, 16), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} +UPB_INLINE grpc_lookup_v1_NameMatcher** grpc_lookup_v1_HttpKeyBuilder_mutable_headers(grpc_lookup_v1_HttpKeyBuilder *msg, size_t *len) { + return (grpc_lookup_v1_NameMatcher**)_upb_array_mutable_accessor(msg, UPB_SIZE(12, 24), len); +} +UPB_INLINE grpc_lookup_v1_NameMatcher** grpc_lookup_v1_HttpKeyBuilder_resize_headers(grpc_lookup_v1_HttpKeyBuilder *msg, size_t len, upb_Arena *arena) { + return (grpc_lookup_v1_NameMatcher**)_upb_Array_Resize_accessor2(msg, UPB_SIZE(12, 24), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct grpc_lookup_v1_NameMatcher* grpc_lookup_v1_HttpKeyBuilder_add_headers(grpc_lookup_v1_HttpKeyBuilder *msg, upb_Arena *arena) { + struct grpc_lookup_v1_NameMatcher* sub = (struct grpc_lookup_v1_NameMatcher*)_upb_Message_New(&grpc_lookup_v1_NameMatcher_msginit, arena); + bool ok = _upb_Array_Append_accessor2( + msg, UPB_SIZE(12, 24), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} +UPB_INLINE void grpc_lookup_v1_HttpKeyBuilder_constant_keys_clear(grpc_lookup_v1_HttpKeyBuilder *msg) { _upb_msg_map_clear(msg, UPB_SIZE(16, 32)); } +UPB_INLINE bool grpc_lookup_v1_HttpKeyBuilder_constant_keys_set(grpc_lookup_v1_HttpKeyBuilder *msg, upb_StringView key, upb_StringView val, upb_Arena *a) { return _upb_msg_map_set(msg, UPB_SIZE(16, 32), &key, 0, &val, 0, a); } +UPB_INLINE bool grpc_lookup_v1_HttpKeyBuilder_constant_keys_delete(grpc_lookup_v1_HttpKeyBuilder *msg, upb_StringView key) { return _upb_msg_map_delete(msg, UPB_SIZE(16, 32), &key, 0); } +UPB_INLINE grpc_lookup_v1_HttpKeyBuilder_ConstantKeysEntry* grpc_lookup_v1_HttpKeyBuilder_constant_keys_nextmutable(grpc_lookup_v1_HttpKeyBuilder *msg, size_t* iter) { return (grpc_lookup_v1_HttpKeyBuilder_ConstantKeysEntry*)_upb_msg_map_next(msg, UPB_SIZE(16, 32), iter); } + +/* grpc.lookup.v1.HttpKeyBuilder.ConstantKeysEntry */ + +UPB_INLINE upb_StringView grpc_lookup_v1_HttpKeyBuilder_ConstantKeysEntry_key(const grpc_lookup_v1_HttpKeyBuilder_ConstantKeysEntry *msg) { + upb_StringView ret; + _upb_msg_map_key(msg, &ret, 0); + return ret; +} +UPB_INLINE upb_StringView grpc_lookup_v1_HttpKeyBuilder_ConstantKeysEntry_value(const grpc_lookup_v1_HttpKeyBuilder_ConstantKeysEntry *msg) { + upb_StringView ret; + _upb_msg_map_value(msg, &ret, 0); + return ret; +} + +UPB_INLINE void grpc_lookup_v1_HttpKeyBuilder_ConstantKeysEntry_set_value(grpc_lookup_v1_HttpKeyBuilder_ConstantKeysEntry *msg, upb_StringView value) { + _upb_msg_map_set_value(msg, &value, 0); +} + +/* grpc.lookup.v1.RouteLookupConfig */ + +UPB_INLINE grpc_lookup_v1_RouteLookupConfig* grpc_lookup_v1_RouteLookupConfig_new(upb_Arena* arena) { + return (grpc_lookup_v1_RouteLookupConfig*)_upb_Message_New(&grpc_lookup_v1_RouteLookupConfig_msginit, arena); +} +UPB_INLINE grpc_lookup_v1_RouteLookupConfig* grpc_lookup_v1_RouteLookupConfig_parse(const char* buf, size_t size, upb_Arena* arena) { + grpc_lookup_v1_RouteLookupConfig* ret = grpc_lookup_v1_RouteLookupConfig_new(arena); + if (!ret) return NULL; + if (upb_Decode(buf, size, ret, &grpc_lookup_v1_RouteLookupConfig_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) { + return NULL; + } + return ret; +} +UPB_INLINE grpc_lookup_v1_RouteLookupConfig* grpc_lookup_v1_RouteLookupConfig_parse_ex(const char* buf, size_t size, + const upb_ExtensionRegistry* extreg, + int options, upb_Arena* arena) { + grpc_lookup_v1_RouteLookupConfig* ret = grpc_lookup_v1_RouteLookupConfig_new(arena); + if (!ret) return NULL; + if (upb_Decode(buf, size, ret, &grpc_lookup_v1_RouteLookupConfig_msginit, extreg, options, arena) != + kUpb_DecodeStatus_Ok) { + return NULL; + } + return ret; +} +UPB_INLINE char* grpc_lookup_v1_RouteLookupConfig_serialize(const grpc_lookup_v1_RouteLookupConfig* msg, upb_Arena* arena, size_t* len) { + return upb_Encode(msg, &grpc_lookup_v1_RouteLookupConfig_msginit, 0, arena, len); +} +UPB_INLINE char* grpc_lookup_v1_RouteLookupConfig_serialize_ex(const grpc_lookup_v1_RouteLookupConfig* msg, int options, + upb_Arena* arena, size_t* len) { + return upb_Encode(msg, &grpc_lookup_v1_RouteLookupConfig_msginit, options, arena, len); +} +UPB_INLINE bool grpc_lookup_v1_RouteLookupConfig_has_http_keybuilders(const grpc_lookup_v1_RouteLookupConfig *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(44, 72)); } +UPB_INLINE const grpc_lookup_v1_HttpKeyBuilder* const* grpc_lookup_v1_RouteLookupConfig_http_keybuilders(const grpc_lookup_v1_RouteLookupConfig *msg, size_t *len) { return (const grpc_lookup_v1_HttpKeyBuilder* const*)_upb_array_accessor(msg, UPB_SIZE(44, 72), len); } +UPB_INLINE bool grpc_lookup_v1_RouteLookupConfig_has_grpc_keybuilders(const grpc_lookup_v1_RouteLookupConfig *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(48, 80)); } +UPB_INLINE const grpc_lookup_v1_GrpcKeyBuilder* const* grpc_lookup_v1_RouteLookupConfig_grpc_keybuilders(const grpc_lookup_v1_RouteLookupConfig *msg, size_t *len) { return (const grpc_lookup_v1_GrpcKeyBuilder* const*)_upb_array_accessor(msg, UPB_SIZE(48, 80), len); } +UPB_INLINE upb_StringView grpc_lookup_v1_RouteLookupConfig_lookup_service(const grpc_lookup_v1_RouteLookupConfig* msg) { + return *UPB_PTR_AT(msg, UPB_SIZE(16, 16), upb_StringView); +} +UPB_INLINE bool grpc_lookup_v1_RouteLookupConfig_has_lookup_service_timeout(const grpc_lookup_v1_RouteLookupConfig *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE const struct google_protobuf_Duration* grpc_lookup_v1_RouteLookupConfig_lookup_service_timeout(const grpc_lookup_v1_RouteLookupConfig* msg) { + return *UPB_PTR_AT(msg, UPB_SIZE(32, 48), const struct google_protobuf_Duration*); +} +UPB_INLINE bool grpc_lookup_v1_RouteLookupConfig_has_max_age(const grpc_lookup_v1_RouteLookupConfig *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE const struct google_protobuf_Duration* grpc_lookup_v1_RouteLookupConfig_max_age(const grpc_lookup_v1_RouteLookupConfig* msg) { + return *UPB_PTR_AT(msg, UPB_SIZE(36, 56), const struct google_protobuf_Duration*); +} +UPB_INLINE bool grpc_lookup_v1_RouteLookupConfig_has_stale_age(const grpc_lookup_v1_RouteLookupConfig *msg) { return _upb_hasbit(msg, 3); } +UPB_INLINE const struct google_protobuf_Duration* grpc_lookup_v1_RouteLookupConfig_stale_age(const grpc_lookup_v1_RouteLookupConfig* msg) { + return *UPB_PTR_AT(msg, UPB_SIZE(40, 64), const struct google_protobuf_Duration*); +} +UPB_INLINE int64_t grpc_lookup_v1_RouteLookupConfig_cache_size_bytes(const grpc_lookup_v1_RouteLookupConfig* msg) { + return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int64_t); +} +UPB_INLINE upb_StringView const* grpc_lookup_v1_RouteLookupConfig_valid_targets(const grpc_lookup_v1_RouteLookupConfig *msg, size_t *len) { return (upb_StringView const*)_upb_array_accessor(msg, UPB_SIZE(52, 88), len); } +UPB_INLINE upb_StringView grpc_lookup_v1_RouteLookupConfig_default_target(const grpc_lookup_v1_RouteLookupConfig* msg) { + return *UPB_PTR_AT(msg, UPB_SIZE(24, 32), upb_StringView); +} + +UPB_INLINE grpc_lookup_v1_HttpKeyBuilder** grpc_lookup_v1_RouteLookupConfig_mutable_http_keybuilders(grpc_lookup_v1_RouteLookupConfig *msg, size_t *len) { + return (grpc_lookup_v1_HttpKeyBuilder**)_upb_array_mutable_accessor(msg, UPB_SIZE(44, 72), len); +} +UPB_INLINE grpc_lookup_v1_HttpKeyBuilder** grpc_lookup_v1_RouteLookupConfig_resize_http_keybuilders(grpc_lookup_v1_RouteLookupConfig *msg, size_t len, upb_Arena *arena) { + return (grpc_lookup_v1_HttpKeyBuilder**)_upb_Array_Resize_accessor2(msg, UPB_SIZE(44, 72), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct grpc_lookup_v1_HttpKeyBuilder* grpc_lookup_v1_RouteLookupConfig_add_http_keybuilders(grpc_lookup_v1_RouteLookupConfig *msg, upb_Arena *arena) { + struct grpc_lookup_v1_HttpKeyBuilder* sub = (struct grpc_lookup_v1_HttpKeyBuilder*)_upb_Message_New(&grpc_lookup_v1_HttpKeyBuilder_msginit, arena); + bool ok = _upb_Array_Append_accessor2( + msg, UPB_SIZE(44, 72), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} +UPB_INLINE grpc_lookup_v1_GrpcKeyBuilder** grpc_lookup_v1_RouteLookupConfig_mutable_grpc_keybuilders(grpc_lookup_v1_RouteLookupConfig *msg, size_t *len) { + return (grpc_lookup_v1_GrpcKeyBuilder**)_upb_array_mutable_accessor(msg, UPB_SIZE(48, 80), len); +} +UPB_INLINE grpc_lookup_v1_GrpcKeyBuilder** grpc_lookup_v1_RouteLookupConfig_resize_grpc_keybuilders(grpc_lookup_v1_RouteLookupConfig *msg, size_t len, upb_Arena *arena) { + return (grpc_lookup_v1_GrpcKeyBuilder**)_upb_Array_Resize_accessor2(msg, UPB_SIZE(48, 80), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct grpc_lookup_v1_GrpcKeyBuilder* grpc_lookup_v1_RouteLookupConfig_add_grpc_keybuilders(grpc_lookup_v1_RouteLookupConfig *msg, upb_Arena *arena) { + struct grpc_lookup_v1_GrpcKeyBuilder* sub = (struct grpc_lookup_v1_GrpcKeyBuilder*)_upb_Message_New(&grpc_lookup_v1_GrpcKeyBuilder_msginit, arena); + bool ok = _upb_Array_Append_accessor2( + msg, UPB_SIZE(48, 80), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} +UPB_INLINE void grpc_lookup_v1_RouteLookupConfig_set_lookup_service(grpc_lookup_v1_RouteLookupConfig *msg, upb_StringView value) { + *UPB_PTR_AT(msg, UPB_SIZE(16, 16), upb_StringView) = value; +} +UPB_INLINE void grpc_lookup_v1_RouteLookupConfig_set_lookup_service_timeout(grpc_lookup_v1_RouteLookupConfig *msg, struct google_protobuf_Duration* value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(32, 48), struct google_protobuf_Duration*) = value; +} +UPB_INLINE struct google_protobuf_Duration* grpc_lookup_v1_RouteLookupConfig_mutable_lookup_service_timeout(grpc_lookup_v1_RouteLookupConfig *msg, upb_Arena *arena) { + struct google_protobuf_Duration* sub = (struct google_protobuf_Duration*)grpc_lookup_v1_RouteLookupConfig_lookup_service_timeout(msg); + if (sub == NULL) { + sub = (struct google_protobuf_Duration*)_upb_Message_New(&google_protobuf_Duration_msginit, arena); + if (!sub) return NULL; + grpc_lookup_v1_RouteLookupConfig_set_lookup_service_timeout(msg, sub); + } + return sub; +} +UPB_INLINE void grpc_lookup_v1_RouteLookupConfig_set_max_age(grpc_lookup_v1_RouteLookupConfig *msg, struct google_protobuf_Duration* value) { + _upb_sethas(msg, 2); + *UPB_PTR_AT(msg, UPB_SIZE(36, 56), struct google_protobuf_Duration*) = value; +} +UPB_INLINE struct google_protobuf_Duration* grpc_lookup_v1_RouteLookupConfig_mutable_max_age(grpc_lookup_v1_RouteLookupConfig *msg, upb_Arena *arena) { + struct google_protobuf_Duration* sub = (struct google_protobuf_Duration*)grpc_lookup_v1_RouteLookupConfig_max_age(msg); + if (sub == NULL) { + sub = (struct google_protobuf_Duration*)_upb_Message_New(&google_protobuf_Duration_msginit, arena); + if (!sub) return NULL; + grpc_lookup_v1_RouteLookupConfig_set_max_age(msg, sub); + } + return sub; +} +UPB_INLINE void grpc_lookup_v1_RouteLookupConfig_set_stale_age(grpc_lookup_v1_RouteLookupConfig *msg, struct google_protobuf_Duration* value) { + _upb_sethas(msg, 3); + *UPB_PTR_AT(msg, UPB_SIZE(40, 64), struct google_protobuf_Duration*) = value; +} +UPB_INLINE struct google_protobuf_Duration* grpc_lookup_v1_RouteLookupConfig_mutable_stale_age(grpc_lookup_v1_RouteLookupConfig *msg, upb_Arena *arena) { + struct google_protobuf_Duration* sub = (struct google_protobuf_Duration*)grpc_lookup_v1_RouteLookupConfig_stale_age(msg); + if (sub == NULL) { + sub = (struct google_protobuf_Duration*)_upb_Message_New(&google_protobuf_Duration_msginit, arena); + if (!sub) return NULL; + grpc_lookup_v1_RouteLookupConfig_set_stale_age(msg, sub); + } + return sub; +} +UPB_INLINE void grpc_lookup_v1_RouteLookupConfig_set_cache_size_bytes(grpc_lookup_v1_RouteLookupConfig *msg, int64_t value) { + *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int64_t) = value; +} +UPB_INLINE upb_StringView* grpc_lookup_v1_RouteLookupConfig_mutable_valid_targets(grpc_lookup_v1_RouteLookupConfig *msg, size_t *len) { + return (upb_StringView*)_upb_array_mutable_accessor(msg, UPB_SIZE(52, 88), len); +} +UPB_INLINE upb_StringView* grpc_lookup_v1_RouteLookupConfig_resize_valid_targets(grpc_lookup_v1_RouteLookupConfig *msg, size_t len, upb_Arena *arena) { + return (upb_StringView*)_upb_Array_Resize_accessor2(msg, UPB_SIZE(52, 88), len, UPB_SIZE(3, 4), arena); +} +UPB_INLINE bool grpc_lookup_v1_RouteLookupConfig_add_valid_targets(grpc_lookup_v1_RouteLookupConfig *msg, upb_StringView val, upb_Arena *arena) { + return _upb_Array_Append_accessor2(msg, UPB_SIZE(52, 88), UPB_SIZE(3, 4), &val, + arena); +} +UPB_INLINE void grpc_lookup_v1_RouteLookupConfig_set_default_target(grpc_lookup_v1_RouteLookupConfig *msg, upb_StringView value) { + *UPB_PTR_AT(msg, UPB_SIZE(24, 32), upb_StringView) = value; +} + +/* grpc.lookup.v1.RouteLookupClusterSpecifier */ + +UPB_INLINE grpc_lookup_v1_RouteLookupClusterSpecifier* grpc_lookup_v1_RouteLookupClusterSpecifier_new(upb_Arena* arena) { + return (grpc_lookup_v1_RouteLookupClusterSpecifier*)_upb_Message_New(&grpc_lookup_v1_RouteLookupClusterSpecifier_msginit, arena); +} +UPB_INLINE grpc_lookup_v1_RouteLookupClusterSpecifier* grpc_lookup_v1_RouteLookupClusterSpecifier_parse(const char* buf, size_t size, upb_Arena* arena) { + grpc_lookup_v1_RouteLookupClusterSpecifier* ret = grpc_lookup_v1_RouteLookupClusterSpecifier_new(arena); + if (!ret) return NULL; + if (upb_Decode(buf, size, ret, &grpc_lookup_v1_RouteLookupClusterSpecifier_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) { + return NULL; + } + return ret; +} +UPB_INLINE grpc_lookup_v1_RouteLookupClusterSpecifier* grpc_lookup_v1_RouteLookupClusterSpecifier_parse_ex(const char* buf, size_t size, + const upb_ExtensionRegistry* extreg, + int options, upb_Arena* arena) { + grpc_lookup_v1_RouteLookupClusterSpecifier* ret = grpc_lookup_v1_RouteLookupClusterSpecifier_new(arena); + if (!ret) return NULL; + if (upb_Decode(buf, size, ret, &grpc_lookup_v1_RouteLookupClusterSpecifier_msginit, extreg, options, arena) != + kUpb_DecodeStatus_Ok) { + return NULL; + } + return ret; +} +UPB_INLINE char* grpc_lookup_v1_RouteLookupClusterSpecifier_serialize(const grpc_lookup_v1_RouteLookupClusterSpecifier* msg, upb_Arena* arena, size_t* len) { + return upb_Encode(msg, &grpc_lookup_v1_RouteLookupClusterSpecifier_msginit, 0, arena, len); +} +UPB_INLINE char* grpc_lookup_v1_RouteLookupClusterSpecifier_serialize_ex(const grpc_lookup_v1_RouteLookupClusterSpecifier* msg, int options, + upb_Arena* arena, size_t* len) { + return upb_Encode(msg, &grpc_lookup_v1_RouteLookupClusterSpecifier_msginit, options, arena, len); +} +UPB_INLINE bool grpc_lookup_v1_RouteLookupClusterSpecifier_has_route_lookup_config(const grpc_lookup_v1_RouteLookupClusterSpecifier *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE const grpc_lookup_v1_RouteLookupConfig* grpc_lookup_v1_RouteLookupClusterSpecifier_route_lookup_config(const grpc_lookup_v1_RouteLookupClusterSpecifier* msg) { + return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), const grpc_lookup_v1_RouteLookupConfig*); +} + +UPB_INLINE void grpc_lookup_v1_RouteLookupClusterSpecifier_set_route_lookup_config(grpc_lookup_v1_RouteLookupClusterSpecifier *msg, grpc_lookup_v1_RouteLookupConfig* value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), grpc_lookup_v1_RouteLookupConfig*) = value; +} +UPB_INLINE struct grpc_lookup_v1_RouteLookupConfig* grpc_lookup_v1_RouteLookupClusterSpecifier_mutable_route_lookup_config(grpc_lookup_v1_RouteLookupClusterSpecifier *msg, upb_Arena *arena) { + struct grpc_lookup_v1_RouteLookupConfig* sub = (struct grpc_lookup_v1_RouteLookupConfig*)grpc_lookup_v1_RouteLookupClusterSpecifier_route_lookup_config(msg); + if (sub == NULL) { + sub = (struct grpc_lookup_v1_RouteLookupConfig*)_upb_Message_New(&grpc_lookup_v1_RouteLookupConfig_msginit, arena); + if (!sub) return NULL; + grpc_lookup_v1_RouteLookupClusterSpecifier_set_route_lookup_config(msg, sub); + } + return sub; +} + +extern const upb_MiniTable_File src_proto_grpc_lookup_v1_rls_config_proto_upb_file_layout; + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#include "upb/port_undef.inc" + +#endif /* SRC_PROTO_GRPC_LOOKUP_V1_RLS_CONFIG_PROTO_UPB_H_ */ diff --git a/src/core/ext/upbdefs-generated/src/proto/grpc/lookup/v1/rls_config.upbdefs.c b/src/core/ext/upbdefs-generated/src/proto/grpc/lookup/v1/rls_config.upbdefs.c new file mode 100644 index 00000000000..92c529b67db --- /dev/null +++ b/src/core/ext/upbdefs-generated/src/proto/grpc/lookup/v1/rls_config.upbdefs.c @@ -0,0 +1,99 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * src/proto/grpc/lookup/v1/rls_config.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#include "upb/def.h" +#include "src/proto/grpc/lookup/v1/rls_config.upbdefs.h" +#include "src/proto/grpc/lookup/v1/rls_config.upb.h" + +extern _upb_DefPool_Init google_protobuf_duration_proto_upbdefinit; +static const char descriptor[1816] = {'\n', ')', 's', 'r', 'c', '/', 'p', 'r', 'o', 't', 'o', '/', 'g', 'r', 'p', 'c', '/', 'l', 'o', 'o', 'k', 'u', 'p', '/', 'v', +'1', '/', 'r', 'l', 's', '_', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'p', 'r', 'o', 't', 'o', '\022', '\016', 'g', 'r', 'p', 'c', '.', +'l', 'o', 'o', 'k', 'u', 'p', '.', 'v', '1', '\032', '\036', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', +'f', '/', 'd', 'u', 'r', 'a', 't', 'i', 'o', 'n', '.', 'p', 'r', 'o', 't', 'o', '\"', '\\', '\n', '\013', 'N', 'a', 'm', 'e', 'M', +'a', 't', 'c', 'h', 'e', 'r', '\022', '\020', '\n', '\003', 'k', 'e', 'y', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\003', 'k', 'e', 'y', '\022', +'\024', '\n', '\005', 'n', 'a', 'm', 'e', 's', '\030', '\002', ' ', '\003', '(', '\t', 'R', '\005', 'n', 'a', 'm', 'e', 's', '\022', '%', '\n', '\016', +'r', 'e', 'q', 'u', 'i', 'r', 'e', 'd', '_', 'm', 'a', 't', 'c', 'h', '\030', '\003', ' ', '\001', '(', '\010', 'R', '\r', 'r', 'e', 'q', +'u', 'i', 'r', 'e', 'd', 'M', 'a', 't', 'c', 'h', '\"', '\360', '\003', '\n', '\016', 'G', 'r', 'p', 'c', 'K', 'e', 'y', 'B', 'u', 'i', +'l', 'd', 'e', 'r', '\022', '9', '\n', '\005', 'n', 'a', 'm', 'e', 's', '\030', '\001', ' ', '\003', '(', '\013', '2', '#', '.', 'g', 'r', 'p', +'c', '.', 'l', 'o', 'o', 'k', 'u', 'p', '.', 'v', '1', '.', 'G', 'r', 'p', 'c', 'K', 'e', 'y', 'B', 'u', 'i', 'l', 'd', 'e', +'r', '.', 'N', 'a', 'm', 'e', 'R', '\005', 'n', 'a', 'm', 'e', 's', '\022', 'G', '\n', '\n', 'e', 'x', 't', 'r', 'a', '_', 'k', 'e', +'y', 's', '\030', '\003', ' ', '\001', '(', '\013', '2', '(', '.', 'g', 'r', 'p', 'c', '.', 'l', 'o', 'o', 'k', 'u', 'p', '.', 'v', '1', +'.', 'G', 'r', 'p', 'c', 'K', 'e', 'y', 'B', 'u', 'i', 'l', 'd', 'e', 'r', '.', 'E', 'x', 't', 'r', 'a', 'K', 'e', 'y', 's', +'R', '\t', 'e', 'x', 't', 'r', 'a', 'K', 'e', 'y', 's', '\022', '5', '\n', '\007', 'h', 'e', 'a', 'd', 'e', 'r', 's', '\030', '\002', ' ', +'\003', '(', '\013', '2', '\033', '.', 'g', 'r', 'p', 'c', '.', 'l', 'o', 'o', 'k', 'u', 'p', '.', 'v', '1', '.', 'N', 'a', 'm', 'e', +'M', 'a', 't', 'c', 'h', 'e', 'r', 'R', '\007', 'h', 'e', 'a', 'd', 'e', 'r', 's', '\022', 'U', '\n', '\r', 'c', 'o', 'n', 's', 't', +'a', 'n', 't', '_', 'k', 'e', 'y', 's', '\030', '\004', ' ', '\003', '(', '\013', '2', '0', '.', 'g', 'r', 'p', 'c', '.', 'l', 'o', 'o', +'k', 'u', 'p', '.', 'v', '1', '.', 'G', 'r', 'p', 'c', 'K', 'e', 'y', 'B', 'u', 'i', 'l', 'd', 'e', 'r', '.', 'C', 'o', 'n', +'s', 't', 'a', 'n', 't', 'K', 'e', 'y', 's', 'E', 'n', 't', 'r', 'y', 'R', '\014', 'c', 'o', 'n', 's', 't', 'a', 'n', 't', 'K', +'e', 'y', 's', '\032', '8', '\n', '\004', 'N', 'a', 'm', 'e', '\022', '\030', '\n', '\007', 's', 'e', 'r', 'v', 'i', 'c', 'e', '\030', '\001', ' ', +'\001', '(', '\t', 'R', '\007', 's', 'e', 'r', 'v', 'i', 'c', 'e', '\022', '\026', '\n', '\006', 'm', 'e', 't', 'h', 'o', 'd', '\030', '\002', ' ', +'\001', '(', '\t', 'R', '\006', 'm', 'e', 't', 'h', 'o', 'd', '\032', 'Q', '\n', '\t', 'E', 'x', 't', 'r', 'a', 'K', 'e', 'y', 's', '\022', +'\022', '\n', '\004', 'h', 'o', 's', 't', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\004', 'h', 'o', 's', 't', '\022', '\030', '\n', '\007', 's', 'e', +'r', 'v', 'i', 'c', 'e', '\030', '\002', ' ', '\001', '(', '\t', 'R', '\007', 's', 'e', 'r', 'v', 'i', 'c', 'e', '\022', '\026', '\n', '\006', 'm', +'e', 't', 'h', 'o', 'd', '\030', '\003', ' ', '\001', '(', '\t', 'R', '\006', 'm', 'e', 't', 'h', 'o', 'd', '\032', '?', '\n', '\021', 'C', 'o', +'n', 's', 't', 'a', 'n', 't', 'K', 'e', 'y', 's', 'E', 'n', 't', 'r', 'y', '\022', '\020', '\n', '\003', 'k', 'e', 'y', '\030', '\001', ' ', +'\001', '(', '\t', 'R', '\003', 'k', 'e', 'y', '\022', '\024', '\n', '\005', 'v', 'a', 'l', 'u', 'e', '\030', '\002', ' ', '\001', '(', '\t', 'R', '\005', +'v', 'a', 'l', 'u', 'e', ':', '\002', '8', '\001', '\"', '\361', '\002', '\n', '\016', 'H', 't', 't', 'p', 'K', 'e', 'y', 'B', 'u', 'i', 'l', +'d', 'e', 'r', '\022', '#', '\n', '\r', 'h', 'o', 's', 't', '_', 'p', 'a', 't', 't', 'e', 'r', 'n', 's', '\030', '\001', ' ', '\003', '(', +'\t', 'R', '\014', 'h', 'o', 's', 't', 'P', 'a', 't', 't', 'e', 'r', 'n', 's', '\022', '#', '\n', '\r', 'p', 'a', 't', 'h', '_', 'p', +'a', 't', 't', 'e', 'r', 'n', 's', '\030', '\002', ' ', '\003', '(', '\t', 'R', '\014', 'p', 'a', 't', 'h', 'P', 'a', 't', 't', 'e', 'r', +'n', 's', '\022', 'F', '\n', '\020', 'q', 'u', 'e', 'r', 'y', '_', 'p', 'a', 'r', 'a', 'm', 'e', 't', 'e', 'r', 's', '\030', '\003', ' ', +'\003', '(', '\013', '2', '\033', '.', 'g', 'r', 'p', 'c', '.', 'l', 'o', 'o', 'k', 'u', 'p', '.', 'v', '1', '.', 'N', 'a', 'm', 'e', +'M', 'a', 't', 'c', 'h', 'e', 'r', 'R', '\017', 'q', 'u', 'e', 'r', 'y', 'P', 'a', 'r', 'a', 'm', 'e', 't', 'e', 'r', 's', '\022', +'5', '\n', '\007', 'h', 'e', 'a', 'd', 'e', 'r', 's', '\030', '\004', ' ', '\003', '(', '\013', '2', '\033', '.', 'g', 'r', 'p', 'c', '.', 'l', +'o', 'o', 'k', 'u', 'p', '.', 'v', '1', '.', 'N', 'a', 'm', 'e', 'M', 'a', 't', 'c', 'h', 'e', 'r', 'R', '\007', 'h', 'e', 'a', +'d', 'e', 'r', 's', '\022', 'U', '\n', '\r', 'c', 'o', 'n', 's', 't', 'a', 'n', 't', '_', 'k', 'e', 'y', 's', '\030', '\005', ' ', '\003', +'(', '\013', '2', '0', '.', 'g', 'r', 'p', 'c', '.', 'l', 'o', 'o', 'k', 'u', 'p', '.', 'v', '1', '.', 'H', 't', 't', 'p', 'K', +'e', 'y', 'B', 'u', 'i', 'l', 'd', 'e', 'r', '.', 'C', 'o', 'n', 's', 't', 'a', 'n', 't', 'K', 'e', 'y', 's', 'E', 'n', 't', +'r', 'y', 'R', '\014', 'c', 'o', 'n', 's', 't', 'a', 'n', 't', 'K', 'e', 'y', 's', '\032', '?', '\n', '\021', 'C', 'o', 'n', 's', 't', +'a', 'n', 't', 'K', 'e', 'y', 's', 'E', 'n', 't', 'r', 'y', '\022', '\020', '\n', '\003', 'k', 'e', 'y', '\030', '\001', ' ', '\001', '(', '\t', +'R', '\003', 'k', 'e', 'y', '\022', '\024', '\n', '\005', 'v', 'a', 'l', 'u', 'e', '\030', '\002', ' ', '\001', '(', '\t', 'R', '\005', 'v', 'a', 'l', +'u', 'e', ':', '\002', '8', '\001', '\"', '\246', '\004', '\n', '\021', 'R', 'o', 'u', 't', 'e', 'L', 'o', 'o', 'k', 'u', 'p', 'C', 'o', 'n', +'f', 'i', 'g', '\022', 'I', '\n', '\020', 'h', 't', 't', 'p', '_', 'k', 'e', 'y', 'b', 'u', 'i', 'l', 'd', 'e', 'r', 's', '\030', '\001', +' ', '\003', '(', '\013', '2', '\036', '.', 'g', 'r', 'p', 'c', '.', 'l', 'o', 'o', 'k', 'u', 'p', '.', 'v', '1', '.', 'H', 't', 't', +'p', 'K', 'e', 'y', 'B', 'u', 'i', 'l', 'd', 'e', 'r', 'R', '\017', 'h', 't', 't', 'p', 'K', 'e', 'y', 'b', 'u', 'i', 'l', 'd', +'e', 'r', 's', '\022', 'I', '\n', '\020', 'g', 'r', 'p', 'c', '_', 'k', 'e', 'y', 'b', 'u', 'i', 'l', 'd', 'e', 'r', 's', '\030', '\002', +' ', '\003', '(', '\013', '2', '\036', '.', 'g', 'r', 'p', 'c', '.', 'l', 'o', 'o', 'k', 'u', 'p', '.', 'v', '1', '.', 'G', 'r', 'p', +'c', 'K', 'e', 'y', 'B', 'u', 'i', 'l', 'd', 'e', 'r', 'R', '\017', 'g', 'r', 'p', 'c', 'K', 'e', 'y', 'b', 'u', 'i', 'l', 'd', +'e', 'r', 's', '\022', '%', '\n', '\016', 'l', 'o', 'o', 'k', 'u', 'p', '_', 's', 'e', 'r', 'v', 'i', 'c', 'e', '\030', '\003', ' ', '\001', +'(', '\t', 'R', '\r', 'l', 'o', 'o', 'k', 'u', 'p', 'S', 'e', 'r', 'v', 'i', 'c', 'e', '\022', 'O', '\n', '\026', 'l', 'o', 'o', 'k', +'u', 'p', '_', 's', 'e', 'r', 'v', 'i', 'c', 'e', '_', 't', 'i', 'm', 'e', 'o', 'u', 't', '\030', '\004', ' ', '\001', '(', '\013', '2', +'\031', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'D', 'u', 'r', 'a', 't', 'i', 'o', +'n', 'R', '\024', 'l', 'o', 'o', 'k', 'u', 'p', 'S', 'e', 'r', 'v', 'i', 'c', 'e', 'T', 'i', 'm', 'e', 'o', 'u', 't', '\022', '2', +'\n', '\007', 'm', 'a', 'x', '_', 'a', 'g', 'e', '\030', '\005', ' ', '\001', '(', '\013', '2', '\031', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', +'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'D', 'u', 'r', 'a', 't', 'i', 'o', 'n', 'R', '\006', 'm', 'a', 'x', 'A', 'g', 'e', +'\022', '6', '\n', '\t', 's', 't', 'a', 'l', 'e', '_', 'a', 'g', 'e', '\030', '\006', ' ', '\001', '(', '\013', '2', '\031', '.', 'g', 'o', 'o', +'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'D', 'u', 'r', 'a', 't', 'i', 'o', 'n', 'R', '\010', 's', 't', +'a', 'l', 'e', 'A', 'g', 'e', '\022', '(', '\n', '\020', 'c', 'a', 'c', 'h', 'e', '_', 's', 'i', 'z', 'e', '_', 'b', 'y', 't', 'e', +'s', '\030', '\007', ' ', '\001', '(', '\003', 'R', '\016', 'c', 'a', 'c', 'h', 'e', 'S', 'i', 'z', 'e', 'B', 'y', 't', 'e', 's', '\022', '#', +'\n', '\r', 'v', 'a', 'l', 'i', 'd', '_', 't', 'a', 'r', 'g', 'e', 't', 's', '\030', '\010', ' ', '\003', '(', '\t', 'R', '\014', 'v', 'a', +'l', 'i', 'd', 'T', 'a', 'r', 'g', 'e', 't', 's', '\022', '%', '\n', '\016', 'd', 'e', 'f', 'a', 'u', 'l', 't', '_', 't', 'a', 'r', +'g', 'e', 't', '\030', '\t', ' ', '\001', '(', '\t', 'R', '\r', 'd', 'e', 'f', 'a', 'u', 'l', 't', 'T', 'a', 'r', 'g', 'e', 't', 'J', +'\004', '\010', '\n', '\020', '\013', 'R', '\033', 'r', 'e', 'q', 'u', 'e', 's', 't', '_', 'p', 'r', 'o', 'c', 'e', 's', 's', 'i', 'n', 'g', +'_', 's', 't', 'r', 'a', 't', 'e', 'g', 'y', '\"', 'p', '\n', '\033', 'R', 'o', 'u', 't', 'e', 'L', 'o', 'o', 'k', 'u', 'p', 'C', +'l', 'u', 's', 't', 'e', 'r', 'S', 'p', 'e', 'c', 'i', 'f', 'i', 'e', 'r', '\022', 'Q', '\n', '\023', 'r', 'o', 'u', 't', 'e', '_', +'l', 'o', 'o', 'k', 'u', 'p', '_', 'c', 'o', 'n', 'f', 'i', 'g', '\030', '\001', ' ', '\001', '(', '\013', '2', '!', '.', 'g', 'r', 'p', +'c', '.', 'l', 'o', 'o', 'k', 'u', 'p', '.', 'v', '1', '.', 'R', 'o', 'u', 't', 'e', 'L', 'o', 'o', 'k', 'u', 'p', 'C', 'o', +'n', 'f', 'i', 'g', 'R', '\021', 'r', 'o', 'u', 't', 'e', 'L', 'o', 'o', 'k', 'u', 'p', 'C', 'o', 'n', 'f', 'i', 'g', 'B', 'S', +'\n', '\021', 'i', 'o', '.', 'g', 'r', 'p', 'c', '.', 'l', 'o', 'o', 'k', 'u', 'p', '.', 'v', '1', 'B', '\016', 'R', 'l', 's', 'C', +'o', 'n', 'f', 'i', 'g', 'P', 'r', 'o', 't', 'o', 'P', '\001', 'Z', ',', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'g', 'o', 'l', 'a', +'n', 'g', '.', 'o', 'r', 'g', '/', 'g', 'r', 'p', 'c', '/', 'l', 'o', 'o', 'k', 'u', 'p', '/', 'g', 'r', 'p', 'c', '_', 'l', +'o', 'o', 'k', 'u', 'p', '_', 'v', '1', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3', +}; + +static _upb_DefPool_Init *deps[2] = { + &google_protobuf_duration_proto_upbdefinit, + NULL +}; + +_upb_DefPool_Init src_proto_grpc_lookup_v1_rls_config_proto_upbdefinit = { + deps, + &src_proto_grpc_lookup_v1_rls_config_proto_upb_file_layout, + "src/proto/grpc/lookup/v1/rls_config.proto", + UPB_STRINGVIEW_INIT(descriptor, 1816) +}; diff --git a/src/core/ext/upbdefs-generated/src/proto/grpc/lookup/v1/rls_config.upbdefs.h b/src/core/ext/upbdefs-generated/src/proto/grpc/lookup/v1/rls_config.upbdefs.h new file mode 100644 index 00000000000..3a7591fa5de --- /dev/null +++ b/src/core/ext/upbdefs-generated/src/proto/grpc/lookup/v1/rls_config.upbdefs.h @@ -0,0 +1,75 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * src/proto/grpc/lookup/v1/rls_config.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#ifndef SRC_PROTO_GRPC_LOOKUP_V1_RLS_CONFIG_PROTO_UPBDEFS_H_ +#define SRC_PROTO_GRPC_LOOKUP_V1_RLS_CONFIG_PROTO_UPBDEFS_H_ + +#include "upb/def.h" +#include "upb/port_def.inc" +#ifdef __cplusplus +extern "C" { +#endif + +#include "upb/def.h" + +#include "upb/port_def.inc" + +extern _upb_DefPool_Init src_proto_grpc_lookup_v1_rls_config_proto_upbdefinit; + +UPB_INLINE const upb_MessageDef *grpc_lookup_v1_NameMatcher_getmsgdef(upb_DefPool *s) { + _upb_DefPool_LoadDefInit(s, &src_proto_grpc_lookup_v1_rls_config_proto_upbdefinit); + return upb_DefPool_FindMessageByName(s, "grpc.lookup.v1.NameMatcher"); +} + +UPB_INLINE const upb_MessageDef *grpc_lookup_v1_GrpcKeyBuilder_getmsgdef(upb_DefPool *s) { + _upb_DefPool_LoadDefInit(s, &src_proto_grpc_lookup_v1_rls_config_proto_upbdefinit); + return upb_DefPool_FindMessageByName(s, "grpc.lookup.v1.GrpcKeyBuilder"); +} + +UPB_INLINE const upb_MessageDef *grpc_lookup_v1_GrpcKeyBuilder_Name_getmsgdef(upb_DefPool *s) { + _upb_DefPool_LoadDefInit(s, &src_proto_grpc_lookup_v1_rls_config_proto_upbdefinit); + return upb_DefPool_FindMessageByName(s, "grpc.lookup.v1.GrpcKeyBuilder.Name"); +} + +UPB_INLINE const upb_MessageDef *grpc_lookup_v1_GrpcKeyBuilder_ExtraKeys_getmsgdef(upb_DefPool *s) { + _upb_DefPool_LoadDefInit(s, &src_proto_grpc_lookup_v1_rls_config_proto_upbdefinit); + return upb_DefPool_FindMessageByName(s, "grpc.lookup.v1.GrpcKeyBuilder.ExtraKeys"); +} + +UPB_INLINE const upb_MessageDef *grpc_lookup_v1_GrpcKeyBuilder_ConstantKeysEntry_getmsgdef(upb_DefPool *s) { + _upb_DefPool_LoadDefInit(s, &src_proto_grpc_lookup_v1_rls_config_proto_upbdefinit); + return upb_DefPool_FindMessageByName(s, "grpc.lookup.v1.GrpcKeyBuilder.ConstantKeysEntry"); +} + +UPB_INLINE const upb_MessageDef *grpc_lookup_v1_HttpKeyBuilder_getmsgdef(upb_DefPool *s) { + _upb_DefPool_LoadDefInit(s, &src_proto_grpc_lookup_v1_rls_config_proto_upbdefinit); + return upb_DefPool_FindMessageByName(s, "grpc.lookup.v1.HttpKeyBuilder"); +} + +UPB_INLINE const upb_MessageDef *grpc_lookup_v1_HttpKeyBuilder_ConstantKeysEntry_getmsgdef(upb_DefPool *s) { + _upb_DefPool_LoadDefInit(s, &src_proto_grpc_lookup_v1_rls_config_proto_upbdefinit); + return upb_DefPool_FindMessageByName(s, "grpc.lookup.v1.HttpKeyBuilder.ConstantKeysEntry"); +} + +UPB_INLINE const upb_MessageDef *grpc_lookup_v1_RouteLookupConfig_getmsgdef(upb_DefPool *s) { + _upb_DefPool_LoadDefInit(s, &src_proto_grpc_lookup_v1_rls_config_proto_upbdefinit); + return upb_DefPool_FindMessageByName(s, "grpc.lookup.v1.RouteLookupConfig"); +} + +UPB_INLINE const upb_MessageDef *grpc_lookup_v1_RouteLookupClusterSpecifier_getmsgdef(upb_DefPool *s) { + _upb_DefPool_LoadDefInit(s, &src_proto_grpc_lookup_v1_rls_config_proto_upbdefinit); + return upb_DefPool_FindMessageByName(s, "grpc.lookup.v1.RouteLookupClusterSpecifier"); +} + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#include "upb/port_undef.inc" + +#endif /* SRC_PROTO_GRPC_LOOKUP_V1_RLS_CONFIG_PROTO_UPBDEFS_H_ */ diff --git a/src/core/ext/xds/xds_client.cc b/src/core/ext/xds/xds_client.cc index 400f7fbf5d7..ae246b44a74 100644 --- a/src/core/ext/xds/xds_client.cc +++ b/src/core/ext/xds/xds_client.cc @@ -38,6 +38,7 @@ #include "src/core/ext/xds/xds_channel_args.h" #include "src/core/ext/xds/xds_client_stats.h" #include "src/core/ext/xds/xds_cluster.h" +#include "src/core/ext/xds/xds_cluster_specifier_plugin.h" #include "src/core/ext/xds/xds_endpoint.h" #include "src/core/ext/xds/xds_http_filters.h" #include "src/core/ext/xds/xds_listener.h" @@ -2333,6 +2334,7 @@ std::string XdsClient::DumpClientConfigBinary() { void XdsClientGlobalInit() { g_mu = new Mutex; XdsHttpFilterRegistry::Init(); + XdsClusterSpecifierPluginRegistry::Init(); } // TODO(roth): Find a better way to clear the fallback config that does @@ -2343,6 +2345,7 @@ void XdsClientGlobalShutdown() ABSL_NO_THREAD_SAFETY_ANALYSIS { delete g_mu; g_mu = nullptr; XdsHttpFilterRegistry::Shutdown(); + XdsClusterSpecifierPluginRegistry::Shutdown(); } namespace { diff --git a/src/core/ext/xds/xds_cluster_specifier_plugin.cc b/src/core/ext/xds/xds_cluster_specifier_plugin.cc new file mode 100644 index 00000000000..de3f6934f06 --- /dev/null +++ b/src/core/ext/xds/xds_cluster_specifier_plugin.cc @@ -0,0 +1,144 @@ +// +// 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_cluster_specifier_plugin.h" + +#include "absl/strings/str_format.h" +#include "envoy/extensions/filters/http/router/v3/router.upb.h" +#include "envoy/extensions/filters/http/router/v3/router.upbdefs.h" +#include "google/protobuf/duration.upb.h" +#include "upb/json_encode.h" + +#include "src/core/ext/filters/client_channel/lb_policy_registry.h" +#include "src/core/ext/xds/upb_utils.h" +#include "src/proto/grpc/lookup/v1/rls_config.upb.h" +#include "src/proto/grpc/lookup/v1/rls_config.upbdefs.h" + +namespace grpc_core { + +const char* kXdsRouteLookupClusterSpecifierPluginConfigName = + "grpc.lookup.v1.RouteLookupClusterSpecifier"; + +void XdsRouteLookupClusterSpecifierPlugin::PopulateSymtab( + upb_DefPool* symtab) const { + grpc_lookup_v1_RouteLookupConfig_getmsgdef(symtab); +} + +absl::StatusOr +XdsRouteLookupClusterSpecifierPlugin::GenerateLoadBalancingPolicyConfig( + upb_StringView serialized_plugin_config, upb_Arena* arena, + upb_DefPool* symtab) const { + const auto* specifier = grpc_lookup_v1_RouteLookupClusterSpecifier_parse( + serialized_plugin_config.data, serialized_plugin_config.size, arena); + if (specifier == nullptr) { + return absl::InvalidArgumentError("Could not parse plugin config"); + } + const auto* plugin_config = + grpc_lookup_v1_RouteLookupClusterSpecifier_route_lookup_config(specifier); + if (plugin_config == nullptr) { + return absl::InvalidArgumentError( + "Could not get route lookup config from route lookup cluster " + "specifier"); + } + upb::Status status; + const upb_MessageDef* msg_type = + grpc_lookup_v1_RouteLookupConfig_getmsgdef(symtab); + size_t json_size = upb_JsonEncode(plugin_config, msg_type, symtab, 0, nullptr, + 0, status.ptr()); + if (json_size == static_cast(-1)) { + return absl::InvalidArgumentError( + absl::StrCat("failed to dump proto to JSON: ", + upb_Status_ErrorMessage(status.ptr()))); + } + void* buf = upb_Arena_Malloc(arena, json_size + 1); + upb_JsonEncode(plugin_config, msg_type, symtab, 0, + reinterpret_cast(buf), json_size + 1, status.ptr()); + Json::Object rls_policy; + grpc_error_handle error = GRPC_ERROR_NONE; + rls_policy["routeLookupConfig"] = + Json::Parse(reinterpret_cast(buf), &error); + GPR_ASSERT(error == GRPC_ERROR_NONE); + Json::Object cds_policy; + cds_policy["cds_experimental"] = Json::Object(); + Json::Array child_policy; + child_policy.emplace_back(std::move(cds_policy)); + rls_policy["childPolicy"] = std::move(child_policy); + rls_policy["childPolicyConfigTargetFieldName"] = "cluster"; + Json::Object policy; + policy["rls_experimental"] = std::move(rls_policy); + Json::Array policies; + policies.emplace_back(std::move(policy)); + return Json(policies); +} + +namespace { + +using PluginRegistryMap = + std::map>; + +PluginRegistryMap* g_plugin_registry = nullptr; + +} // namespace + +void XdsClusterSpecifierPluginRegistry::PopulateSymtab(upb_DefPool* symtab) { + for (const auto& p : *g_plugin_registry) { + p.second->PopulateSymtab(symtab); + } +} + +void XdsClusterSpecifierPluginRegistry::RegisterPlugin( + std::unique_ptr plugin, + absl::string_view config_proto_type_name) { + (*g_plugin_registry)[config_proto_type_name] = std::move(plugin); +} + +absl::StatusOr +XdsClusterSpecifierPluginRegistry::GenerateLoadBalancingPolicyConfig( + absl::string_view proto_type_name, upb_StringView serialized_plugin_config, + upb_Arena* arena, upb_DefPool* symtab) { + auto it = g_plugin_registry->find(proto_type_name); + if (it == g_plugin_registry->end()) { + return absl::InvalidArgumentError( + "Unable to locate the cluster specifier plugin in the registry"); + } + auto lb_policy_config = it->second->GenerateLoadBalancingPolicyConfig( + serialized_plugin_config, arena, symtab); + if (!lb_policy_config.ok()) return lb_policy_config.status(); + grpc_error_handle parse_error = GRPC_ERROR_NONE; + LoadBalancingPolicyRegistry::ParseLoadBalancingConfig(*lb_policy_config, + &parse_error); + if (parse_error != GRPC_ERROR_NONE) { + absl::Status status = absl::InvalidArgumentError(absl::StrCat( + proto_type_name, + " ClusterSpecifierPlugin returned invalid LB policy config: ", + grpc_error_std_string(parse_error))); + GRPC_ERROR_UNREF(parse_error); + return status; + } + return lb_policy_config->Dump(); +} + +void XdsClusterSpecifierPluginRegistry::Init() { + g_plugin_registry = new PluginRegistryMap; + RegisterPlugin(absl::make_unique(), + kXdsRouteLookupClusterSpecifierPluginConfigName); +} + +void XdsClusterSpecifierPluginRegistry::Shutdown() { delete g_plugin_registry; } + +} // namespace grpc_core diff --git a/src/core/ext/xds/xds_cluster_specifier_plugin.h b/src/core/ext/xds/xds_cluster_specifier_plugin.h new file mode 100644 index 00000000000..1d688cfc02e --- /dev/null +++ b/src/core/ext/xds/xds_cluster_specifier_plugin.h @@ -0,0 +1,81 @@ +// +// 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_CLUSTER_SPECIFIER_PLUGIN_H +#define GRPC_CORE_EXT_XDS_XDS_CLUSTER_SPECIFIER_PLUGIN_H + +#include + +#include +#include +#include + +#include "absl/status/statusor.h" +#include "absl/strings/str_cat.h" +#include "absl/strings/string_view.h" +#include "google/protobuf/any.upb.h" +#include "upb/def.h" + +#include + +#include "src/core/lib/channel/channel_stack.h" +#include "src/core/lib/json/json.h" + +namespace grpc_core { + +class XdsClusterSpecifierPluginImpl { + public: + virtual ~XdsClusterSpecifierPluginImpl() = default; + + // Loads the proto message into the upb symtab. + virtual void PopulateSymtab(upb_DefPool* symtab) const = 0; + + // Returns the LB policy config in JSON form. + virtual absl::StatusOr GenerateLoadBalancingPolicyConfig( + upb_StringView serialized_plugin_config, upb_Arena* arena, + upb_DefPool* symtab) const = 0; +}; + +class XdsRouteLookupClusterSpecifierPlugin + : public XdsClusterSpecifierPluginImpl { + void PopulateSymtab(upb_DefPool* symtab) const override; + + absl::StatusOr GenerateLoadBalancingPolicyConfig( + upb_StringView serialized_plugin_config, upb_Arena* arena, + upb_DefPool* symtab) const override; +}; + +class XdsClusterSpecifierPluginRegistry { + public: + static void RegisterPlugin( + std::unique_ptr plugin, + absl::string_view config_proto_type_name); + + static void PopulateSymtab(upb_DefPool* symtab); + + static absl::StatusOr GenerateLoadBalancingPolicyConfig( + absl::string_view proto_type_name, + upb_StringView serialized_plugin_config, upb_Arena* arena, + upb_DefPool* symtab); + + // Global init and shutdown. + static void Init(); + static void Shutdown(); +}; + +} // namespace grpc_core + +#endif // GRPC_CORE_EXT_XDS_XDS_CLUSTER_SPECIFIER_PLUGIN_H diff --git a/src/core/ext/xds/xds_common_types.cc b/src/core/ext/xds/xds_common_types.cc index bfa0ecad173..37083181321 100644 --- a/src/core/ext/xds/xds_common_types.cc +++ b/src/core/ext/xds/xds_common_types.cc @@ -365,23 +365,23 @@ grpc_error_handle CommonTlsContext::Parse( &errors); } -grpc_error_handle ExtractHttpFilterTypeName(const XdsEncodingContext& context, - const google_protobuf_Any* any, - absl::string_view* filter_type) { - *filter_type = UpbStringToAbsl(google_protobuf_Any_type_url(any)); - if (*filter_type == "type.googleapis.com/xds.type.v3.TypedStruct" || - *filter_type == "type.googleapis.com/udpa.type.v1.TypedStruct") { +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") { upb_StringView any_value = google_protobuf_Any_value(any); const auto* 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( - "could not parse TypedStruct from filter config"); + "could not parse TypedStruct from extension"); } - *filter_type = + *extension_type = UpbStringToAbsl(xds_type_v3_TypedStruct_type_url(typed_struct)); } - *filter_type = absl::StripPrefix(*filter_type, "type.googleapis.com/"); + *extension_type = absl::StripPrefix(*extension_type, "type.googleapis.com/"); return GRPC_ERROR_NONE; } diff --git a/src/core/ext/xds/xds_common_types.h b/src/core/ext/xds/xds_common_types.h index df96e8c93ff..c5e118bd828 100644 --- a/src/core/ext/xds/xds_common_types.h +++ b/src/core/ext/xds/xds_common_types.h @@ -86,9 +86,9 @@ struct CommonTlsContext { CommonTlsContext* common_tls_context); }; -grpc_error_handle ExtractHttpFilterTypeName(const XdsEncodingContext& context, - const google_protobuf_Any* any, - absl::string_view* filter_type); +grpc_error_handle ExtractExtensionTypeName(const XdsEncodingContext& context, + const google_protobuf_Any* any, + absl::string_view* extension_type); } // namespace grpc_core diff --git a/src/core/ext/xds/xds_listener.cc b/src/core/ext/xds/xds_listener.cc index 24cde3609fe..14847e31d19 100644 --- a/src/core/ext/xds/xds_listener.cc +++ b/src/core/ext/xds/xds_listener.cc @@ -332,7 +332,7 @@ grpc_error_handle HttpConnectionManagerParse( } absl::string_view filter_type; grpc_error_handle error = - ExtractHttpFilterTypeName(context, any, &filter_type); + ExtractExtensionTypeName(context, any, &filter_type); if (error != GRPC_ERROR_NONE) return error; const XdsHttpFilterImpl* filter_impl = XdsHttpFilterRegistry::GetFilterForType(filter_type); diff --git a/src/core/ext/xds/xds_route_config.cc b/src/core/ext/xds/xds_route_config.cc index c894ad6800d..6720c90a2bc 100644 --- a/src/core/ext/xds/xds_route_config.cc +++ b/src/core/ext/xds/xds_route_config.cc @@ -23,6 +23,7 @@ #include "absl/strings/str_split.h" #include "absl/strings/string_view.h" #include "envoy/config/core/v3/base.upb.h" +#include "envoy/config/core/v3/extension.upb.h" #include "envoy/config/route/v3/route.upb.h" #include "envoy/config/route/v3/route.upbdefs.h" #include "envoy/config/route/v3/route_components.upb.h" @@ -39,12 +40,14 @@ #include "src/core/ext/xds/upb_utils.h" #include "src/core/ext/xds/xds_api.h" +#include "src/core/ext/xds/xds_cluster_specifier_plugin.h" #include "src/core/ext/xds/xds_common_types.h" #include "src/core/ext/xds/xds_resource_type.h" #include "src/core/ext/xds/xds_routing.h" #include "src/core/lib/gpr/env.h" #include "src/core/lib/gpr/string.h" #include "src/core/lib/iomgr/error.h" +#include "src/core/lib/transport/error_utils.h" namespace grpc_core { @@ -57,6 +60,15 @@ bool XdsRbacEnabled() { return parse_succeeded && parsed_value; } +// TODO(donnadionne): Remove once RLS is no longer experimental +bool XdsRlsEnabled() { + char* value = gpr_getenv("GRPC_EXPERIMENTAL_XDS_RLS_LB"); + bool parsed_value; + bool parse_succeeded = gpr_parse_bool_value(value, &parsed_value); + gpr_free(value); + return parse_succeeded && parsed_value; +} + // // XdsRouteConfigResource::RetryPolicy // @@ -212,11 +224,18 @@ std::string XdsRouteConfigResource::Route::RouteAction::ToString() const { if (retry_policy.has_value()) { contents.push_back(absl::StrCat("retry_policy=", retry_policy->ToString())); } - if (!cluster_name.empty()) { - contents.push_back(absl::StrFormat("Cluster name: %s", cluster_name)); - } - for (const ClusterWeight& cluster_weight : weighted_clusters) { - contents.push_back(cluster_weight.ToString()); + if (action.index() == kClusterIndex) { + contents.push_back( + absl::StrFormat("Cluster name: %s", absl::get(action))); + } else if (action.index() == kWeightedClustersIndex) { + auto& action_weighted_clusters = absl::get(action); + for (const ClusterWeight& cluster_weight : action_weighted_clusters) { + contents.push_back(cluster_weight.ToString()); + } + } else if (action.index() == kClusterSpecifierPluginIndex) { + contents.push_back( + absl::StrFormat("Cluster specifier plugin name: %s", + absl::get(action))); } if (max_stream_duration.has_value()) { contents.push_back(max_stream_duration->ToString()); @@ -258,35 +277,78 @@ std::string XdsRouteConfigResource::Route::ToString() const { // std::string XdsRouteConfigResource::ToString() const { - std::vector vhosts; + std::vector parts; for (const VirtualHost& vhost : virtual_hosts) { - vhosts.push_back( + parts.push_back( absl::StrCat("vhost={\n" " domains=[", absl::StrJoin(vhost.domains, ", "), "]\n" " routes=[\n")); for (const XdsRouteConfigResource::Route& route : vhost.routes) { - vhosts.push_back(" {\n"); - vhosts.push_back(route.ToString()); - vhosts.push_back("\n }\n"); + parts.push_back(" {\n"); + parts.push_back(route.ToString()); + parts.push_back("\n }\n"); } - vhosts.push_back(" ]\n"); - vhosts.push_back(" typed_per_filter_config={\n"); + parts.push_back(" ]\n"); + parts.push_back(" typed_per_filter_config={\n"); for (const auto& p : vhost.typed_per_filter_config) { const std::string& name = p.first; const auto& config = p.second; - vhosts.push_back( - absl::StrCat(" ", name, "=", config.ToString(), "\n")); + parts.push_back(absl::StrCat(" ", name, "=", config.ToString(), "\n")); } - vhosts.push_back(" }\n"); - vhosts.push_back("]\n"); + parts.push_back(" }\n"); + parts.push_back("]\n"); } - return absl::StrJoin(vhosts, ""); + parts.push_back("cluster_specifier_plugins={\n"); + for (const auto& it : cluster_specifier_plugin_map) { + parts.push_back(absl::StrFormat("%s={%s}\n", it.first, it.second)); + } + parts.push_back("}"); + return absl::StrJoin(parts, ""); } namespace { +grpc_error_handle ClusterSpecifierPluginParse( + const XdsEncodingContext& context, + const envoy_config_route_v3_RouteConfiguration* route_config, + XdsRouteConfigResource* rds_update) { + size_t num_cluster_specifier_plugins; + const envoy_config_route_v3_ClusterSpecifierPlugin* const* + cluster_specifier_plugin = + envoy_config_route_v3_RouteConfiguration_cluster_specifier_plugins( + route_config, &num_cluster_specifier_plugins); + for (size_t i = 0; i < num_cluster_specifier_plugins; ++i) { + const envoy_config_core_v3_TypedExtensionConfig* extension = + envoy_config_route_v3_ClusterSpecifierPlugin_extension( + cluster_specifier_plugin[i]); + std::string name = UpbStringToStdString( + envoy_config_core_v3_TypedExtensionConfig_name(extension)); + const google_protobuf_Any* any = + envoy_config_core_v3_TypedExtensionConfig_typed_config(extension); + if (any == nullptr) { + 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; + // Find the plugin and generate the policy. + auto lb_policy_config = + XdsClusterSpecifierPluginRegistry::GenerateLoadBalancingPolicyConfig( + plugin_type, google_protobuf_Any_value(any), context.arena, + context.symtab); + if (!lb_policy_config.ok()) { + return absl_status_to_grpc_error(lb_policy_config.status()); + } + rds_update->cluster_specifier_plugin_map[std::move(name)] = + std::move(lb_policy_config.value()); + } + return GRPC_ERROR_NONE; +} + grpc_error_handle RoutePathMatchParse( const envoy_config_route_v3_RouteMatch* match, XdsRouteConfigResource::Route* route, bool* ignore_route) { @@ -523,7 +585,7 @@ grpc_error_handle ParseTypedPerFilterConfig( } } grpc_error_handle error = - ExtractHttpFilterTypeName(context, any, &filter_type); + ExtractExtensionTypeName(context, any, &filter_type); if (error != GRPC_ERROR_NONE) return error; const XdsHttpFilterImpl* filter_impl = XdsHttpFilterRegistry::GetFilterForType(filter_type); @@ -623,19 +685,27 @@ grpc_error_handle RetryPolicyParse( grpc_error_handle RouteActionParse( const XdsEncodingContext& context, const envoy_config_route_v3_Route* route_msg, + const std::map& + cluster_specifier_plugin_map, XdsRouteConfigResource::Route::RouteAction* route, bool* ignore_route) { const envoy_config_route_v3_RouteAction* route_action = envoy_config_route_v3_Route_route(route_msg); // Get the cluster or weighted_clusters in the RouteAction. if (envoy_config_route_v3_RouteAction_has_cluster(route_action)) { - route->cluster_name = UpbStringToStdString( + std::string cluster_name = UpbStringToStdString( envoy_config_route_v3_RouteAction_cluster(route_action)); - if (route->cluster_name.empty()) { + if (cluster_name.empty()) { return GRPC_ERROR_CREATE_FROM_STATIC_STRING( "RouteAction cluster contains empty cluster name."); } + route->action + .emplace( + std::move(cluster_name)); } else if (envoy_config_route_v3_RouteAction_has_weighted_clusters( route_action)) { + std::vector + action_weighted_clusters; const envoy_config_route_v3_WeightedCluster* weighted_cluster = envoy_config_route_v3_RouteAction_weighted_clusters(route_action); uint32_t total_weight = 100; @@ -682,18 +752,39 @@ grpc_error_handle RouteActionParse( &cluster.typed_per_filter_config); if (error != GRPC_ERROR_NONE) return error; } - route->weighted_clusters.emplace_back(std::move(cluster)); + action_weighted_clusters.emplace_back(std::move(cluster)); } if (total_weight != sum_of_weights) { return GRPC_ERROR_CREATE_FROM_STATIC_STRING( "RouteAction weighted_cluster has incorrect total weight"); } - if (route->weighted_clusters.empty()) { + if (action_weighted_clusters.empty()) { return GRPC_ERROR_CREATE_FROM_STATIC_STRING( "RouteAction weighted_cluster has no valid clusters specified."); } + route->action = std::move(action_weighted_clusters); + } else if (XdsRlsEnabled() && + envoy_config_route_v3_RouteAction_has_cluster_specifier_plugin( + route_action)) { + std::string plugin_name = UpbStringToStdString( + envoy_config_route_v3_RouteAction_cluster_specifier_plugin( + route_action)); + if (plugin_name.empty()) { + return GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "RouteAction cluster contains empty cluster specifier plugin name."); + } + if (cluster_specifier_plugin_map.find(plugin_name) == + cluster_specifier_plugin_map.end()) { + return GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "RouteAction cluster contains cluster specifier plugin name not " + "configured."); + } + route->action.emplace( + std::move(plugin_name)); } else { - // No cluster or weighted_clusters found in RouteAction, ignore this route. + // No cluster or weighted_clusters or plugin found in RouteAction, ignore + // this route. *ignore_route = true; } if (!*ignore_route) { @@ -808,6 +899,12 @@ grpc_error_handle XdsRouteConfigResource::Parse( const XdsEncodingContext& context, const envoy_config_route_v3_RouteConfiguration* route_config, XdsRouteConfigResource* rds_update) { + // Get the cluster spcifier plugins + if (XdsRlsEnabled()) { + grpc_error_handle error = + ClusterSpecifierPluginParse(context, route_config, rds_update); + if (error != GRPC_ERROR_NONE) return error; + } // Get the virtual hosts. size_t num_virtual_hosts; const envoy_config_route_v3_VirtualHost* const* virtual_hosts = @@ -862,6 +959,12 @@ grpc_error_handle XdsRouteConfigResource::Parse( return GRPC_ERROR_CREATE_FROM_STATIC_STRING( "No route found in the virtual host."); } + // Build a set of cluster_specifier_plugin configured to make sure each is + // actually referenced by a route action. + std::set cluster_specifier_plugins; + for (auto& plugin : rds_update->cluster_specifier_plugin_map) { + cluster_specifier_plugins.emplace(plugin.first); + } // Loop over the whole list of routes for (size_t j = 0; j < num_routes; ++j) { const envoy_config_route_v3_RouteMatch* match = @@ -889,14 +992,23 @@ grpc_error_handle XdsRouteConfigResource::Parse( route.action.emplace(); auto& route_action = absl::get(route.action); - error = - RouteActionParse(context, routes[j], &route_action, &ignore_route); + error = RouteActionParse(context, routes[j], + rds_update->cluster_specifier_plugin_map, + &route_action, &ignore_route); if (error != GRPC_ERROR_NONE) return error; if (ignore_route) continue; if (route_action.retry_policy == absl::nullopt && retry_policy != nullptr) { route_action.retry_policy = virtual_host_retry_policy; } + // Mark off plugins used in route action. + std::string* cluster_specifier_action = + absl::get_if( + &route_action.action); + if (cluster_specifier_action != nullptr) { + cluster_specifier_plugins.erase(*cluster_specifier_action); + } } else if (envoy_config_route_v3_Route_has_non_forwarding_action( routes[j])) { route.action @@ -918,6 +1030,12 @@ grpc_error_handle XdsRouteConfigResource::Parse( if (vhost.routes.empty()) { return GRPC_ERROR_CREATE_FROM_STATIC_STRING("No valid routes specified."); } + // For plugins not used in route action, delete from the update to prevent + // further use. + for (auto& unused_plugin : cluster_specifier_plugins) { + rds_update->cluster_specifier_plugin_map.erase( + std::string(unused_plugin)); + } } return GRPC_ERROR_NONE; } diff --git a/src/core/ext/xds/xds_route_config.h b/src/core/ext/xds/xds_route_config.h index 08803a09815..dd719b0c86c 100644 --- a/src/core/ext/xds/xds_route_config.h +++ b/src/core/ext/xds/xds_route_config.h @@ -30,6 +30,7 @@ #include "re2/re2.h" #include "src/core/ext/xds/xds_client.h" +#include "src/core/ext/xds/xds_cluster_specifier_plugin.h" #include "src/core/ext/xds/xds_common_types.h" #include "src/core/ext/xds/xds_http_filters.h" #include "src/core/ext/xds/xds_resource_type_impl.h" @@ -67,8 +68,6 @@ struct XdsRouteConfigResource { std::string ToString() const; }; - // TODO(donnadionne): When we can use absl::variant<>, consider using that - // for: PathMatcher, HeaderMatcher, cluster_name and weighted_clusters struct Route { // Matchers for this route. struct Matchers { @@ -130,10 +129,11 @@ struct XdsRouteConfigResource { absl::optional retry_policy; // Action for this route. - // TODO(roth): When we can use absl::variant<>, consider using that - // here, to enforce the fact that only one of the two fields can be set. - std::string cluster_name; - std::vector weighted_clusters; + static constexpr size_t kClusterIndex = 0; + static constexpr size_t kWeightedClustersIndex = 1; + static constexpr size_t kClusterSpecifierPluginIndex = 2; + absl::variant, std::string> + action; // Storing the timeout duration from route action: // RouteAction.max_stream_duration.grpc_timeout_header_max or // RouteAction.max_stream_duration.max_stream_duration if the former is @@ -142,9 +142,7 @@ struct XdsRouteConfigResource { bool operator==(const RouteAction& other) const { return hash_policies == other.hash_policies && - retry_policy == other.retry_policy && - cluster_name == other.cluster_name && - weighted_clusters == other.weighted_clusters && + retry_policy == other.retry_policy && action == other.action && max_stream_duration == other.max_stream_duration; } std::string ToString() const; @@ -178,9 +176,13 @@ struct XdsRouteConfigResource { }; std::vector virtual_hosts; + std::map + cluster_specifier_plugin_map; bool operator==(const XdsRouteConfigResource& other) const { - return virtual_hosts == other.virtual_hosts; + return virtual_hosts == other.virtual_hosts && + cluster_specifier_plugin_map == other.cluster_specifier_plugin_map; } std::string ToString() const; @@ -207,6 +209,7 @@ class XdsRouteConfigResourceType void InitUpbSymtab(upb_DefPool* symtab) const override { envoy_config_route_v3_RouteConfiguration_getmsgdef(symtab); + XdsClusterSpecifierPluginRegistry::PopulateSymtab(symtab); } }; diff --git a/src/core/lib/channel/call_tracer.h b/src/core/lib/channel/call_tracer.h index 577104ab012..403ea7c5bdd 100644 --- a/src/core/lib/channel/call_tracer.h +++ b/src/core/lib/channel/call_tracer.h @@ -59,9 +59,12 @@ class CallTracer { virtual void RecordReceivedInitialMetadata( grpc_metadata_batch* recv_initial_metadata, uint32_t flags) = 0; virtual void RecordReceivedMessage(const ByteStream& recv_message) = 0; + // If the call was cancelled before the recv_trailing_metadata op + // was started, recv_trailing_metadata and transport_stream_stats + // will be null. virtual void RecordReceivedTrailingMetadata( absl::Status status, grpc_metadata_batch* recv_trailing_metadata, - const grpc_transport_stream_stats& transport_stream_stats) = 0; + const grpc_transport_stream_stats* transport_stream_stats) = 0; virtual void RecordCancel(grpc_error_handle cancel_error) = 0; // Should be the last API call to the object. Once invoked, the tracer // library is free to destroy the object. diff --git a/src/core/lib/channel/promise_based_filter.cc b/src/core/lib/channel/promise_based_filter.cc index 480d085344d..bc6ba573abf 100644 --- a/src/core/lib/channel/promise_based_filter.cc +++ b/src/core/lib/channel/promise_based_filter.cc @@ -79,6 +79,8 @@ struct ClientCallData::RecvInitialMetadata final { kInitial, // No op seen, but we have a latch that would like to modify it when we do kGotLatch, + // Responded to trailing metadata prior to getting a recv_initial_metadata + kRespondedToTrailingMetadataPriorToHook, // Hooked, no latch yet kHookedWaitingForLatch, // Hooked, latch seen @@ -123,6 +125,7 @@ class ClientCallData::PollContext { case RecvInitialMetadata::kHookedAndGotLatch: case RecvInitialMetadata::kCompleteWaitingForLatch: case RecvInitialMetadata::kResponded: + case RecvInitialMetadata::kRespondedToTrailingMetadataPriorToHook: break; case RecvInitialMetadata::kCompleteAndGotLatch: self_->recv_initial_metadata_->state = @@ -172,6 +175,34 @@ class ClientCallData::PollContext { absl::exchange(self_->original_recv_trailing_metadata_ready_, nullptr), GRPC_ERROR_NONE, "wake_inside_combiner:recv_trailing_ready:1"); + if (self_->recv_initial_metadata_ != nullptr) { + switch (self_->recv_initial_metadata_->state) { + case RecvInitialMetadata::kInitial: + case RecvInitialMetadata::kGotLatch: + self_->recv_initial_metadata_->state = RecvInitialMetadata:: + kRespondedToTrailingMetadataPriorToHook; + break; + case RecvInitialMetadata:: + kRespondedToTrailingMetadataPriorToHook: + abort(); // not reachable + break; + case RecvInitialMetadata::kHookedWaitingForLatch: + case RecvInitialMetadata::kHookedAndGotLatch: + case RecvInitialMetadata::kResponded: + case RecvInitialMetadata::kCompleteAndGotLatch: + case RecvInitialMetadata::kCompleteAndSetLatch: + break; + case RecvInitialMetadata::kCompleteWaitingForLatch: + self_->recv_initial_metadata_->state = + RecvInitialMetadata::kResponded; + call_closures_.Add( + absl::exchange( + self_->recv_initial_metadata_->original_on_ready, + nullptr), + GRPC_ERROR_CANCELLED, + "wake_inside_combiner:recv_initial_metadata_ready"); + } + } } else { GPR_ASSERT(*md->get_pointer(GrpcStatusMetadata()) != GRPC_STATUS_OK); @@ -190,10 +221,17 @@ class ClientCallData::PollContext { switch (self_->recv_initial_metadata_->state) { case RecvInitialMetadata::kInitial: case RecvInitialMetadata::kGotLatch: + self_->recv_initial_metadata_->state = RecvInitialMetadata:: + kRespondedToTrailingMetadataPriorToHook; + break; case RecvInitialMetadata::kHookedWaitingForLatch: case RecvInitialMetadata::kHookedAndGotLatch: case RecvInitialMetadata::kResponded: break; + case RecvInitialMetadata:: + kRespondedToTrailingMetadataPriorToHook: + abort(); // not reachable + break; case RecvInitialMetadata::kCompleteWaitingForLatch: case RecvInitialMetadata::kCompleteAndGotLatch: case RecvInitialMetadata::kCompleteAndSetLatch: @@ -372,6 +410,7 @@ void ClientCallData::StartBatch(grpc_transport_stream_op_batch* batch) { } if (recv_initial_metadata_ != nullptr && batch->recv_initial_metadata) { + bool hook = true; switch (recv_initial_metadata_->state) { case RecvInitialMetadata::kInitial: recv_initial_metadata_->state = @@ -380,6 +419,9 @@ void ClientCallData::StartBatch(grpc_transport_stream_op_batch* batch) { case RecvInitialMetadata::kGotLatch: recv_initial_metadata_->state = RecvInitialMetadata::kHookedAndGotLatch; break; + case RecvInitialMetadata::kRespondedToTrailingMetadataPriorToHook: + hook = false; + break; case RecvInitialMetadata::kHookedWaitingForLatch: case RecvInitialMetadata::kHookedAndGotLatch: case RecvInitialMetadata::kCompleteWaitingForLatch: @@ -388,17 +430,19 @@ void ClientCallData::StartBatch(grpc_transport_stream_op_batch* batch) { case RecvInitialMetadata::kResponded: abort(); // unreachable } - auto cb = [](void* ptr, grpc_error_handle error) { - ClientCallData* self = static_cast(ptr); - self->RecvInitialMetadataReady(error); - }; - recv_initial_metadata_->metadata = - batch->payload->recv_initial_metadata.recv_initial_metadata; - recv_initial_metadata_->original_on_ready = - batch->payload->recv_initial_metadata.recv_initial_metadata_ready; - GRPC_CLOSURE_INIT(&recv_initial_metadata_->on_ready, cb, this, nullptr); - batch->payload->recv_initial_metadata.recv_initial_metadata_ready = - &recv_initial_metadata_->on_ready; + if (hook) { + auto cb = [](void* ptr, grpc_error_handle error) { + ClientCallData* self = static_cast(ptr); + self->RecvInitialMetadataReady(error); + }; + recv_initial_metadata_->metadata = + batch->payload->recv_initial_metadata.recv_initial_metadata; + recv_initial_metadata_->original_on_ready = + batch->payload->recv_initial_metadata.recv_initial_metadata_ready; + GRPC_CLOSURE_INIT(&recv_initial_metadata_->on_ready, cb, this, nullptr); + batch->payload->recv_initial_metadata.recv_initial_metadata_ready = + &recv_initial_metadata_->on_ready; + } } // send_initial_metadata: seeing this triggers the start of the promise part @@ -490,6 +534,7 @@ void ClientCallData::Cancel(grpc_error_handle error) { break; case RecvInitialMetadata::kInitial: case RecvInitialMetadata::kGotLatch: + case RecvInitialMetadata::kRespondedToTrailingMetadataPriorToHook: case RecvInitialMetadata::kHookedWaitingForLatch: case RecvInitialMetadata::kHookedAndGotLatch: case RecvInitialMetadata::kResponded: @@ -532,6 +577,7 @@ void ClientCallData::RecvInitialMetadataReady(grpc_error_handle error) { case RecvInitialMetadata::kCompleteAndGotLatch: case RecvInitialMetadata::kCompleteAndSetLatch: case RecvInitialMetadata::kResponded: + case RecvInitialMetadata::kRespondedToTrailingMetadataPriorToHook: abort(); // unreachable } if (error != GRPC_ERROR_NONE) { @@ -600,6 +646,7 @@ ArenaPromise ClientCallData::MakeNextPromise( case RecvInitialMetadata::kCompleteAndGotLatch: case RecvInitialMetadata::kCompleteAndSetLatch: case RecvInitialMetadata::kResponded: + case RecvInitialMetadata::kRespondedToTrailingMetadataPriorToHook: abort(); // unreachable } } else { @@ -659,9 +706,13 @@ void ClientCallData::RecvTrailingMetadataReadyCallback( } void ClientCallData::RecvTrailingMetadataReady(grpc_error_handle error) { + // If we were cancelled prior to receiving this callback, we should simply + // forward the callback up with the same error. if (recv_trailing_state_ == RecvTrailingState::kCancelled) { - Closure::Run(DEBUG_LOCATION, original_recv_trailing_metadata_ready_, - GRPC_ERROR_REF(cancelled_error_)); + if (grpc_closure* call_closure = + absl::exchange(original_recv_trailing_metadata_ready_, nullptr)) { + Closure::Run(DEBUG_LOCATION, call_closure, GRPC_ERROR_REF(error)); + } return; } // If there was an error, we'll put that into the trailing metadata and diff --git a/src/core/lib/iomgr/tcp_client_posix.cc b/src/core/lib/iomgr/tcp_client_posix.cc index f146fdec7f7..92e9c70dfd5 100644 --- a/src/core/lib/iomgr/tcp_client_posix.cc +++ b/src/core/lib/iomgr/tcp_client_posix.cc @@ -136,6 +136,7 @@ static void on_writable(void* acp, grpc_error_handle error) { int done; grpc_endpoint** ep = ac->ep; grpc_closure* closure = ac->closure; + std::string addr_str = ac->addr_str; grpc_fd* fd; (void)GRPC_ERROR_REF(error); @@ -221,8 +222,7 @@ finish: std::string description = absl::StrCat("Failed to connect to remote host: ", str); error = grpc_error_set_str(error, GRPC_ERROR_STR_DESCRIPTION, description); - error = - grpc_error_set_str(error, GRPC_ERROR_STR_TARGET_ADDRESS, ac->addr_str); + error = grpc_error_set_str(error, GRPC_ERROR_STR_TARGET_ADDRESS, addr_str); } if (done) { // This is safe even outside the lock, because "done", the sentinel, is diff --git a/src/core/lib/json/json_util.h b/src/core/lib/json/json_util.h index 29de52d8173..9582ab21f9e 100644 --- a/src/core/lib/json/json_util.h +++ b/src/core/lib/json/json_util.h @@ -45,9 +45,9 @@ bool ExtractJsonNumber(const Json& json, absl::string_view field_name, NumericType* output, std::vector* error_list) { static_assert(std::is_integral::value, "Integral required"); - if (json.type() != Json::Type::NUMBER) { - error_list->push_back(GRPC_ERROR_CREATE_FROM_CPP_STRING( - absl::StrCat("field:", field_name, " error:type should be NUMBER"))); + if (json.type() != Json::Type::NUMBER && json.type() != Json::Type::STRING) { + error_list->push_back(GRPC_ERROR_CREATE_FROM_CPP_STRING(absl::StrCat( + "field:", field_name, " error:type should be NUMBER or STRING"))); return false; } if (!absl::SimpleAtoi(json.string_value(), output)) { diff --git a/src/core/tsi/ssl_transport_security.cc b/src/core/tsi/ssl_transport_security.cc index 2208681e4ea..44352ce977b 100644 --- a/src/core/tsi/ssl_transport_security.cc +++ b/src/core/tsi/ssl_transport_security.cc @@ -1939,8 +1939,16 @@ static void ssl_keylogging_callback(const SSL* ssl, const char* info) { factory->key_logger->LogSessionKeys(ssl_context, info); } +// This callback is invoked when the CRL has been verified and will soft-fail +// errors in verification depending on certain error types. static int verify_cb(int ok, X509_STORE_CTX* ctx) { int cert_error = X509_STORE_CTX_get_error(ctx); + if (cert_error == X509_V_ERR_UNABLE_TO_GET_CRL) { + gpr_log( + GPR_INFO, + "Certificate verification failed to get CRL files. Ignoring error."); + return 1; + } if (cert_error != 0) { gpr_log(GPR_ERROR, "Certificate verify failed with code %d", cert_error); } diff --git a/src/cpp/ext/filters/census/client_filter.cc b/src/cpp/ext/filters/census/client_filter.cc index 16438b3f3cd..618324f523a 100644 --- a/src/cpp/ext/filters/census/client_filter.cc +++ b/src/cpp/ext/filters/census/client_filter.cc @@ -95,7 +95,7 @@ OpenCensusCallTracer::OpenCensusCallAttemptTracer::OpenCensusCallAttemptTracer( void OpenCensusCallTracer::OpenCensusCallAttemptTracer:: RecordSendInitialMetadata(grpc_metadata_batch* send_initial_metadata, - uint32_t /* flags */) { + uint32_t /*flags*/) { char tracing_buf[kMaxTraceContextLen]; size_t tracing_len = TraceContextSerialize(context_.Context(), tracing_buf, kMaxTraceContextLen); @@ -114,12 +114,12 @@ void OpenCensusCallTracer::OpenCensusCallAttemptTracer:: } void OpenCensusCallTracer::OpenCensusCallAttemptTracer::RecordSendMessage( - const grpc_core::ByteStream& /* send_message */) { + const grpc_core::ByteStream& /*send_message*/) { ++sent_message_count_; } void OpenCensusCallTracer::OpenCensusCallAttemptTracer::RecordReceivedMessage( - const grpc_core::ByteStream& /* recv_message */) { + const grpc_core::ByteStream& /*recv_message*/) { ++recv_message_count_; } @@ -140,21 +140,25 @@ void FilterTrailingMetadata(grpc_metadata_batch* b, uint64_t* elapsed_time) { void OpenCensusCallTracer::OpenCensusCallAttemptTracer:: RecordReceivedTrailingMetadata( absl::Status status, grpc_metadata_batch* recv_trailing_metadata, - const grpc_transport_stream_stats& transport_stream_stats) { - FilterTrailingMetadata(recv_trailing_metadata, &elapsed_time_); - const uint64_t request_size = transport_stream_stats.outgoing.data_bytes; - const uint64_t response_size = transport_stream_stats.incoming.data_bytes; + const grpc_transport_stream_stats* transport_stream_stats) { + status_code_ = status.code(); + if (recv_trailing_metadata == nullptr || transport_stream_stats == nullptr) { + return; + } + uint64_t elapsed_time = 0; + FilterTrailingMetadata(recv_trailing_metadata, &elapsed_time); std::vector> tags = context_.tags().tags(); tags.emplace_back(ClientMethodTagKey(), std::string(parent_->method_)); - status_code_ = status.code(); std::string final_status = absl::StatusCodeToString(status_code_); tags.emplace_back(ClientStatusTagKey(), final_status); ::opencensus::stats::Record( - {{RpcClientSentBytesPerRpc(), static_cast(request_size)}, - {RpcClientReceivedBytesPerRpc(), static_cast(response_size)}, + {{RpcClientSentBytesPerRpc(), + static_cast(transport_stream_stats->outgoing.data_bytes)}, + {RpcClientReceivedBytesPerRpc(), + static_cast(transport_stream_stats->incoming.data_bytes)}, {RpcClientServerLatency(), - ToDoubleMilliseconds(absl::Nanoseconds(elapsed_time_))}}, + ToDoubleMilliseconds(absl::Nanoseconds(elapsed_time))}}, tags); } @@ -165,7 +169,7 @@ void OpenCensusCallTracer::OpenCensusCallAttemptTracer::RecordCancel( } void OpenCensusCallTracer::OpenCensusCallAttemptTracer::RecordEnd( - const gpr_timespec& /* latency */) { + const gpr_timespec& /*latency*/) { double latency_ms = absl::ToDoubleMilliseconds(absl::Now() - start_time_); std::vector> tags = context_.tags().tags(); diff --git a/src/cpp/ext/filters/census/open_census_call_tracer.h b/src/cpp/ext/filters/census/open_census_call_tracer.h index 1daea1a2571..d856afbe51e 100644 --- a/src/cpp/ext/filters/census/open_census_call_tracer.h +++ b/src/cpp/ext/filters/census/open_census_call_tracer.h @@ -33,25 +33,23 @@ class OpenCensusCallTracer : public grpc_core::CallTracer { OpenCensusCallAttemptTracer(OpenCensusCallTracer* parent, uint64_t attempt_num, bool is_transparent_retry, bool arena_allocated); - void RecordSendInitialMetadata( - grpc_metadata_batch* /* send_initial_metadata */, - uint32_t /* flags */) override; - void RecordOnDoneSendInitialMetadata(gpr_atm* /* peer_string */) override {} + void RecordSendInitialMetadata(grpc_metadata_batch* send_initial_metadata, + uint32_t /*flags*/) override; + void RecordOnDoneSendInitialMetadata(gpr_atm* /*peer_string*/) override {} void RecordSendTrailingMetadata( - grpc_metadata_batch* /* send_trailing_metadata */) override {} + grpc_metadata_batch* /*send_trailing_metadata*/) override {} void RecordSendMessage( - const grpc_core::ByteStream& /* send_message */) override; + const grpc_core::ByteStream& /*send_message*/) override; void RecordReceivedInitialMetadata( - grpc_metadata_batch* /* recv_initial_metadata */, - uint32_t /* flags */) override {} + grpc_metadata_batch* /*recv_initial_metadata*/, + uint32_t /*flags*/) override {} void RecordReceivedMessage( - const grpc_core::ByteStream& /* recv_message */) override; + const grpc_core::ByteStream& /*recv_message*/) override; void RecordReceivedTrailingMetadata( - absl::Status /* status */, grpc_metadata_batch* recv_trailing_metadata, - const grpc_transport_stream_stats& /* transport_stream_stats */) - override; + absl::Status status, grpc_metadata_batch* recv_trailing_metadata, + const grpc_transport_stream_stats* transport_stream_stats) override; void RecordCancel(grpc_error_handle cancel_error) override; - void RecordEnd(const gpr_timespec& /* latency */) override; + void RecordEnd(const gpr_timespec& /*latency*/) override; CensusContext* context() { return &context_; } @@ -65,8 +63,6 @@ class OpenCensusCallTracer : public grpc_core::CallTracer { CensusContext context_; // Start time (for measuring latency). absl::Time start_time_; - // Server elapsed time in nanoseconds. - uint64_t elapsed_time_ = 0; // Number of messages in this RPC. uint64_t recv_message_count_ = 0; uint64_t sent_message_count_ = 0; diff --git a/src/proto/grpc/lookup/v1/BUILD b/src/proto/grpc/lookup/v1/BUILD index 0701ec0e674..81cf765b56f 100644 --- a/src/proto/grpc/lookup/v1/BUILD +++ b/src/proto/grpc/lookup/v1/BUILD @@ -28,7 +28,21 @@ grpc_proto_library( well_known_protos = True, ) +grpc_proto_library( + name = "rls_config_proto", + srcs = ["rls_config.proto"], + well_known_protos = True, +) + proto_library( name = "rls_proto_descriptor", srcs = ["rls.proto"], ) + +proto_library( + name = "rls_config_proto_descriptor", + srcs = ["rls_config.proto"], + deps = [ + "@com_google_protobuf//:duration_proto", + ], +) diff --git a/src/proto/grpc/testing/xds/v3/BUILD b/src/proto/grpc/testing/xds/v3/BUILD index 2c87a97ea76..fe2ee270bf9 100644 --- a/src/proto/grpc/testing/xds/v3/BUILD +++ b/src/proto/grpc/testing/xds/v3/BUILD @@ -197,6 +197,7 @@ grpc_proto_library( well_known_protos = True, deps = [ "base_proto", + "extension_proto", "percent_proto", "range_proto", "regex_proto", diff --git a/src/proto/grpc/testing/xds/v3/route.proto b/src/proto/grpc/testing/xds/v3/route.proto index 7109fe21db1..02133d8de36 100644 --- a/src/proto/grpc/testing/xds/v3/route.proto +++ b/src/proto/grpc/testing/xds/v3/route.proto @@ -19,6 +19,7 @@ syntax = "proto3"; package envoy.config.route.v3; import "src/proto/grpc/testing/xds/v3/base.proto"; +import "src/proto/grpc/testing/xds/v3/extension.proto"; import "src/proto/grpc/testing/xds/v3/regex.proto"; import "src/proto/grpc/testing/xds/v3/percent.proto"; import "src/proto/grpc/testing/xds/v3/range.proto"; @@ -268,6 +269,13 @@ message RouteAction { // :ref:`traffic splitting ` // for additional documentation. WeightedCluster weighted_clusters = 3; + + // Name of the cluster specifier plugin to use to determine the cluster for + // requests on this route. The plugin name must be defined in the associated + // :ref:`envoy_v3_api_field_config.route.v3.RouteConfiguration.cluster_specifier_plugins` + // in the + // :ref:`envoy_v3_api_field_config.core.v3.TypedExtensionConfig.name` field. + string cluster_specifier_plugin = 37; } message HashPolicy { @@ -435,6 +443,12 @@ message HeaderMatcher { message QueryParameterMatcher { } +// Configuration for a cluster specifier plugin. +message ClusterSpecifierPlugin { + // The name of the plugin and its opaque configuration. + core.v3.TypedExtensionConfig extension = 1; +} + // [#protodoc-title: HTTP route configuration] // * Routing :ref:`architecture overview ` // * HTTP :ref:`router filter ` @@ -449,6 +463,11 @@ message RouteConfiguration { // An array of virtual hosts that make up the route table. repeated VirtualHost virtual_hosts = 2; + + // A list of plugins and their configurations which may be used by a + // :ref:`envoy_v3_api_field_config.route.v3.RouteAction.cluster_specifier_plugin` + // within the route. All *extension.name* fields in this list must be unique. + repeated ClusterSpecifierPlugin cluster_specifier_plugins = 12; } message RedirectAction { diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py index 7305945dc3f..f1d0e689883 100644 --- a/src/python/grpcio/grpc_core_dependencies.py +++ b/src/python/grpcio/grpc_core_dependencies.py @@ -235,6 +235,7 @@ CORE_SOURCE_FILES = [ 'src/core/ext/upb-generated/src/proto/grpc/health/v1/health.upb.c', 'src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c', 'src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls.upb.c', + 'src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls_config.upb.c', 'src/core/ext/upb-generated/udpa/annotations/migrate.upb.c', 'src/core/ext/upb-generated/udpa/annotations/security.upb.c', 'src/core/ext/upb-generated/udpa/annotations/sensitive.upb.c', @@ -369,6 +370,7 @@ CORE_SOURCE_FILES = [ 'src/core/ext/upbdefs-generated/google/protobuf/wrappers.upbdefs.c', 'src/core/ext/upbdefs-generated/google/rpc/status.upbdefs.c', 'src/core/ext/upbdefs-generated/opencensus/proto/trace/v1/trace_config.upbdefs.c', + 'src/core/ext/upbdefs-generated/src/proto/grpc/lookup/v1/rls_config.upbdefs.c', 'src/core/ext/upbdefs-generated/udpa/annotations/migrate.upbdefs.c', 'src/core/ext/upbdefs-generated/udpa/annotations/security.upbdefs.c', 'src/core/ext/upbdefs-generated/udpa/annotations/sensitive.upbdefs.c', @@ -401,6 +403,7 @@ CORE_SOURCE_FILES = [ 'src/core/ext/xds/xds_client.cc', 'src/core/ext/xds/xds_client_stats.cc', 'src/core/ext/xds/xds_cluster.cc', + 'src/core/ext/xds/xds_cluster_specifier_plugin.cc', 'src/core/ext/xds/xds_common_types.cc', 'src/core/ext/xds/xds_endpoint.cc', 'src/core/ext/xds/xds_http_fault_filter.cc', @@ -1171,6 +1174,7 @@ CORE_SOURCE_FILES = [ 'third_party/upb/upb/decode_fast.c', 'third_party/upb/upb/def.c', 'third_party/upb/upb/encode.c', + 'third_party/upb/upb/json_encode.c', 'third_party/upb/upb/msg.c', 'third_party/upb/upb/reflection.c', 'third_party/upb/upb/table.c', diff --git a/src/upb/gen_build_yaml.py b/src/upb/gen_build_yaml.py index d347eb554f4..939d71b3991 100755 --- a/src/upb/gen_build_yaml.py +++ b/src/upb/gen_build_yaml.py @@ -36,6 +36,7 @@ try: "third_party/upb/upb/decode.c", "third_party/upb/upb/def.c", "third_party/upb/upb/encode.c", + "third_party/upb/upb/json_encode.c", "third_party/upb/upb/msg.c", "third_party/upb/upb/reflection.c", "third_party/upb/upb/table.c", @@ -52,6 +53,7 @@ try: "third_party/upb/upb/def.h", "third_party/upb/upb/def.hpp", "third_party/upb/upb/encode.h", + "third_party/upb/upb/json_encode.h", "third_party/upb/upb/msg_internal.h", "third_party/upb/upb/msg.h", "third_party/upb/upb/port_def.inc", diff --git a/templates/doc/bazel_support.md.template b/templates/doc/bazel_support.md.template new file mode 100644 index 00000000000..477bf6a8c91 --- /dev/null +++ b/templates/doc/bazel_support.md.template @@ -0,0 +1,46 @@ +%YAML 1.2 +--- | + # Bazel Support + + ${ '##' } Basic Usage + + The `grpc/grpc` repository's primary build system is Bazel. Rules are provided + for C++, Python, and Objective-C. While C++ supports other build systems such as + CMake, these rules are actually generated from the Bazel definitions. + + Projects built with Bazel may use the `grpc/grpc` repo not only to add a + dependency on the library itself, but also to generate protobuf, stub, and + servicer code. To do so, one must invoke the `grpc_deps` and `grpc_extra_deps` + repository rules in their `WORKSPACE` file: + + ```starlark + workspace(name = "example_workspace") + + load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") + + http_archive( + name = "com_github_grpc_grpc", + strip_prefix = "grpc-1.45.0", + sha256 = "ec19657a677d49af59aa806ec299c070c882986c9fcc022b1c22c2a3caf01bcd"k + urls = ["https://github.com/grpc/grpc/archive/refs/tags/v1.45.0.tar.gz"], + ) + + load("@com_github_grpc_grpc//bazel:grpc_deps.bzl", "grpc_deps") + + grpc_deps() + + load("@com_github_grpc_grpc//bazel:grpc_extra_deps.bzl", "grpc_extra_deps") + + grpc_extra_deps() + ``` + + ${ '##' } Supported Versions + + In general, gRPC supports building with the latest patch release of the most + recent two major versions of Bazel. However individual releases may have a + broader compatibility range. The currently supported versions are captured by + the following list: + + % for version in supported_bazel_versions: + - [`${version}`](https://github.com/bazelbuild/bazel/releases/tag/${version}) + % endfor diff --git a/templates/tools/dockerfile/compile_python_310.include b/templates/tools/dockerfile/compile_python_310.include index 2fd17838fa7..21ff50121dd 100644 --- a/templates/tools/dockerfile/compile_python_310.include +++ b/templates/tools/dockerfile/compile_python_310.include @@ -1,19 +1,19 @@ #================= -# Compile CPython 3.10.2 from source +# Compile CPython 3.10.3 from source RUN apt-get update && apt-get install -y zlib1g-dev libssl-dev && apt-get clean RUN apt-get update && apt-get install -y jq build-essential libffi-dev && apt-get clean RUN cd /tmp && ${'\\'} - wget -q https://www.python.org/ftp/python/3.10.2/Python-3.10.2.tgz && ${'\\'} - tar xzvf Python-3.10.2.tgz && ${'\\'} - cd Python-3.10.2 && ${'\\'} + wget -q https://www.python.org/ftp/python/3.10.3/Python-3.10.3.tgz && ${'\\'} + tar xzvf Python-3.10.3.tgz && ${'\\'} + cd Python-3.10.3 && ${'\\'} ./configure && ${'\\'} make -j4 && ${'\\'} make install RUN cd /tmp && ${'\\'} - echo "67c92270be6701f4a6fed57c4530139b Python-3.10.2.tgz" > checksum.md5 && ${'\\'} + echo "f276ffcd05bccafe46da023d0a5bb04a Python-3.10.3.tgz" > checksum.md5 && ${'\\'} md5sum -c checksum.md5 RUN python3.10 -m ensurepip && ${'\\'} diff --git a/templates/tools/dockerfile/compile_python_36.include b/templates/tools/dockerfile/compile_python_36.include index 47c660a0d6e..b65e030b7fb 100644 --- a/templates/tools/dockerfile/compile_python_36.include +++ b/templates/tools/dockerfile/compile_python_36.include @@ -1,19 +1,19 @@ #================= -# Compile CPython 3.6.9 from source +# Compile CPython 3.6.15 from source RUN apt-get update && apt-get install -y zlib1g-dev libssl-dev && apt-get clean RUN apt-get update && apt-get install -y jq build-essential libffi-dev && apt-get clean RUN cd /tmp && ${'\\'} - wget -q https://www.python.org/ftp/python/3.6.9/Python-3.6.9.tgz && ${'\\'} - tar xzvf Python-3.6.9.tgz && ${'\\'} - cd Python-3.6.9 && ${'\\'} + wget -q https://www.python.org/ftp/python/3.6.15/Python-3.6.15.tgz && ${'\\'} + tar xzvf Python-3.6.15.tgz && ${'\\'} + cd Python-3.6.15 && ${'\\'} ./configure && ${'\\'} make -j4 && ${'\\'} make install RUN cd /tmp && ${'\\'} - echo "ff7cdaef4846c89c1ec0d7b709bbd54d Python-3.6.9.tgz" > checksum.md5 && ${'\\'} + echo "f9e6f91c754a604f4fc6f6c7683723fb Python-3.6.15.tgz" > checksum.md5 && ${'\\'} md5sum -c checksum.md5 RUN python3.6 -m ensurepip && ${'\\'} diff --git a/templates/tools/dockerfile/compile_python_37.include b/templates/tools/dockerfile/compile_python_37.include index ad768640a13..80a72ae65b8 100644 --- a/templates/tools/dockerfile/compile_python_37.include +++ b/templates/tools/dockerfile/compile_python_37.include @@ -1,19 +1,19 @@ #================= -# Compile CPython 3.7.12 from source +# Compile CPython 3.7.13 from source RUN apt-get update && apt-get install -y zlib1g-dev libssl-dev && apt-get clean RUN apt-get update && apt-get install -y jq build-essential libffi-dev && apt-get clean RUN cd /tmp && ${'\\'} - wget -q https://www.python.org/ftp/python/3.7.12/Python-3.7.12.tgz && ${'\\'} - tar xzvf Python-3.7.12.tgz && ${'\\'} - cd Python-3.7.12 && ${'\\'} + wget -q https://www.python.org/ftp/python/3.7.13/Python-3.7.13.tgz && ${'\\'} + tar xzvf Python-3.7.13.tgz && ${'\\'} + cd Python-3.7.13 && ${'\\'} ./configure && ${'\\'} make -j4 && ${'\\'} make install RUN cd /tmp && ${'\\'} - echo "6fe83678c085a7735a943cf1e4d41c14 Python-3.7.12.tgz" > checksum.md5 && ${'\\'} + echo "e0d3321026d4a5f3a3890b5d821ad762 Python-3.7.13.tgz" > checksum.md5 && ${'\\'} md5sum -c checksum.md5 RUN python3.7 -m ensurepip && ${'\\'} diff --git a/templates/tools/dockerfile/compile_python_38.include b/templates/tools/dockerfile/compile_python_38.include index ce880d87a77..9147a95367d 100644 --- a/templates/tools/dockerfile/compile_python_38.include +++ b/templates/tools/dockerfile/compile_python_38.include @@ -1,19 +1,19 @@ #================= -# Compile CPython 3.8.0b4 from source +# Compile CPython 3.8.13 from source RUN apt-get update && apt-get install -y zlib1g-dev libssl-dev && apt-get clean RUN apt-get update && apt-get install -y jq build-essential libffi-dev && apt-get clean RUN cd /tmp && ${'\\'} - wget -q https://www.python.org/ftp/python/3.8.0/Python-3.8.0b4.tgz && ${'\\'} - tar xzvf Python-3.8.0b4.tgz && ${'\\'} - cd Python-3.8.0b4 && ${'\\'} + wget -q https://www.python.org/ftp/python/3.8.13/Python-3.8.13.tgz && ${'\\'} + tar xzvf Python-3.8.13.tgz && ${'\\'} + cd Python-3.8.13 && ${'\\'} ./configure && ${'\\'} make -j4 && ${'\\'} make install RUN cd /tmp && ${'\\'} - echo "b8f4f897df967014ddb42033b90c3058 Python-3.8.0b4.tgz" > checksum.md5 && ${'\\'} + echo "3c49180c6b43df3519849b7e390af0b9 Python-3.8.13.tgz" > checksum.md5 && ${'\\'} md5sum -c checksum.md5 RUN python3.8 -m ensurepip && ${'\\'} diff --git a/test/core/client_channel/rls_lb_config_parser_test.cc b/test/core/client_channel/rls_lb_config_parser_test.cc index 3089e33c988..7ac0efef283 100644 --- a/test/core/client_channel/rls_lb_config_parser_test.cc +++ b/test/core/client_channel/rls_lb_config_parser_test.cc @@ -35,22 +35,16 @@ namespace { class RlsConfigParsingTest : public ::testing::Test { public: - static void SetUpTestSuite() { - gpr_setenv("GRPC_EXPERIMENTAL_ENABLE_RLS_LB_POLICY", "true"); - grpc_init(); - } + static void SetUpTestSuite() { grpc_init(); } - static void TearDownTestSuite() { - grpc_shutdown_blocking(); - gpr_unsetenv("GRPC_EXPERIMENTAL_ENABLE_RLS_LB_POLICY"); - } + static void TearDownTestSuite() { grpc_shutdown_blocking(); } }; TEST_F(RlsConfigParsingTest, ValidConfig) { const char* service_config_json = "{\n" " \"loadBalancingConfig\":[{\n" - " \"rls\":{\n" + " \"rls_experimental\":{\n" " \"routeLookupConfig\":{\n" " \"lookupService\":\"rls.example.com:80\",\n" " \"cacheSizeBytes\":1,\n" @@ -88,7 +82,7 @@ TEST_F(RlsConfigParsingTest, TopLevelRequiredFieldsMissing) { const char* service_config_json = "{\n" " \"loadBalancingConfig\":[{\n" - " \"rls\":{\n" + " \"rls_experimental\":{\n" " }\n" " }]\n" "}\n"; @@ -109,7 +103,7 @@ TEST_F(RlsConfigParsingTest, TopLevelFieldsWrongTypes) { const char* service_config_json = "{\n" " \"loadBalancingConfig\":[{\n" - " \"rls\":{\n" + " \"rls_experimental\":{\n" " \"routeLookupConfig\":1,\n" " \"routeLookupChannelServiceConfig\": 1,\n" " \"childPolicy\":1,\n" @@ -135,7 +129,7 @@ TEST_F(RlsConfigParsingTest, TopLevelFieldsInvalidValues) { const char* service_config_json = "{\n" " \"loadBalancingConfig\":[{\n" - " \"rls\":{\n" + " \"rls_experimental\":{\n" " \"childPolicy\":[\n" " {\"unknown\":{}}\n" " ],\n" @@ -160,7 +154,7 @@ TEST_F(RlsConfigParsingTest, InvalidChildPolicyConfig) { const char* service_config_json = "{\n" " \"loadBalancingConfig\":[{\n" - " \"rls\":{\n" + " \"rls_experimental\":{\n" " \"childPolicy\":[\n" " {\"grpclb\":{\"childPolicy\":1}}\n" " ],\n" @@ -184,7 +178,7 @@ TEST_F(RlsConfigParsingTest, InvalidRlsChannelServiceConfig) { const char* service_config_json = "{\n" " \"loadBalancingConfig\":[{\n" - " \"rls\":{\n" + " \"rls_experimental\":{\n" " \"routeLookupChannelServiceConfig\": {\n" " \"loadBalancingPolicy\": \"unknown\"\n" " },\n" @@ -217,7 +211,7 @@ TEST_F(RlsConfigParsingTest, RouteLookupConfigRequiredFieldsMissing) { const char* service_config_json = "{\n" " \"loadBalancingConfig\":[{\n" - " \"rls\":{\n" + " \"rls_experimental\":{\n" " \"routeLookupConfig\":{\n" " }\n" " }\n" @@ -239,7 +233,7 @@ TEST_F(RlsConfigParsingTest, RouteLookupConfigFieldsWrongTypes) { const char* service_config_json = "{\n" " \"loadBalancingConfig\":[{\n" - " \"rls\":{\n" + " \"rls_experimental\":{\n" " \"routeLookupConfig\":{\n" " \"grpcKeybuilders\":1,\n" " \"name\":1,\n" @@ -264,7 +258,7 @@ TEST_F(RlsConfigParsingTest, RouteLookupConfigFieldsWrongTypes) { "field:lookupService error:type should be STRING.*" "field:maxAge error:type should be STRING.*" "field:staleAge error:type should be STRING.*" - "field:cacheSizeBytes error:type should be NUMBER.*" + "field:cacheSizeBytes error:failed to parse.*" "field:defaultTarget error:type should be STRING")); GRPC_ERROR_UNREF(error); } @@ -273,7 +267,7 @@ TEST_F(RlsConfigParsingTest, RouteLookupConfigFieldsInvalidValues) { const char* service_config_json = "{\n" " \"loadBalancingConfig\":[{\n" - " \"rls\":{\n" + " \"rls_experimental\":{\n" " \"routeLookupConfig\":{\n" " \"lookupService\":\"\",\n" " \"cacheSizeBytes\":0\n" @@ -301,7 +295,7 @@ TEST_F(RlsConfigParsingTest, GrpcKeybuilderRequiredFieldsMissing) { const char* service_config_json = "{\n" " \"loadBalancingConfig\":[{\n" - " \"rls\":{\n" + " \"rls_experimental\":{\n" " \"routeLookupConfig\":{\n" " \"grpcKeybuilders\":[\n" " {\n" @@ -328,7 +322,7 @@ TEST_F(RlsConfigParsingTest, GrpcKeybuilderWrongFieldTypes) { const char* service_config_json = "{\n" " \"loadBalancingConfig\":[{\n" - " \"rls\":{\n" + " \"rls_experimental\":{\n" " \"routeLookupConfig\":{\n" " \"grpcKeybuilders\":[\n" " {\n" @@ -362,7 +356,7 @@ TEST_F(RlsConfigParsingTest, GrpcKeybuilderInvalidValues) { const char* service_config_json = "{\n" " \"loadBalancingConfig\":[{\n" - " \"rls\":{\n" + " \"rls_experimental\":{\n" " \"routeLookupConfig\":{\n" " \"grpcKeybuilders\":[\n" " {\n" @@ -403,7 +397,7 @@ TEST_F(RlsConfigParsingTest, GrpcKeybuilderInvalidHeaders) { const char* service_config_json = "{\n" " \"loadBalancingConfig\":[{\n" - " \"rls\":{\n" + " \"rls_experimental\":{\n" " \"routeLookupConfig\":{\n" " \"grpcKeybuilders\":[\n" " {\n" @@ -463,7 +457,7 @@ TEST_F(RlsConfigParsingTest, GrpcKeybuilderNameWrongFieldTypes) { const char* service_config_json = "{\n" " \"loadBalancingConfig\":[{\n" - " \"rls\":{\n" + " \"rls_experimental\":{\n" " \"routeLookupConfig\":{\n" " \"grpcKeybuilders\":[\n" " {\n" @@ -500,7 +494,7 @@ TEST_F(RlsConfigParsingTest, DuplicateMethodNamesInSameKeyBuilder) { const char* service_config_json = "{\n" " \"loadBalancingConfig\":[{\n" - " \"rls\":{\n" + " \"rls_experimental\":{\n" " \"routeLookupConfig\":{\n" " \"grpcKeybuilders\":[\n" " {\n" @@ -537,7 +531,7 @@ TEST_F(RlsConfigParsingTest, DuplicateMethodNamesInDifferentKeyBuilders) { const char* service_config_json = "{\n" " \"loadBalancingConfig\":[{\n" - " \"rls\":{\n" + " \"rls_experimental\":{\n" " \"routeLookupConfig\":{\n" " \"grpcKeybuilders\":[\n" " {\n" diff --git a/test/core/ext/filters/rbac/rbac_service_config_parser_test.cc b/test/core/ext/filters/rbac/rbac_service_config_parser_test.cc index 9ab1102c4dc..400c6281c58 100644 --- a/test/core/ext/filters/rbac/rbac_service_config_parser_test.cc +++ b/test/core/ext/filters/rbac/rbac_service_config_parser_test.cc @@ -410,7 +410,7 @@ TEST(RbacServiceConfigParsingTest, VariousPermissionsAndPrincipalsBadTypes) { "permissions\\[5\\]" CHILD_ERROR_TAG "field:destinationIp error:type should be OBJECT.*" "permissions\\[6\\]" CHILD_ERROR_TAG - "field:destinationPort error:type should be NUMBER.*" + "field:destinationPort error:failed to parse.*" "permissions\\[7\\]" CHILD_ERROR_TAG "field:metadata error:type should be OBJECT.*" "permissions\\[8\\]" CHILD_ERROR_TAG diff --git a/test/core/memory_usage/client.cc b/test/core/memory_usage/client.cc index 9734cae13e2..2e3a4fa1eb3 100644 --- a/test/core/memory_usage/client.cc +++ b/test/core/memory_usage/client.cc @@ -30,6 +30,7 @@ #include #include +#include "src/core/lib/channel/channel_args.h" #include "src/core/lib/gpr/env.h" #include "src/core/lib/gpr/string.h" #include "src/core/lib/gpr/useful.h" @@ -214,6 +215,7 @@ std::pair run_test_loop(int iterations, int* call_idx) { ABSL_FLAG(std::string, target, "localhost:443", "Target host:port"); ABSL_FLAG(int, warmup, 100, "Warmup iterations"); ABSL_FLAG(int, benchmark, 1000, "Benchmark iterations"); +ABSL_FLAG(bool, minstack, false, "Use minimal stack"); int main(int argc, char** argv) { absl::ParseCommandLine(argc, argv); @@ -233,8 +235,15 @@ int main(int argc, char** argv) { cq = grpc_completion_queue_create_for_next(nullptr); + std::vector args_vec; + if (absl::GetFlag(FLAGS_minstack)) { + args_vec.push_back(grpc_channel_arg_integer_create( + const_cast(GRPC_ARG_MINIMAL_STACK), 1)); + } + grpc_channel_args args = {args_vec.size(), args_vec.data()}; + channel = grpc_channel_create(absl::GetFlag(FLAGS_target).c_str(), - grpc_insecure_credentials_create(), nullptr); + grpc_insecure_credentials_create(), &args); int call_idx = 0; const int warmup_iterations = absl::GetFlag(FLAGS_warmup); diff --git a/test/core/memory_usage/memory_usage_test.cc b/test/core/memory_usage/memory_usage_test.cc index d535ece9eec..91593dede8f 100644 --- a/test/core/memory_usage/memory_usage_test.cc +++ b/test/core/memory_usage/memory_usage_test.cc @@ -34,6 +34,7 @@ ABSL_FLAG(int, warmup, 100, "Warmup iterations"); ABSL_FLAG(int, benchmark, 1000, "Benchmark iterations"); +ABSL_FLAG(bool, minstack, false, "Use minimal stack"); class Subprocess { public: @@ -74,15 +75,16 @@ int main(int argc, char** argv) { /* start the server */ Subprocess svr({absl::StrCat(root, "/memory_usage_server", gpr_subprocess_binary_extension()), - "--bind", grpc_core::JoinHostPort("::", port), "--nosecure"}); + "--bind", grpc_core::JoinHostPort("::", port), "--nosecure", + absl::StrCat("--minstack=", absl::GetFlag(FLAGS_minstack))}); /* start the client */ - Subprocess cli( - {absl::StrCat(root, "/memory_usage_client", - gpr_subprocess_binary_extension()), - "--target", grpc_core::JoinHostPort("127.0.0.1", port), - absl::StrCat("--warmup=", absl::GetFlag(FLAGS_warmup)), - absl::StrCat("--benchmark=", absl::GetFlag(FLAGS_benchmark))}); + Subprocess cli({absl::StrCat(root, "/memory_usage_client", + gpr_subprocess_binary_extension()), + "--target", grpc_core::JoinHostPort("127.0.0.1", port), + absl::StrCat("--warmup=", absl::GetFlag(FLAGS_warmup)), + absl::StrCat("--benchmark=", absl::GetFlag(FLAGS_benchmark)), + absl::StrCat("--minstack=", absl::GetFlag(FLAGS_minstack))}); /* wait for completion */ if ((status = cli.Join()) != 0) { diff --git a/test/core/memory_usage/server.cc b/test/core/memory_usage/server.cc index da1bc165a34..f41ca21459a 100644 --- a/test/core/memory_usage/server.cc +++ b/test/core/memory_usage/server.cc @@ -40,6 +40,7 @@ #include #include +#include "src/core/lib/channel/channel_args.h" #include "src/core/lib/gprpp/host_port.h" #include "test/core/end2end/data/ssl_test_data.h" #include "test/core/memory_usage/memstats.h" @@ -154,6 +155,7 @@ static void sigint_handler(int /*x*/) { _exit(0); } ABSL_FLAG(std::string, bind, "", "Bind host:port"); ABSL_FLAG(bool, secure, false, "Use security"); +ABSL_FLAG(bool, minstack, false, "Use minimal stack"); int main(int argc, char** argv) { absl::ParseCommandLine(argc, argv); @@ -180,17 +182,24 @@ int main(int argc, char** argv) { cq = grpc_completion_queue_create_for_next(nullptr); + std::vector args_vec; + if (absl::GetFlag(FLAGS_minstack)) { + args_vec.push_back(grpc_channel_arg_integer_create( + const_cast(GRPC_ARG_MINIMAL_STACK), 1)); + } + grpc_channel_args args = {args_vec.size(), args_vec.data()}; + MemStats before_server_create = MemStats::Snapshot(); if (absl::GetFlag(FLAGS_secure)) { grpc_ssl_pem_key_cert_pair pem_key_cert_pair = {test_server1_key, test_server1_cert}; grpc_server_credentials* ssl_creds = grpc_ssl_server_credentials_create( nullptr, &pem_key_cert_pair, 1, 0, nullptr); - server = grpc_server_create(nullptr, nullptr); + server = grpc_server_create(&args, nullptr); GPR_ASSERT(grpc_server_add_http2_port(server, addr.c_str(), ssl_creds)); grpc_server_credentials_release(ssl_creds); } else { - server = grpc_server_create(nullptr, nullptr); + server = grpc_server_create(&args, nullptr); GPR_ASSERT(grpc_server_add_http2_port( server, addr.c_str(), grpc_insecure_server_credentials_create())); } diff --git a/test/core/tsi/crl_ssl_transport_security_test.cc b/test/core/tsi/crl_ssl_transport_security_test.cc index 17a04585f8e..eede108d3db 100644 --- a/test/core/tsi/crl_ssl_transport_security_test.cc +++ b/test/core/tsi/crl_ssl_transport_security_test.cc @@ -43,6 +43,7 @@ const int kSslTsiTestRevokedKeyCertPairsNum = 1; const int kSslTsiTestValidKeyCertPairsNum = 1; const char* kSslTsiTestCrlSupportedCredentialsDir = "test/core/tsi/test_creds/crl_data/"; +const char* kSslTsiTestFaultyCrlsDir = "bad_path/"; class CrlSslTransportSecurityTest : public testing::TestWithParam { @@ -50,10 +51,14 @@ class CrlSslTransportSecurityTest // A tsi_test_fixture implementation. class SslTsiTestFixture { public: + // When use_faulty_crl_directory is set, the crl_directory of the + // client is set to a non-existant path. static SslTsiTestFixture* Create(bool use_revoked_server_cert, - bool use_revoked_client_cert) { + bool use_revoked_client_cert, + bool use_faulty_crl_directory) { return new SslTsiTestFixture(use_revoked_server_cert, - use_revoked_client_cert); + use_revoked_client_cert, + use_faulty_crl_directory); } void Run() { @@ -63,9 +68,11 @@ class CrlSslTransportSecurityTest private: SslTsiTestFixture(bool use_revoked_server_cert, - bool use_revoked_client_cert) + bool use_revoked_client_cert, + bool use_faulty_crl_directory) : use_revoked_server_cert_(use_revoked_server_cert), - use_revoked_client_cert_(use_revoked_client_cert) { + use_revoked_client_cert_(use_revoked_client_cert), + use_faulty_crl_directory_(use_faulty_crl_directory) { tsi_test_fixture_init(&base_); base_.test_unused_bytes = true; base_.vtable = &kVtable; @@ -120,7 +127,11 @@ class CrlSslTransportSecurityTest } else { client_options.pem_key_cert_pair = valid_pem_key_cert_pairs_; } - client_options.crl_directory = kSslTsiTestCrlSupportedCredentialsDir; + if (use_faulty_crl_directory_) { + client_options.crl_directory = kSslTsiTestFaultyCrlsDir; + } else { + client_options.crl_directory = kSslTsiTestCrlSupportedCredentialsDir; + } client_options.root_store = root_store_; client_options.min_tls_version = GetParam(); client_options.max_tls_version = GetParam(); @@ -228,6 +239,7 @@ class CrlSslTransportSecurityTest tsi_test_fixture base_; bool use_revoked_server_cert_; bool use_revoked_client_cert_; + bool use_faulty_crl_directory_; char* root_cert_; tsi_ssl_root_certs_store* root_store_; tsi_ssl_pem_key_cert_pair* revoked_pem_key_cert_pairs_; @@ -245,19 +257,29 @@ struct tsi_test_fixture_vtable TEST_P(CrlSslTransportSecurityTest, RevokedServerCert) { auto* fixture = SslTsiTestFixture::Create(/*use_revoked_server_cert=*/true, - /*use_revoked_client_cert=*/false); + /*use_revoked_client_cert=*/false, + /*use_faulty_crl_directory=*/false); fixture->Run(); } TEST_P(CrlSslTransportSecurityTest, RevokedClientCert) { auto* fixture = SslTsiTestFixture::Create(/*use_revoked_server_cert=*/false, - /*use_revoked_client_cert=*/true); + /*use_revoked_client_cert=*/true, + /*use_faulty_crl_directory=*/false); fixture->Run(); } TEST_P(CrlSslTransportSecurityTest, ValidCerts) { auto* fixture = SslTsiTestFixture::Create(/*use_revoked_server_cert=*/false, - /*use_revoked_client_cert=*/false); + /*use_revoked_client_cert=*/false, + /*use_faulty_crl_directory=*/false); + fixture->Run(); +} + +TEST_P(CrlSslTransportSecurityTest, UseFaultyCrlDirectory) { + auto* fixture = SslTsiTestFixture::Create(/*use_revoked_server_cert=*/false, + /*use_revoked_client_cert=*/false, + /*use_faulty_crl_directory=*/true); fixture->Run(); } diff --git a/test/core/util/test_lb_policies.cc b/test/core/util/test_lb_policies.cc index 056597a24d5..413d572821c 100644 --- a/test/core/util/test_lb_policies.cc +++ b/test/core/util/test_lb_policies.cc @@ -281,6 +281,7 @@ class InterceptRecvTrailingMetadataLoadBalancingPolicy void Finish(FinishArgs args) override { TrailingMetadataArgsSeen args_seen; + args_seen.status = args.status; args_seen.backend_metric_data = args.backend_metric_accessor->GetBackendMetricData(); args_seen.metadata = args.trailing_metadata->TestOnlyCopyToVector(); diff --git a/test/core/util/test_lb_policies.h b/test/core/util/test_lb_policies.h index a8f023b1143..9196aee3c78 100644 --- a/test/core/util/test_lb_policies.h +++ b/test/core/util/test_lb_policies.h @@ -36,6 +36,7 @@ void RegisterTestPickArgsLoadBalancingPolicy( TestPickArgsCallback cb, const char* delegate_policy_name = "pick_first"); struct TrailingMetadataArgsSeen { + absl::Status status; const LoadBalancingPolicy::BackendMetricAccessor::BackendMetricData* backend_metric_data; MetadataVector metadata; diff --git a/test/core/xds/google_mesh_ca_certificate_provider_factory_test.cc b/test/core/xds/google_mesh_ca_certificate_provider_factory_test.cc index b5ee4fbbb63..cbbad3c5988 100644 --- a/test/core/xds/google_mesh_ca_certificate_provider_factory_test.cc +++ b/test/core/xds/google_mesh_ca_certificate_provider_factory_test.cc @@ -214,7 +214,7 @@ TEST(GoogleMeshCaConfigTest, WrongTypes) { " \"certificate_lifetime\": 400," " \"renewal_grace_period\": 100," " \"key_type\": 123," - " \"key_size\": \"1024\"," + " \"key_size\": \"1024A\"," " \"location\": 123" "}"; grpc_error_handle error = GRPC_ERROR_NONE; @@ -245,7 +245,7 @@ TEST(GoogleMeshCaConfigTest, WrongTypes) { "field:renewal_grace_period error:type should be STRING of the form " "given by google.proto.Duration..*" "field:key_type error:type should be STRING.*" - "field:key_size error:type should be NUMBER.*" + "field:key_size error:failed to parse.*" "field:location error:type should be STRING")); GRPC_ERROR_UNREF(error); } diff --git a/test/cpp/end2end/BUILD b/test/cpp/end2end/BUILD index 2bae92a3b17..32bcf8bea58 100644 --- a/test/cpp/end2end/BUILD +++ b/test/cpp/end2end/BUILD @@ -70,6 +70,21 @@ grpc_cc_library( ], ) +grpc_cc_library( + name = "rls_server", + testonly = True, + srcs = ["rls_server.cc"], + hdrs = ["rls_server.h"], + external_deps = [ + "gtest", + ], + deps = [ + ":counted_service", + "//src/proto/grpc/lookup/v1:rls_proto", + "//test/core/util:grpc_test_util", + ], +) + grpc_cc_test( name = "async_end2end_test", srcs = ["async_end2end_test.cc"], @@ -487,6 +502,7 @@ grpc_cc_test( tags = ["no_test_ios"], deps = [ ":counted_service", + ":rls_server", ":test_service_impl", "//:gpr", "//:grpc", diff --git a/test/cpp/end2end/client_lb_end2end_test.cc b/test/cpp/end2end/client_lb_end2end_test.cc index f76980c25ad..c698037cb82 100644 --- a/test/cpp/end2end/client_lb_end2end_test.cc +++ b/test/cpp/end2end/client_lb_end2end_test.cc @@ -78,6 +78,8 @@ namespace grpc { namespace testing { namespace { +constexpr char kRequestMessage[] = "Live long and prosper."; + gpr_atm g_connection_delay_ms; void tcp_client_connect_with_delay(grpc_closure* closure, grpc_endpoint** ep, @@ -232,7 +234,6 @@ class ClientLbEnd2endTest : public ::testing::Test { protected: ClientLbEnd2endTest() : server_host_("localhost"), - kRequestMessage_("Live long and prosper."), creds_(new SecureChannelCredentials( grpc_fake_transport_security_credentials_create())) {} @@ -316,21 +317,22 @@ class ClientLbEnd2endTest : public ::testing::Test { bool SendRpc( const std::unique_ptr& stub, EchoResponse* response = nullptr, int timeout_ms = 1000, - Status* result = nullptr, bool wait_for_ready = false) { - const bool local_response = (response == nullptr); - if (local_response) response = new EchoResponse; - EchoRequest request; - request.set_message(kRequestMessage_); - request.mutable_param()->set_echo_metadata(true); + Status* result = nullptr, bool wait_for_ready = false, + EchoRequest* request = nullptr) { + EchoResponse local_response; + if (response == nullptr) response = &local_response; + EchoRequest local_request; + if (request == nullptr) request = &local_request; + request->set_message(kRequestMessage); + request->mutable_param()->set_echo_metadata(true); ClientContext context; context.set_deadline(grpc_timeout_milliseconds_to_deadline(timeout_ms)); if (wait_for_ready) context.set_wait_for_ready(true); context.AddMetadata("foo", "1"); context.AddMetadata("bar", "2"); context.AddMetadata("baz", "3"); - Status status = stub->Echo(&context, request, response); + Status status = stub->Echo(&context, *request, response); if (result != nullptr) *result = status; - if (local_response) delete response; return status.ok(); } @@ -345,7 +347,7 @@ class ClientLbEnd2endTest : public ::testing::Test { << "\n" << "Error: " << status.error_message() << " " << status.error_details(); - ASSERT_EQ(response.message(), kRequestMessage_) + ASSERT_EQ(response.message(), kRequestMessage) << "From " << location.file() << ":" << location.line(); if (!success) abort(); } @@ -483,7 +485,6 @@ class ClientLbEnd2endTest : public ::testing::Test { const std::string server_host_; std::vector> servers_; - const std::string kRequestMessage_; std::shared_ptr creds_; bool ipv6_only_ = false; }; @@ -1832,14 +1833,19 @@ class ClientLbInterceptTrailingMetadataTest : public ClientLbEnd2endTest { return trailers_intercepted_; } - const grpc_core::MetadataVector& trailing_metadata() { + absl::Status last_status() { + grpc::internal::MutexLock lock(&mu_); + return last_status_; + } + + grpc_core::MetadataVector trailing_metadata() { grpc::internal::MutexLock lock(&mu_); - return trailing_metadata_; + return std::move(trailing_metadata_); } - const xds::data::orca::v3::OrcaLoadReport* backend_load_report() { + std::unique_ptr backend_load_report() { grpc::internal::MutexLock lock(&mu_); - return load_report_.get(); + return std::move(load_report_); } private: @@ -1848,6 +1854,7 @@ class ClientLbInterceptTrailingMetadataTest : public ClientLbEnd2endTest { const auto* backend_metric_data = args_seen.backend_metric_data; ClientLbInterceptTrailingMetadataTest* self = current_test_instance_; grpc::internal::MutexLock lock(&self->mu_); + self->last_status_ = args_seen.status; self->trailers_intercepted_++; self->trailing_metadata_ = args_seen.metadata; if (backend_metric_data != nullptr) { @@ -1872,6 +1879,7 @@ class ClientLbInterceptTrailingMetadataTest : public ClientLbEnd2endTest { static ClientLbInterceptTrailingMetadataTest* current_test_instance_; grpc::internal::Mutex mu_; int trailers_intercepted_ = 0; + absl::Status last_status_; grpc_core::MetadataVector trailing_metadata_; std::unique_ptr load_report_; }; @@ -1879,13 +1887,74 @@ class ClientLbInterceptTrailingMetadataTest : public ClientLbEnd2endTest { ClientLbInterceptTrailingMetadataTest* ClientLbInterceptTrailingMetadataTest::current_test_instance_ = nullptr; +TEST_F(ClientLbInterceptTrailingMetadataTest, StatusOk) { + StartServers(1); + auto response_generator = BuildResolverResponseGenerator(); + auto channel = + BuildChannel("intercept_trailing_metadata_lb", response_generator); + auto stub = BuildStub(channel); + response_generator.SetNextResolution(GetServersPorts()); + // Send an OK RPC. + CheckRpcSendOk(stub, DEBUG_LOCATION); + // Check LB policy name for the channel. + EXPECT_EQ("intercept_trailing_metadata_lb", + channel->GetLoadBalancingPolicyName()); + EXPECT_EQ(1, trailers_intercepted()); + EXPECT_EQ(absl::OkStatus(), last_status()); +} + +TEST_F(ClientLbInterceptTrailingMetadataTest, StatusFailed) { + StartServers(1); + auto response_generator = BuildResolverResponseGenerator(); + auto channel = + BuildChannel("intercept_trailing_metadata_lb", response_generator); + auto stub = BuildStub(channel); + response_generator.SetNextResolution(GetServersPorts()); + EchoRequest request; + auto* expected_error = request.mutable_param()->mutable_expected_error(); + expected_error->set_code(GRPC_STATUS_PERMISSION_DENIED); + expected_error->set_error_message("bummer, man"); + Status status; + SendRpc(stub, /*response=*/nullptr, /*timeout_ms=*/1000, &status, + /*wait_for_ready=*/false, &request); + EXPECT_EQ(status.error_code(), GRPC_STATUS_PERMISSION_DENIED); + EXPECT_EQ(status.error_message(), "bummer, man"); + absl::Status status_seen_by_lb = last_status(); + EXPECT_EQ(status_seen_by_lb.code(), absl::StatusCode::kPermissionDenied); + EXPECT_EQ(status_seen_by_lb.message(), "bummer, man"); +} + +TEST_F(ClientLbInterceptTrailingMetadataTest, + StatusCancelledWithoutStartingRecvTrailingMetadata) { + StartServers(1); + auto response_generator = BuildResolverResponseGenerator(); + auto channel = + BuildChannel("intercept_trailing_metadata_lb", response_generator); + response_generator.SetNextResolution(GetServersPorts()); + auto stub = BuildStub(channel); + { + // Start a stream (sends initial metadata) and then cancel without + // calling Finish(). + ClientContext ctx; + auto stream = stub->BidiStream(&ctx); + ctx.TryCancel(); + } + // Check status seen by LB policy. + EXPECT_EQ(1, trailers_intercepted()); + absl::Status status_seen_by_lb = last_status(); + EXPECT_EQ(status_seen_by_lb.code(), absl::StatusCode::kCancelled); + EXPECT_EQ(status_seen_by_lb.message(), "call cancelled"); +} + TEST_F(ClientLbInterceptTrailingMetadataTest, InterceptsRetriesDisabled) { const int kNumServers = 1; const int kNumRpcs = 10; StartServers(kNumServers); auto response_generator = BuildResolverResponseGenerator(); - auto channel = - BuildChannel("intercept_trailing_metadata_lb", response_generator); + ChannelArguments channel_args; + channel_args.SetInt(GRPC_ARG_ENABLE_RETRIES, 0); + auto channel = BuildChannel("intercept_trailing_metadata_lb", + response_generator, channel_args); auto stub = BuildStub(channel); response_generator.SetNextResolution(GetServersPorts()); for (size_t i = 0; i < kNumRpcs; ++i) { @@ -1971,7 +2040,7 @@ TEST_F(ClientLbInterceptTrailingMetadataTest, BackendMetricData) { response_generator.SetNextResolution(GetServersPorts()); for (size_t i = 0; i < kNumRpcs; ++i) { CheckRpcSendOk(stub, DEBUG_LOCATION); - auto* actual = backend_load_report(); + auto actual = backend_load_report(); ASSERT_NE(actual, nullptr); // TODO(roth): Change this to use EqualsProto() once that becomes // available in OSS. diff --git a/test/cpp/end2end/rls_end2end_test.cc b/test/cpp/end2end/rls_end2end_test.cc index a759ffc5664..c35766b5ebd 100644 --- a/test/cpp/end2end/rls_end2end_test.cc +++ b/test/cpp/end2end/rls_end2end_test.cc @@ -60,11 +60,11 @@ #include "test/core/util/test_config.h" #include "test/core/util/test_lb_policies.h" #include "test/cpp/end2end/counted_service.h" +#include "test/cpp/end2end/rls_server.h" #include "test/cpp/end2end/test_service_impl.h" #include "test/cpp/util/test_config.h" using ::grpc::lookup::v1::RouteLookupRequest; -using ::grpc::lookup::v1::RouteLookupResponse; namespace grpc { namespace testing { @@ -87,92 +87,6 @@ const char* kConstantKey = "constant_key"; const char* kConstantValue = "constant_value"; using BackendService = CountedService; -using RlsService = - CountedService; - -class RlsServiceImpl : public RlsService { - public: - grpc::Status RouteLookup(grpc::ServerContext* context, - const RouteLookupRequest* request, - RouteLookupResponse* response) override { - gpr_log(GPR_INFO, "RLS: Received request: %s", - request->DebugString().c_str()); - // RLS server should see call creds. - EXPECT_THAT(context->client_metadata(), - ::testing::Contains( - ::testing::Pair(kCallCredsMdKey, kCallCredsMdValue))); - IncreaseRequestCount(); - EXPECT_EQ(request->target_type(), "grpc"); - // See if we have a configured response for this request. - ResponseData res; - { - grpc::internal::MutexLock lock(&mu_); - auto it = responses_.find(*request); - if (it == responses_.end()) { - gpr_log(GPR_INFO, "RLS: no matching request, returning INTERNAL"); - unmatched_requests_.push_back(*request); - return Status(StatusCode::INTERNAL, "no response entry"); - } - res = it->second; - } - // Configured response found, so use it. - if (res.response_delay > grpc_core::Duration::Zero()) { - gpr_sleep_until( - grpc_timeout_milliseconds_to_deadline(res.response_delay.millis())); - } - IncreaseResponseCount(); - *response = res.response; - gpr_log(GPR_INFO, "RLS: returning configured response: %s", - response->DebugString().c_str()); - return Status::OK; - } - - void Start() {} - - void Shutdown() {} - - void SetResponse(RouteLookupRequest request, RouteLookupResponse response, - grpc_core::Duration response_delay = grpc_core::Duration()) { - grpc::internal::MutexLock lock(&mu_); - responses_[std::move(request)] = {std::move(response), response_delay}; - } - - void RemoveResponse(const RouteLookupRequest& request) { - grpc::internal::MutexLock lock(&mu_); - responses_.erase(request); - } - - std::vector GetUnmatchedRequests() { - grpc::internal::MutexLock lock(&mu_); - return std::move(unmatched_requests_); - } - - private: - // Sorting thunk for RouteLookupRequest. - struct RlsRequestLessThan { - bool operator()(const RouteLookupRequest& req1, - const RouteLookupRequest& req2) const { - std::map key_map1( - req1.key_map().begin(), req1.key_map().end()); - std::map key_map2( - req2.key_map().begin(), req2.key_map().end()); - if (key_map1 < key_map2) return true; - if (req1.reason() < req2.reason()) return true; - if (req1.stale_header_data() < req2.stale_header_data()) return true; - return false; - } - }; - - struct ResponseData { - RouteLookupResponse response; - grpc_core::Duration response_delay; - }; - - grpc::internal::Mutex mu_; - std::map responses_ - ABSL_GUARDED_BY(&mu_); - std::vector unmatched_requests_ ABSL_GUARDED_BY(&mu_); -}; // Subclass of TestServiceImpl that increments a request counter for // every call to the Echo Rpc. @@ -265,7 +179,12 @@ class RlsEnd2endTest : public ::testing::Test { grpc_core::LocalhostResolves(&localhost_resolves_to_ipv4, &localhost_resolves_to_ipv6); ipv6_only_ = !localhost_resolves_to_ipv4 && localhost_resolves_to_ipv6; - rls_server_ = absl::make_unique>("rls"); + rls_server_ = absl::make_unique>( + "rls", [](grpc::ServerContext* ctx) { + EXPECT_THAT(ctx->client_metadata(), + ::testing::Contains( + ::testing::Pair(kCallCredsMdKey, kCallCredsMdValue))); + }); rls_server_->Start(); resolver_response_generator_ = absl::make_unique(); @@ -316,26 +235,6 @@ class RlsEnd2endTest : public ::testing::Test { return absl::StrCat("ipv4:127.0.0.1:", port); } - static RouteLookupRequest BuildRlsRequest( - std::map key, - RouteLookupRequest::Reason reason = RouteLookupRequest::REASON_MISS, - const char* stale_header_data = "") { - RouteLookupRequest request; - request.set_target_type("grpc"); - request.mutable_key_map()->insert(key.begin(), key.end()); - request.set_reason(reason); - request.set_stale_header_data(stale_header_data); - return request; - } - - static RouteLookupResponse BuildRlsResponse(std::vector targets, - const char* header_data = "") { - RouteLookupResponse response; - response.mutable_targets()->Add(targets.begin(), targets.end()); - response.set_header_data(header_data); - return response; - } - struct RpcOptions { int timeout_ms = 1000; bool wait_for_ready = false; @@ -481,7 +380,7 @@ class RlsEnd2endTest : public ::testing::Test { return absl::StrCat( "{" " \"loadBalancingConfig\":[{" - " \"rls\":{", + " \"rls_experimental\":{", absl::StrJoin(rls_config_parts, ","), " }" " }]" diff --git a/test/cpp/end2end/rls_server.cc b/test/cpp/end2end/rls_server.cc new file mode 100644 index 00000000000..c5053792cc4 --- /dev/null +++ b/test/cpp/end2end/rls_server.cc @@ -0,0 +1,103 @@ +// +// Copyright 2020 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 "test/cpp/end2end/rls_server.h" + +#include + +#include "src/proto/grpc/lookup/v1/rls.grpc.pb.h" +#include "src/proto/grpc/lookup/v1/rls.pb.h" +#include "test/core/util/test_config.h" + +using ::grpc::lookup::v1::RouteLookupRequest; +using ::grpc::lookup::v1::RouteLookupResponse; + +namespace grpc { +namespace testing { + +::grpc::Status RlsServiceImpl::RouteLookup(grpc::ServerContext* context, + const RouteLookupRequest* request, + RouteLookupResponse* response) { + gpr_log(GPR_INFO, "RLS: Received request: %s", + request->DebugString().c_str()); + if (context_proc_ != nullptr) { + context_proc_(context); + } + IncreaseRequestCount(); + EXPECT_EQ(request->target_type(), "grpc"); + // See if we have a configured response for this request. + ResponseData res; + { + grpc::internal::MutexLock lock(&mu_); + auto it = responses_.find(*request); + if (it == responses_.end()) { + gpr_log(GPR_INFO, "RLS: no matching request, returning INTERNAL"); + unmatched_requests_.push_back(*request); + return Status(StatusCode::INTERNAL, "no response entry"); + } + res = it->second; + } + // Configured response found, so use it. + if (res.response_delay > grpc_core::Duration::Zero()) { + gpr_sleep_until( + grpc_timeout_milliseconds_to_deadline(res.response_delay.millis())); + } + IncreaseResponseCount(); + *response = res.response; + gpr_log(GPR_INFO, "RLS: returning configured response: %s", + response->DebugString().c_str()); + return Status::OK; +} + +void RlsServiceImpl::SetResponse(RouteLookupRequest request, + RouteLookupResponse response, + grpc_core::Duration response_delay) { + grpc::internal::MutexLock lock(&mu_); + responses_[std::move(request)] = {std::move(response), response_delay}; +} + +void RlsServiceImpl::RemoveResponse(const RouteLookupRequest& request) { + grpc::internal::MutexLock lock(&mu_); + responses_.erase(request); +} + +std::vector RlsServiceImpl::GetUnmatchedRequests() { + grpc::internal::MutexLock lock(&mu_); + return std::move(unmatched_requests_); +} + +grpc::lookup::v1::RouteLookupRequest BuildRlsRequest( + std::map key, + grpc::lookup::v1::RouteLookupRequest::Reason reason, + const char* stale_header_data) { + grpc::lookup::v1::RouteLookupRequest request; + request.set_target_type("grpc"); + request.mutable_key_map()->insert(key.begin(), key.end()); + request.set_reason(reason); + request.set_stale_header_data(stale_header_data); + return request; +} + +grpc::lookup::v1::RouteLookupResponse BuildRlsResponse( + std::vector targets, const char* header_data) { + grpc::lookup::v1::RouteLookupResponse response; + response.mutable_targets()->Add(targets.begin(), targets.end()); + response.set_header_data(header_data); + return response; +} + +} // namespace testing +} // namespace grpc diff --git a/test/cpp/end2end/rls_server.h b/test/cpp/end2end/rls_server.h new file mode 100644 index 00000000000..958d19676e3 --- /dev/null +++ b/test/cpp/end2end/rls_server.h @@ -0,0 +1,94 @@ +// +// Copyright 2020 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 "absl/types/optional.h" + +#include "src/core/lib/gprpp/time.h" +#include "src/proto/grpc/lookup/v1/rls.grpc.pb.h" +#include "src/proto/grpc/lookup/v1/rls.pb.h" +#include "test/cpp/end2end/counted_service.h" + +namespace grpc { +namespace testing { + +using RlsService = + CountedService; + +class RlsServiceImpl : public RlsService { + public: + using ContextProcessingFunc = std::function; + + explicit RlsServiceImpl(ContextProcessingFunc context_proc = nullptr) + : context_proc_(std::move(context_proc)) {} + + grpc::Status RouteLookup( + grpc::ServerContext* context, + const grpc::lookup::v1::RouteLookupRequest* request, + grpc::lookup::v1::RouteLookupResponse* response) override; + + void Start() {} + + void Shutdown() {} + + void SetResponse(grpc::lookup::v1::RouteLookupRequest request, + grpc::lookup::v1::RouteLookupResponse response, + grpc_core::Duration response_delay = grpc_core::Duration()); + + void RemoveResponse(const grpc::lookup::v1::RouteLookupRequest& request); + + std::vector GetUnmatchedRequests(); + + private: + // Sorting thunk for RouteLookupRequest. + struct RlsRequestLessThan { + bool operator()(const grpc::lookup::v1::RouteLookupRequest& req1, + const grpc::lookup::v1::RouteLookupRequest& req2) const { + std::map key_map1( + req1.key_map().begin(), req1.key_map().end()); + std::map key_map2( + req2.key_map().begin(), req2.key_map().end()); + if (key_map1 < key_map2) return true; + if (req1.reason() < req2.reason()) return true; + if (req1.stale_header_data() < req2.stale_header_data()) return true; + return false; + } + }; + + struct ResponseData { + grpc::lookup::v1::RouteLookupResponse response; + grpc_core::Duration response_delay; + }; + + ContextProcessingFunc context_proc_; + grpc::internal::Mutex mu_; + std::map + responses_ ABSL_GUARDED_BY(&mu_); + std::vector unmatched_requests_ + ABSL_GUARDED_BY(&mu_); +}; + +grpc::lookup::v1::RouteLookupRequest BuildRlsRequest( + std::map key, + grpc::lookup::v1::RouteLookupRequest::Reason reason = + grpc::lookup::v1::RouteLookupRequest::REASON_MISS, + const char* stale_header_data = ""); + +grpc::lookup::v1::RouteLookupResponse BuildRlsResponse( + std::vector targets, const char* header_data = ""); + +} // namespace testing +} // namespace grpc diff --git a/test/cpp/end2end/xds/BUILD b/test/cpp/end2end/xds/BUILD index 19c53146c08..4a69b5c8953 100644 --- a/test/cpp/end2end/xds/BUILD +++ b/test/cpp/end2end/xds/BUILD @@ -77,6 +77,8 @@ grpc_cc_test( "//:grpc++", "//:grpc_resolver_fake", "//:grpcpp_csds", + "//src/proto/grpc/lookup/v1:rls_config_proto", + "//src/proto/grpc/lookup/v1:rls_proto", "//src/proto/grpc/testing:echo_messages_proto", "//src/proto/grpc/testing:echo_proto", "//src/proto/grpc/testing/duplicate:echo_duplicate_proto", @@ -96,6 +98,7 @@ grpc_cc_test( "//src/proto/grpc/testing/xds/v3:tls_proto", "//test/core/util:grpc_test_util", "//test/cpp/end2end:counted_service", + "//test/cpp/end2end:rls_server", "//test/cpp/end2end:test_service_impl", "//test/cpp/util:test_config", "//test/cpp/util:test_util", diff --git a/test/cpp/end2end/xds/xds_end2end_test.cc b/test/cpp/end2end/xds/xds_end2end_test.cc index af7e9d8d216..bad4896e10d 100644 --- a/test/cpp/end2end/xds/xds_end2end_test.cc +++ b/test/cpp/end2end/xds/xds_end2end_test.cc @@ -80,6 +80,9 @@ #include "src/core/lib/security/credentials/fake/fake_credentials.h" #include "src/cpp/client/secure_credentials.h" #include "src/cpp/server/secure_server_credentials.h" +#include "src/proto/grpc/lookup/v1/rls.grpc.pb.h" +#include "src/proto/grpc/lookup/v1/rls.pb.h" +#include "src/proto/grpc/lookup/v1/rls_config.pb.h" #include "src/proto/grpc/testing/echo.grpc.pb.h" #include "src/proto/grpc/testing/xds/ads_for_test.grpc.pb.h" #include "src/proto/grpc/testing/xds/cds_for_test.grpc.pb.h" @@ -103,6 +106,7 @@ #include "test/core/util/resolve_localhost_ip46.h" #include "test/core/util/test_config.h" #include "test/cpp/end2end/counted_service.h" +#include "test/cpp/end2end/rls_server.h" #include "test/cpp/end2end/test_service_impl.h" #include "test/cpp/end2end/xds/xds_server.h" #include "test/cpp/util/test_config.h" @@ -153,6 +157,8 @@ using ClientStats = LrsServiceImpl::ClientStats; using ::grpc::experimental::ExternalCertificateVerifier; using ::grpc::experimental::IdentityKeyCertPair; using ::grpc::experimental::StaticDataCertificateProvider; +using ::grpc::lookup::v1::RouteLookupClusterSpecifier; +using ::grpc::lookup::v1::RouteLookupConfig; constexpr char kDefaultLocalityRegion[] = "xds_default_locality_region"; constexpr char kDefaultLocalityZone[] = "xds_default_locality_zone"; @@ -177,6 +183,18 @@ constexpr char kClientKeyPath[] = "src/core/tsi/test_creds/client.key"; constexpr char kBadClientCertPath[] = "src/core/tsi/test_creds/badclient.pem"; constexpr char kBadClientKeyPath[] = "src/core/tsi/test_creds/badclient.key"; +constexpr char kRlsTestKey[] = "test_key"; +constexpr char kRlsTestKey1[] = "key1"; +constexpr char kRlsTestValue[] = "test_value"; +constexpr char kRlsHostKey[] = "host_key"; +constexpr char kRlsServiceKey[] = "service_key"; +constexpr char kRlsServiceValue[] = "grpc.testing.EchoTestService"; +constexpr char kRlsMethodKey[] = "method_key"; +constexpr char kRlsMethodValue[] = "Echo"; +constexpr char kRlsConstantKey[] = "constant_key"; +constexpr char kRlsConstantValue[] = "constant_value"; +constexpr char kRlsClusterSpecifierPluginInstanceName[] = "rls_plugin_instance"; + template class BackendServiceImpl : public CountedService> { @@ -6598,6 +6616,128 @@ TEST_P(CdsTest, AggregateClusterLogicalDnsToEds) { "GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER"); } +// This test covers a bug seen in the wild where the +// xds_cluster_resolver policy's code to reuse child policy names did +// not correctly handle the case where the LOGICAL_DNS priority failed, +// thus returning a priority with no localities. This caused the child +// name to be reused incorrectly, which triggered an assertion failure +// in the xds_cluster_impl policy caused by changing its cluster name. +TEST_P(CdsTest, AggregateClusterReconfigEdsWhileLogicalDnsChildFails) { + gpr_setenv("GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER", + "true"); + const char* kNewCluster1Name = "new_cluster_1"; + const char* kNewEdsService1Name = "new_eds_service_name_1"; + const char* kLogicalDNSClusterName = "logical_dns_cluster"; + // Populate EDS resource with all unreachable endpoints. + // - Priority 0: locality0 + // - Priority 1: locality1, locality2 + EdsResourceArgs args1({ + {"locality0", {MakeNonExistantEndpoint()}, kDefaultLocalityWeight, 0}, + {"locality1", {MakeNonExistantEndpoint()}, kDefaultLocalityWeight, 1}, + {"locality2", {MakeNonExistantEndpoint()}, kDefaultLocalityWeight, 1}, + }); + balancer_->ads_service()->SetEdsResource( + BuildEdsResource(args1, kNewEdsService1Name)); + // Populate new CDS resources. + Cluster new_cluster1 = default_cluster_; + new_cluster1.set_name(kNewCluster1Name); + new_cluster1.mutable_eds_cluster_config()->set_service_name( + kNewEdsService1Name); + balancer_->ads_service()->SetCdsResource(new_cluster1); + // Create Logical DNS Cluster + auto logical_dns_cluster = default_cluster_; + logical_dns_cluster.set_name(kLogicalDNSClusterName); + logical_dns_cluster.set_type(Cluster::LOGICAL_DNS); + auto* address = logical_dns_cluster.mutable_load_assignment() + ->add_endpoints() + ->add_lb_endpoints() + ->mutable_endpoint() + ->mutable_address() + ->mutable_socket_address(); + address->set_address(kServerName); + address->set_port_value(443); + balancer_->ads_service()->SetCdsResource(logical_dns_cluster); + // Create Aggregate Cluster + auto cluster = default_cluster_; + CustomClusterType* custom_cluster = cluster.mutable_cluster_type(); + custom_cluster->set_name("envoy.clusters.aggregate"); + ClusterConfig cluster_config; + cluster_config.add_clusters(kNewCluster1Name); + cluster_config.add_clusters(kLogicalDNSClusterName); + custom_cluster->mutable_typed_config()->PackFrom(cluster_config); + balancer_->ads_service()->SetCdsResource(cluster); + // Set Logical DNS result + { + grpc_core::ExecCtx exec_ctx; + grpc_core::Resolver::Result result; + result.addresses = absl::UnavailableError("injected error"); + logical_dns_cluster_resolver_response_generator_->SetResponse( + std::move(result)); + } + // When an RPC fails, we know the channel has seen the update. + CheckRpcSendFailure(); + // Send an EDS update that moves locality1 to priority 0. + args1 = EdsResourceArgs({ + {"locality1", CreateEndpointsForBackends(0, 1), kDefaultLocalityWeight, + 0}, + {"locality2", CreateEndpointsForBackends(1, 2), kDefaultLocalityWeight, + 1}, + }); + balancer_->ads_service()->SetEdsResource( + BuildEdsResource(args1, kNewEdsService1Name)); + WaitForBackend(0, WaitForBackendOptions().set_allow_failures(true)); + gpr_unsetenv( + "GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER"); +} + +TEST_P(CdsTest, AggregateClusterMultipleClustersWithSameLocalities) { + gpr_setenv("GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER", + "true"); + const char* kNewClusterName1 = "new_cluster_1"; + const char* kNewEdsServiceName1 = "new_eds_service_name_1"; + const char* kNewClusterName2 = "new_cluster_2"; + const char* kNewEdsServiceName2 = "new_eds_service_name_2"; + // Populate EDS resource for cluster 1 with unreachable endpoint. + EdsResourceArgs args1({{"locality0", {MakeNonExistantEndpoint()}}}); + balancer_->ads_service()->SetEdsResource( + BuildEdsResource(args1, kNewEdsServiceName1)); + // Populate CDS resource for cluster 1. + Cluster new_cluster1 = default_cluster_; + new_cluster1.set_name(kNewClusterName1); + new_cluster1.mutable_eds_cluster_config()->set_service_name( + kNewEdsServiceName1); + balancer_->ads_service()->SetCdsResource(new_cluster1); + // Populate EDS resource for cluster 2. + args1 = EdsResourceArgs({{"locality1", CreateEndpointsForBackends(0, 1)}}); + balancer_->ads_service()->SetEdsResource( + BuildEdsResource(args1, kNewEdsServiceName2)); + // Populate CDS resource for cluster 2. + Cluster new_cluster2 = default_cluster_; + new_cluster2.set_name(kNewClusterName2); + new_cluster2.mutable_eds_cluster_config()->set_service_name( + kNewEdsServiceName2); + balancer_->ads_service()->SetCdsResource(new_cluster2); + // Create Aggregate Cluster + auto cluster = default_cluster_; + CustomClusterType* custom_cluster = cluster.mutable_cluster_type(); + custom_cluster->set_name("envoy.clusters.aggregate"); + ClusterConfig cluster_config; + cluster_config.add_clusters(kNewClusterName1); + cluster_config.add_clusters(kNewClusterName2); + custom_cluster->mutable_typed_config()->PackFrom(cluster_config); + balancer_->ads_service()->SetCdsResource(cluster); + // Wait for channel to get the resources and get connected. + WaitForBackend(0); + // Send an EDS update for cluster 1 that reuses the locality name from + // cluster 1 and points traffic to backend 1. + args1 = EdsResourceArgs({{"locality1", CreateEndpointsForBackends(1, 2)}}); + balancer_->ads_service()->SetEdsResource( + BuildEdsResource(args1, kNewEdsServiceName1)); + WaitForBackend(1); + gpr_unsetenv( + "GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER"); +} + // Test that CDS client should send a NACK if cluster type is Logical DNS but // the feature is not yet supported. TEST_P(CdsTest, LogicalDNSClusterTypeDisabled) { @@ -7493,6 +7633,302 @@ TEST_P(CdsTest, RingHashPolicyHasInvalidRingSizeMinGreaterThanMax) { "min_ring_size cannot be greater than max_ring_size.")); } +class RlsTest : public XdsEnd2endTest { + protected: + class RlsServerThread : public ServerThread { + public: + explicit RlsServerThread(XdsEnd2endTest* test_obj) + : ServerThread(test_obj, /*use_xds_enabled_server=*/false), + rls_service_(new RlsServiceImpl()) {} + + RlsServiceImpl* rls_service() { return rls_service_.get(); } + + private: + void RegisterAllServices(ServerBuilder* builder) override { + builder->RegisterService(rls_service_.get()); + } + + void StartAllServices() override { rls_service_->Start(); } + + void ShutdownAllServices() override { rls_service_->Shutdown(); } + + const char* Type() override { return "Rls"; } + + std::shared_ptr rls_service_; + }; + + RlsTest() : XdsEnd2endTest(4) { + rls_server_ = absl::make_unique(this); + rls_server_->Start(); + } + + void SetUp() override { + XdsEnd2endTest::SetUp(); + StartAllBackends(); + } + + void TearDown() override { + rls_server_->Shutdown(); + XdsEnd2endTest::TearDown(); + } + + std::unique_ptr rls_server_; +}; + +TEST_P(RlsTest, XdsRoutingClusterSpecifierPlugin) { + gpr_setenv("GRPC_EXPERIMENTAL_XDS_RLS_LB", "true"); + const char* kNewClusterName = "new_cluster"; + const char* kNewEdsServiceName = "new_eds_service_name"; + const size_t kNumEchoRpcs = 5; + // Populate new EDS resources. + EdsResourceArgs args({ + {"locality0", CreateEndpointsForBackends(0, 1)}, + }); + EdsResourceArgs args1({ + {"locality0", CreateEndpointsForBackends(1, 2)}, + }); + balancer_->ads_service()->SetEdsResource(BuildEdsResource(args)); + balancer_->ads_service()->SetEdsResource( + BuildEdsResource(args1, kNewEdsServiceName)); + // Populate new CDS resources. + Cluster new_cluster = default_cluster_; + new_cluster.set_name(kNewClusterName); + new_cluster.mutable_eds_cluster_config()->set_service_name( + kNewEdsServiceName); + balancer_->ads_service()->SetCdsResource(new_cluster); + // Prepare the RLSLookupConfig and configure all the keys; change route + // configurations to use cluster specifier plugin. + rls_server_->rls_service()->SetResponse( + BuildRlsRequest({{kRlsTestKey, kRlsTestValue}, + {kRlsHostKey, kServerName}, + {kRlsServiceKey, kRlsServiceValue}, + {kRlsMethodKey, kRlsMethodValue}, + {kRlsConstantKey, kRlsConstantValue}}), + BuildRlsResponse({kNewClusterName})); + RouteLookupConfig route_lookup_config; + auto* key_builder = route_lookup_config.add_grpc_keybuilders(); + auto* name = key_builder->add_names(); + name->set_service(kRlsServiceValue); + name->set_method(kRlsMethodValue); + auto* header = key_builder->add_headers(); + header->set_key(kRlsTestKey); + header->add_names(kRlsTestKey1); + header->add_names("key2"); + auto* extra_keys = key_builder->mutable_extra_keys(); + extra_keys->set_host(kRlsHostKey); + extra_keys->set_service(kRlsServiceKey); + extra_keys->set_method(kRlsMethodKey); + (*key_builder->mutable_constant_keys())[kRlsConstantKey] = kRlsConstantValue; + route_lookup_config.set_lookup_service( + absl::StrCat("localhost:", rls_server_->port())); + route_lookup_config.set_cache_size_bytes(5000); + RouteLookupClusterSpecifier rls; + *rls.mutable_route_lookup_config() = std::move(route_lookup_config); + RouteConfiguration new_route_config = default_route_config_; + auto* plugin = new_route_config.add_cluster_specifier_plugins(); + plugin->mutable_extension()->set_name(kRlsClusterSpecifierPluginInstanceName); + plugin->mutable_extension()->mutable_typed_config()->PackFrom(rls); + auto* default_route = + new_route_config.mutable_virtual_hosts(0)->mutable_routes(0); + default_route->mutable_route()->set_cluster_specifier_plugin( + kRlsClusterSpecifierPluginInstanceName); + SetRouteConfiguration(balancer_.get(), new_route_config); + auto rpc_options = RpcOptions().set_metadata({{kRlsTestKey1, kRlsTestValue}}); + WaitForAllBackends(1, 2, WaitForBackendOptions(), rpc_options); + CheckRpcSendOk(kNumEchoRpcs, rpc_options); + // Make sure RPCs all go to the correct backend. + EXPECT_EQ(kNumEchoRpcs, backends_[1]->backend_service()->request_count()); + gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_XDS_RLS_LB"); +} + +TEST_P(RlsTest, XdsRoutingClusterSpecifierPluginNacksUndefinedSpecifier) { + gpr_setenv("GRPC_EXPERIMENTAL_XDS_RLS_LB", "true"); + const char* kNewClusterName = "new_cluster"; + const char* kNewEdsServiceName = "new_eds_service_name"; + // Populate new EDS resources. + EdsResourceArgs args({ + {"locality0", CreateEndpointsForBackends(0, 1)}, + }); + EdsResourceArgs args1({ + {"locality0", CreateEndpointsForBackends(1, 2)}, + }); + balancer_->ads_service()->SetEdsResource(BuildEdsResource(args)); + balancer_->ads_service()->SetEdsResource( + BuildEdsResource(args1, kNewEdsServiceName)); + // Populate new CDS resources. + Cluster new_cluster = default_cluster_; + new_cluster.set_name(kNewClusterName); + new_cluster.mutable_eds_cluster_config()->set_service_name( + kNewEdsServiceName); + balancer_->ads_service()->SetCdsResource(new_cluster); + RouteConfiguration new_route_config = default_route_config_; + auto* default_route = + new_route_config.mutable_virtual_hosts(0)->mutable_routes(0); + // Set Cluster Specifier Plugin to something that does not exist. + default_route->mutable_route()->set_cluster_specifier_plugin( + kRlsClusterSpecifierPluginInstanceName); + SetRouteConfiguration(balancer_.get(), new_route_config); + const auto response_state = WaitForRdsNack(); + ASSERT_TRUE(response_state.has_value()) << "timed out waiting for NACK"; + EXPECT_THAT(response_state->error_message, + ::testing::HasSubstr("RouteAction cluster contains cluster " + "specifier plugin name not configured.")); + gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_XDS_RLS_LB"); +} + +TEST_P(RlsTest, XdsRoutingClusterSpecifierPluginNacksUnknownSpecifierProto) { + // TODO(donnadionne): Doug is working on adding a new is_optional field to + // ClusterSpecifierPlugin in envoyproxy/envoy#20301. Once that goes in, the + // behavior we want in this case is that if is_optional is true, then we + // ignore that plugin and ignore any routes that refer to that plugin. + // However, if is_optional is false, then we want to NACK. + gpr_setenv("GRPC_EXPERIMENTAL_XDS_RLS_LB", "true"); + const char* kNewClusterName = "new_cluster"; + const char* kNewEdsServiceName = "new_eds_service_name"; + // Populate new EDS resources. + EdsResourceArgs args({ + {"locality0", CreateEndpointsForBackends(0, 1)}, + }); + EdsResourceArgs args1({ + {"locality0", CreateEndpointsForBackends(1, 2)}, + }); + balancer_->ads_service()->SetEdsResource(BuildEdsResource(args)); + balancer_->ads_service()->SetEdsResource( + BuildEdsResource(args1, kNewEdsServiceName)); + // Populate new CDS resources. + Cluster new_cluster = default_cluster_; + new_cluster.set_name(kNewClusterName); + new_cluster.mutable_eds_cluster_config()->set_service_name( + kNewEdsServiceName); + balancer_->ads_service()->SetCdsResource(new_cluster); + // Prepare the RLSLookupConfig: change route configurations to use cluster + // specifier plugin. + RouteLookupConfig route_lookup_config; + RouteConfiguration new_route_config = default_route_config_; + auto* plugin = new_route_config.add_cluster_specifier_plugins(); + plugin->mutable_extension()->set_name(kRlsClusterSpecifierPluginInstanceName); + // Instead of grpc.lookup.v1.RouteLookupClusterSpecifier, let's say we + // mistakenly packed the inner RouteLookupConfig instead. + plugin->mutable_extension()->mutable_typed_config()->PackFrom( + route_lookup_config); + auto* default_route = + new_route_config.mutable_virtual_hosts(0)->mutable_routes(0); + default_route->mutable_route()->set_cluster_specifier_plugin( + kRlsClusterSpecifierPluginInstanceName); + SetRouteConfiguration(balancer_.get(), new_route_config); + const auto response_state = WaitForRdsNack(); + ASSERT_TRUE(response_state.has_value()) << "timed out waiting for NACK"; + EXPECT_THAT( + response_state->error_message, + ::testing::HasSubstr( + "Unable to locate the cluster specifier plugin in the registry")); + gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_XDS_RLS_LB"); +} + +TEST_P(RlsTest, XdsRoutingRlsClusterSpecifierPluginNacksRequiredMatch) { + gpr_setenv("GRPC_EXPERIMENTAL_XDS_RLS_LB", "true"); + const char* kNewClusterName = "new_cluster"; + const char* kNewEdsServiceName = "new_eds_service_name"; + // Populate new EDS resources. + EdsResourceArgs args({ + {"locality0", CreateEndpointsForBackends(0, 1)}, + }); + EdsResourceArgs args1({ + {"locality0", CreateEndpointsForBackends(1, 2)}, + }); + balancer_->ads_service()->SetEdsResource(BuildEdsResource(args)); + balancer_->ads_service()->SetEdsResource( + BuildEdsResource(args1, kNewEdsServiceName)); + // Populate new CDS resources. + Cluster new_cluster = default_cluster_; + new_cluster.set_name(kNewClusterName); + new_cluster.mutable_eds_cluster_config()->set_service_name( + kNewEdsServiceName); + balancer_->ads_service()->SetCdsResource(new_cluster); + // Prepare the RLSLookupConfig and configure all the keys; add required_match + // field which should not be there. + RouteLookupConfig route_lookup_config; + auto* key_builder = route_lookup_config.add_grpc_keybuilders(); + auto* name = key_builder->add_names(); + name->set_service(kRlsServiceValue); + name->set_method(kRlsMethodValue); + auto* header = key_builder->add_headers(); + header->set_key(kRlsTestKey); + header->add_names(kRlsTestKey1); + header->set_required_match(true); + route_lookup_config.set_lookup_service( + absl::StrCat("localhost:", rls_server_->port())); + route_lookup_config.set_cache_size_bytes(5000); + RouteLookupClusterSpecifier rls; + *rls.mutable_route_lookup_config() = std::move(route_lookup_config); + RouteConfiguration new_route_config = default_route_config_; + auto* plugin = new_route_config.add_cluster_specifier_plugins(); + plugin->mutable_extension()->set_name(kRlsClusterSpecifierPluginInstanceName); + plugin->mutable_extension()->mutable_typed_config()->PackFrom(rls); + auto* default_route = + new_route_config.mutable_virtual_hosts(0)->mutable_routes(0); + default_route->mutable_route()->set_cluster_specifier_plugin( + kRlsClusterSpecifierPluginInstanceName); + SetRouteConfiguration(balancer_.get(), new_route_config); + const auto response_state = WaitForRdsNack(); + ASSERT_TRUE(response_state.has_value()) << "timed out waiting for NACK"; + EXPECT_THAT( + response_state->error_message, + ::testing::HasSubstr("field:requiredMatch error:must not be present")); + gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_XDS_RLS_LB"); +} + +TEST_P(RlsTest, XdsRoutingClusterSpecifierPluginDisabled) { + const char* kNewClusterName = "new_cluster"; + const char* kNewEdsServiceName = "new_eds_service_name"; + // Populate new EDS resources. + EdsResourceArgs args({ + {"locality0", CreateEndpointsForBackends(0, 1)}, + }); + EdsResourceArgs args1({ + {"locality0", CreateEndpointsForBackends(1, 2)}, + }); + balancer_->ads_service()->SetEdsResource(BuildEdsResource(args)); + balancer_->ads_service()->SetEdsResource( + BuildEdsResource(args1, kNewEdsServiceName)); + // Populate new CDS resources. + Cluster new_cluster = default_cluster_; + new_cluster.set_name(kNewClusterName); + new_cluster.mutable_eds_cluster_config()->set_service_name( + kNewEdsServiceName); + balancer_->ads_service()->SetCdsResource(new_cluster); + // Prepare the RLSLookupConfig and configure all the keys; change route + // configurations to use cluster specifier plugin. + RouteLookupConfig route_lookup_config; + auto* key_builder = route_lookup_config.add_grpc_keybuilders(); + auto* name = key_builder->add_names(); + name->set_service(kRlsServiceValue); + name->set_method(kRlsMethodValue); + auto* header = key_builder->add_headers(); + header->set_key(kRlsTestKey); + header->add_names(kRlsTestKey1); + route_lookup_config.set_lookup_service( + absl::StrCat("localhost:", rls_server_->port())); + route_lookup_config.set_cache_size_bytes(5000); + RouteLookupClusterSpecifier rls; + *rls.mutable_route_lookup_config() = std::move(route_lookup_config); + RouteConfiguration new_route_config = default_route_config_; + auto* plugin = new_route_config.add_cluster_specifier_plugins(); + plugin->mutable_extension()->set_name(kRlsClusterSpecifierPluginInstanceName); + plugin->mutable_extension()->mutable_typed_config()->PackFrom(rls); + auto* route = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0); + route->mutable_route()->set_cluster_specifier_plugin( + kRlsClusterSpecifierPluginInstanceName); + auto* default_route = new_route_config.mutable_virtual_hosts(0)->add_routes(); + default_route->mutable_match()->set_prefix(""); + default_route->mutable_route()->set_cluster(kDefaultClusterName); + SetRouteConfiguration(balancer_.get(), new_route_config); + // Ensure we ignore the cluster specifier plugin and send traffic according to + // the default route. + auto rpc_options = RpcOptions().set_metadata({{kRlsTestKey1, kRlsTestValue}}); + WaitForAllBackends(0, 1, WaitForBackendOptions(), rpc_options); +} + class XdsSecurityTest : public BasicTest { protected: void SetUp() override { @@ -13465,6 +13901,14 @@ INSTANTIATE_TEST_SUITE_P( TestType().set_enable_rds_testing().set_use_v2()), &TestTypeName); +// Rls tests depend on XdsResolver. +INSTANTIATE_TEST_SUITE_P( + XdsTest, RlsTest, + ::testing::Values(TestType(), TestType().set_enable_rds_testing(), + // Also test with xDS v2. + TestType().set_enable_rds_testing().set_use_v2()), + &TestTypeName); + // CDS depends on XdsResolver. INSTANTIATE_TEST_SUITE_P( XdsTest, CdsTest, diff --git a/test/cpp/ext/filters/census/BUILD b/test/cpp/ext/filters/census/BUILD index 0a243484168..538ad7e72ec 100644 --- a/test/cpp/ext/filters/census/BUILD +++ b/test/cpp/ext/filters/census/BUILD @@ -37,6 +37,7 @@ grpc_cc_test( "//:grpc_opencensus_plugin", "//src/proto/grpc/testing:echo_proto", "//test/core/util:grpc_test_util", + "//test/cpp/end2end:test_service_impl", "//test/cpp/util:test_config", "//test/cpp/util:test_util", ], diff --git a/test/cpp/ext/filters/census/stats_plugin_end2end_test.cc b/test/cpp/ext/filters/census/stats_plugin_end2end_test.cc index 4ad28aefc8d..d7d0e1d1cf5 100644 --- a/test/cpp/ext/filters/census/stats_plugin_end2end_test.cc +++ b/test/cpp/ext/filters/census/stats_plugin_end2end_test.cc @@ -37,6 +37,7 @@ #include "src/cpp/ext/filters/census/grpc_plugin.h" #include "src/proto/grpc/testing/echo.grpc.pb.h" #include "test/core/util/test_config.h" +#include "test/cpp/end2end/test_service_impl.h" namespace grpc { namespace testing { @@ -54,12 +55,25 @@ const auto TEST_TAG_KEY = TagKey::Register("my_key"); const auto TEST_TAG_VALUE = "my_value"; const char* kExpectedTraceIdKey = "expected_trace_id"; -class EchoServer final : public EchoTestService::Service { - grpc::Status Echo(grpc::ServerContext* context, const EchoRequest* request, - EchoResponse* response) override { +class EchoServer final : public TestServiceImpl { + Status Echo(ServerContext* context, const EchoRequest* request, + EchoResponse* response) override { + CheckMetadata(context); + return TestServiceImpl::Echo(context, request, response); + } + + Status BidiStream( + ServerContext* context, + ServerReaderWriter* stream) override { + CheckMetadata(context); + return TestServiceImpl::BidiStream(context, stream); + } + + private: + void CheckMetadata(ServerContext* context) { for (const auto& metadata : context->client_metadata()) { if (metadata.first == kExpectedTraceIdKey) { - EXPECT_EQ(metadata.second, reinterpret_cast( + EXPECT_EQ(metadata.second, reinterpret_cast( context->census_context()) ->Span() .context() @@ -68,14 +82,6 @@ class EchoServer final : public EchoTestService::Service { break; } } - if (request->param().expected_error().code() == 0) { - response->set_message(request->message()); - return grpc::Status::OK; - } else { - return grpc::Status(static_cast( - request->param().expected_error().code()), - ""); - } } }; @@ -374,6 +380,20 @@ TEST_F(StatsPluginEnd2EndTest, CompletedRpcs) { ::testing::UnorderedElementsAre(::testing::Pair( ::testing::ElementsAre(server_method_name_, "OK"), i + 1))); } + + // Client should see calls that are cancelled without calling Finish(). + { + ClientContext ctx; + auto stream = stub_->BidiStream(&ctx); + ctx.TryCancel(); + } + absl::SleepFor(absl::Milliseconds(500)); + TestUtils::Flush(); + EXPECT_THAT(client_completed_rpcs_view.GetData().int_data(), + ::testing::Contains(::testing::Pair( + ::testing::ElementsAre( + "grpc.testing.EchoTestService/BidiStream", "CANCELLED"), + 1))); } TEST_F(StatsPluginEnd2EndTest, RequestReceivedMessagesPerRpc) { @@ -472,7 +492,6 @@ TEST_F(StatsPluginEnd2EndTest, TestRetryStatsWithAdditionalRetries) { ClientTransparentRetriesCumulative()); View client_retry_delay_per_call_view(ClientRetryDelayPerCallCumulative()); ChannelArguments args; - args.SetInt(GRPC_ARG_ENABLE_RETRIES, 1); args.SetString(GRPC_ARG_SERVICE_CONFIG, "{\n" " \"methodConfig\": [ {\n" diff --git a/test/distrib/bazel/cpp/BUILD b/test/distrib/bazel/cpp/BUILD new file mode 100644 index 00000000000..0869e63f20c --- /dev/null +++ b/test/distrib/bazel/cpp/BUILD @@ -0,0 +1,43 @@ +# 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. + +licenses(["notice"]) + +cc_binary( + name = "greeter_client", + srcs = ["greeter_client.cc"], + deps = [ + "//protos:helloworld_cc_grpc", + "@com_github_grpc_grpc//:grpc++", + ], +) + +cc_binary( + name = "greeter_server", + srcs = ["greeter_server.cc"], + deps = [ + "//protos:helloworld_cc_grpc", + "@com_github_grpc_grpc//:grpc++", + "@com_github_grpc_grpc//:grpc++_reflection", + ], +) + +sh_test( + name = "greeter_test", + srcs = ["greeter_test.sh"], + data = [ + ":greeter_client", + ":greeter_server", + ], +) diff --git a/test/distrib/bazel/cpp/WORKSPACE b/test/distrib/bazel/cpp/WORKSPACE new file mode 100644 index 00000000000..4b7644085ee --- /dev/null +++ b/test/distrib/bazel/cpp/WORKSPACE @@ -0,0 +1,27 @@ +# 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_repository( + name = "com_github_grpc_grpc", + path = "../../../..", +) + +workspace(name = "bazel_cpp_distribtests") + +load("@com_github_grpc_grpc//bazel:grpc_deps.bzl", "grpc_deps") + +grpc_deps() + +load("@com_github_grpc_grpc//bazel:grpc_extra_deps.bzl", "grpc_extra_deps") + +grpc_extra_deps() diff --git a/test/distrib/bazel/cpp/greeter_client.cc b/test/distrib/bazel/cpp/greeter_client.cc new file mode 100644 index 00000000000..75597c1f21e --- /dev/null +++ b/test/distrib/bazel/cpp/greeter_client.cc @@ -0,0 +1,104 @@ +/* + * + * 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. + * + */ + +#include +#include +#include + +#include + +#include "protos/helloworld.grpc.pb.h" + +using grpc::Channel; +using grpc::ClientContext; +using grpc::Status; +using helloworld::Greeter; +using helloworld::HelloReply; +using helloworld::HelloRequest; + +class GreeterClient { + public: + GreeterClient(std::shared_ptr channel) + : stub_(Greeter::NewStub(channel)) {} + + // Assembles the client's payload, sends it and presents the response back + // from the server. + std::string SayHello(const std::string& user) { + // Data we are sending to the server. + HelloRequest request; + request.set_name(user); + + // Container for the data we expect from the server. + HelloReply reply; + + // Context for the client. It could be used to convey extra information to + // the server and/or tweak certain RPC behaviors. + ClientContext context; + + // The actual RPC. + Status status = stub_->SayHello(&context, request, &reply); + + // Act upon its status. + if (status.ok()) { + return reply.message(); + } else { + std::cout << status.error_code() << ": " << status.error_message() + << std::endl; + return "RPC failed"; + } + } + + private: + std::unique_ptr stub_; +}; + +int main(int argc, char** argv) { + // Instantiate the client. It requires a channel, out of which the actual RPCs + // are created. This channel models a connection to an endpoint specified by + // the argument "--target=" which is the only expected argument. + // We indicate that the channel isn't authenticated (use of + // InsecureChannelCredentials()). + std::string target_str; + std::string arg_str("--target"); + if (argc > 1) { + std::string arg_val = argv[1]; + size_t start_pos = arg_val.find(arg_str); + if (start_pos != std::string::npos) { + start_pos += arg_str.size(); + if (arg_val[start_pos] == '=') { + target_str = arg_val.substr(start_pos + 1); + } else { + std::cout << "The only correct argument syntax is --target=" + << std::endl; + return 0; + } + } else { + std::cout << "The only acceptable argument is --target=" << std::endl; + return 0; + } + } else { + target_str = "localhost:50051"; + } + GreeterClient greeter( + grpc::CreateChannel(target_str, grpc::InsecureChannelCredentials())); + std::string user("world"); + std::string reply = greeter.SayHello(user); + std::cout << "Greeter received: " << reply << std::endl; + + return 0; +} diff --git a/test/distrib/bazel/cpp/greeter_server.cc b/test/distrib/bazel/cpp/greeter_server.cc new file mode 100644 index 00000000000..f42c9b8bdf5 --- /dev/null +++ b/test/distrib/bazel/cpp/greeter_server.cc @@ -0,0 +1,73 @@ +/* + * + * 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. + * + */ + +#include +#include +#include + +#include +#include +#include + +#include "protos/helloworld.grpc.pb.h" + +using grpc::Server; +using grpc::ServerBuilder; +using grpc::ServerContext; +using grpc::Status; +using helloworld::Greeter; +using helloworld::HelloReply; +using helloworld::HelloRequest; + +// Logic and data behind the server's behavior. +class GreeterServiceImpl final : public Greeter::Service { + Status SayHello(ServerContext* context, const HelloRequest* request, + HelloReply* reply) override { + std::string prefix("Hello "); + reply->set_message(prefix + request->name()); + return Status::OK; + } +}; + +void RunServer() { + std::string server_address("0.0.0.0:0"); + GreeterServiceImpl service; + + grpc::EnableDefaultHealthCheckService(true); + grpc::reflection::InitProtoReflectionServerBuilderPlugin(); + ServerBuilder builder; + // Listen on the given address without any authentication mechanism. + int bound_port; + builder.AddListeningPort(server_address, grpc::InsecureServerCredentials(), &bound_port); + // Register "service" as the instance through which we'll communicate with + // clients. In this case it corresponds to an *synchronous* service. + builder.RegisterService(&service); + // Finally assemble the server. + std::unique_ptr server(builder.BuildAndStart()); + std::cout << "127.0.0.1:" << bound_port << std::endl; + + // Wait for the server to shutdown. Note that some other thread must be + // responsible for shutting down the server for this call to ever return. + server->Wait(); +} + +int main(int argc, char** argv) { + RunServer(); + + return 0; +} diff --git a/test/distrib/bazel/cpp/greeter_test.sh b/test/distrib/bazel/cpp/greeter_test.sh new file mode 100755 index 00000000000..92f6233e6ae --- /dev/null +++ b/test/distrib/bazel/cpp/greeter_test.sh @@ -0,0 +1,61 @@ +#!/usr/bin/env bash +# 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. + +set -exo pipefail + +SERVER_PID="" +SERVER_TIMEOUT=10 + +SERVER_OUTPUT=$(mktemp) + +function cleanup() { + if [ -n "$SERVER_PID" ]; then + kill "$SERVER_PID" + fi +} + +function fail() { + echo "$1" >/dev/stderr + echo "Failed." >/dev/stderr + exit 1 +} + +function await_server() { + TIME=0 + while [ ! -s "$SERVER_OUTPUT" ]; do + if [ "$TIME" == "$SERVER_TIMEOUT" ] ; then + fail "Server not listening after $SERVER_TIMEOUT seconds." + fi + sleep 1 + TIME=$((TIME+1)) + done + cat "$SERVER_OUTPUT" +} + +trap cleanup SIGINT SIGTERM EXIT + +./greeter_server >"$SERVER_OUTPUT" & +SERVER_PID=$! + +SERVER_ADDRESS=$(await_server) + +RESPONSE=$(./greeter_client --target="$SERVER_ADDRESS") +EXPECTED_RESPONSE="Greeter received: Hello world" + +if [ "$RESPONSE" != "$EXPECTED_RESPONSE" ]; then + fail "Received response \"$RESPONSE\" but expected \"$EXPECTED_RESPONSE\"" +fi + +echo "Success." diff --git a/test/distrib/bazel/cpp/protos/BUILD b/test/distrib/bazel/cpp/protos/BUILD new file mode 100644 index 00000000000..5923542b55c --- /dev/null +++ b/test/distrib/bazel/cpp/protos/BUILD @@ -0,0 +1,37 @@ +# 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. + +load("@rules_proto//proto:defs.bzl", "proto_library") +load("@com_github_grpc_grpc//bazel:cc_grpc_library.bzl", "cc_grpc_library") + +licenses(["notice"]) + +package(default_visibility = ["//:__subpackages__"]) + +proto_library( + name = "helloworld_proto", + srcs = ["helloworld.proto"], +) + +cc_proto_library( + name = "helloworld_cc_proto", + deps = [":helloworld_proto"], +) + +cc_grpc_library( + name = "helloworld_cc_grpc", + srcs = [":helloworld_proto"], + grpc_only = True, + deps = [":helloworld_cc_proto"], +) diff --git a/test/distrib/bazel/cpp/protos/helloworld.proto b/test/distrib/bazel/cpp/protos/helloworld.proto new file mode 100644 index 00000000000..be878ce25ff --- /dev/null +++ b/test/distrib/bazel/cpp/protos/helloworld.proto @@ -0,0 +1,38 @@ +// Copyright 2015 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. + +syntax = "proto3"; + +option java_multiple_files = true; +option java_package = "io.grpc.examples.helloworld"; +option java_outer_classname = "HelloWorldProto"; +option objc_class_prefix = "HLW"; + +package helloworld; + +// The greeting service definition. +service Greeter { + // Sends a greeting + rpc SayHello (HelloRequest) returns (HelloReply) {} +} + +// The request message containing the user's name. +message HelloRequest { + string name = 1; +} + +// The response message containing the greetings +message HelloReply { + string message = 1; +} diff --git a/test/distrib/bazel/cpp/tools/bazel b/test/distrib/bazel/cpp/tools/bazel new file mode 120000 index 00000000000..e50c110d3a8 --- /dev/null +++ b/test/distrib/bazel/cpp/tools/bazel @@ -0,0 +1 @@ +../../../../../tools/bazel \ No newline at end of file diff --git a/test/distrib/bazel/run_bazel_distrib_test.sh b/test/distrib/bazel/run_bazel_distrib_test.sh index 534651f66de..347417a7bd1 100755 --- a/test/distrib/bazel/run_bazel_distrib_test.sh +++ b/test/distrib/bazel/run_bazel_distrib_test.sh @@ -18,20 +18,16 @@ set -ex cd "$(dirname "$0")" # TODO(jtattermusch): make build work with bazel 2.2.0 and bazel 1.2.1 if that's reasonably simple. -SUPPORTED_VERSIONS=( - "3.7.2" - "4.0.0" - "5.0.0" -) +VERSIONS=$(cat ../../../bazel/supported_versions.txt) FAILED_VERSIONS="" -for VERSION in "${SUPPORTED_VERSIONS[@]}"; do +for VERSION in $VERSIONS; do echo "Running bazel distribtest with bazel version ${VERSION}" ./test_single_bazel_version.sh "${VERSION}" || FAILED_VERSIONS="${FAILED_VERSIONS}${VERSION} " done if [ "$FAILED_VERSIONS" != "" ] then - echo "Bazel distribtest failed: Failed to build with bazel versions ${FAILED_VERSIONS}" + echo "Bazel distribtest failed: Failing versions: ${FAILED_VERSIONS}" exit 1 fi diff --git a/test/distrib/bazel/test_single_bazel_version.sh b/test/distrib/bazel/test_single_bazel_version.sh index ef338c9349b..0fa68425411 100755 --- a/test/distrib/bazel/test_single_bazel_version.sh +++ b/test/distrib/bazel/test_single_bazel_version.sh @@ -41,7 +41,19 @@ EXCLUDED_TARGETS=( "-//examples/android/binder/..." ) +FAILED_TESTS="" + export OVERRIDE_BAZEL_VERSION="$VERSION" # when running under bazel docker image, the workspace is read only. export OVERRIDE_BAZEL_WRAPPER_DOWNLOAD_DIR=/tmp -bazel build -- //... "${EXCLUDED_TARGETS[@]}" +bazel build -- //... "${EXCLUDED_TARGETS[@]}" || FAILED_TESTS="${FAILED_TESTS}Build " + +cd test/distrib/bazel/cpp/ + +bazel test //:all || FAILED_TESTS="${FAILED_TESTS}C++ Distribtest" + +if [ "$FAILED_TESTS" != "" ] +then + echo "Failed tests at version ${VERSION}: ${FAILED_TESTS}" + exit 1 +fi diff --git a/tools/buildgen/plugins/supported_bazel_versions.py b/tools/buildgen/plugins/supported_bazel_versions.py new file mode 100644 index 00000000000..8d2d980cd3f --- /dev/null +++ b/tools/buildgen/plugins/supported_bazel_versions.py @@ -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. +"""Retrieves supported bazel versions from plaintext file.""" + +_SUPPORTED_VERSIONS_FILE = "bazel/supported_versions.txt" + + +def _get_supported_bazel_versions(): + versions = [] + with open(_SUPPORTED_VERSIONS_FILE, "r") as f: + for line in f: + versions.append(line.strip()) + return versions + + +def mako_plugin(dictionary): + dictionary["supported_bazel_versions"] = _get_supported_bazel_versions() diff --git a/tools/dockerfile/test/python_debian11_default_x64/Dockerfile b/tools/dockerfile/test/python_debian11_default_x64/Dockerfile index 45c8db09c32..67a3acf1324 100644 --- a/tools/dockerfile/test/python_debian11_default_x64/Dockerfile +++ b/tools/dockerfile/test/python_debian11_default_x64/Dockerfile @@ -58,84 +58,84 @@ RUN mkdir /var/local/jenkins #================= -# Compile CPython 3.6.9 from source +# Compile CPython 3.6.15 from source RUN apt-get update && apt-get install -y zlib1g-dev libssl-dev && apt-get clean RUN apt-get update && apt-get install -y jq build-essential libffi-dev && apt-get clean RUN cd /tmp && \ - wget -q https://www.python.org/ftp/python/3.6.9/Python-3.6.9.tgz && \ - tar xzvf Python-3.6.9.tgz && \ - cd Python-3.6.9 && \ + wget -q https://www.python.org/ftp/python/3.6.15/Python-3.6.15.tgz && \ + tar xzvf Python-3.6.15.tgz && \ + cd Python-3.6.15 && \ ./configure && \ make -j4 && \ make install RUN cd /tmp && \ - echo "ff7cdaef4846c89c1ec0d7b709bbd54d Python-3.6.9.tgz" > checksum.md5 && \ + echo "f9e6f91c754a604f4fc6f6c7683723fb Python-3.6.15.tgz" > checksum.md5 && \ md5sum -c checksum.md5 RUN python3.6 -m ensurepip && \ python3.6 -m pip install coverage #================= -# Compile CPython 3.7.12 from source +# Compile CPython 3.7.13 from source RUN apt-get update && apt-get install -y zlib1g-dev libssl-dev && apt-get clean RUN apt-get update && apt-get install -y jq build-essential libffi-dev && apt-get clean RUN cd /tmp && \ - wget -q https://www.python.org/ftp/python/3.7.12/Python-3.7.12.tgz && \ - tar xzvf Python-3.7.12.tgz && \ - cd Python-3.7.12 && \ + wget -q https://www.python.org/ftp/python/3.7.13/Python-3.7.13.tgz && \ + tar xzvf Python-3.7.13.tgz && \ + cd Python-3.7.13 && \ ./configure && \ make -j4 && \ make install RUN cd /tmp && \ - echo "6fe83678c085a7735a943cf1e4d41c14 Python-3.7.12.tgz" > checksum.md5 && \ + echo "e0d3321026d4a5f3a3890b5d821ad762 Python-3.7.13.tgz" > checksum.md5 && \ md5sum -c checksum.md5 RUN python3.7 -m ensurepip && \ python3.7 -m pip install coverage #================= -# Compile CPython 3.8.0b4 from source +# Compile CPython 3.8.13 from source RUN apt-get update && apt-get install -y zlib1g-dev libssl-dev && apt-get clean RUN apt-get update && apt-get install -y jq build-essential libffi-dev && apt-get clean RUN cd /tmp && \ - wget -q https://www.python.org/ftp/python/3.8.0/Python-3.8.0b4.tgz && \ - tar xzvf Python-3.8.0b4.tgz && \ - cd Python-3.8.0b4 && \ + wget -q https://www.python.org/ftp/python/3.8.13/Python-3.8.13.tgz && \ + tar xzvf Python-3.8.13.tgz && \ + cd Python-3.8.13 && \ ./configure && \ make -j4 && \ make install RUN cd /tmp && \ - echo "b8f4f897df967014ddb42033b90c3058 Python-3.8.0b4.tgz" > checksum.md5 && \ + echo "3c49180c6b43df3519849b7e390af0b9 Python-3.8.13.tgz" > checksum.md5 && \ md5sum -c checksum.md5 RUN python3.8 -m ensurepip && \ python3.8 -m pip install coverage #================= -# Compile CPython 3.10.2 from source +# Compile CPython 3.10.3 from source RUN apt-get update && apt-get install -y zlib1g-dev libssl-dev && apt-get clean RUN apt-get update && apt-get install -y jq build-essential libffi-dev && apt-get clean RUN cd /tmp && \ - wget -q https://www.python.org/ftp/python/3.10.2/Python-3.10.2.tgz && \ - tar xzvf Python-3.10.2.tgz && \ - cd Python-3.10.2 && \ + wget -q https://www.python.org/ftp/python/3.10.3/Python-3.10.3.tgz && \ + tar xzvf Python-3.10.3.tgz && \ + cd Python-3.10.3 && \ ./configure && \ make -j4 && \ make install RUN cd /tmp && \ - echo "67c92270be6701f4a6fed57c4530139b Python-3.10.2.tgz" > checksum.md5 && \ + echo "f276ffcd05bccafe46da023d0a5bb04a Python-3.10.3.tgz" > checksum.md5 && \ md5sum -c checksum.md5 RUN python3.10 -m ensurepip && \ diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++ index fa803a34f1a..5ae8e739581 100644 --- a/tools/doxygen/Doxyfile.c++ +++ b/tools/doxygen/Doxyfile.c++ @@ -762,6 +762,7 @@ WARN_LOGFILE = INPUT = doc/PROTOCOL-HTTP2.md \ doc/PROTOCOL-WEB.md \ +doc/bazel_support.md \ doc/binary-logging.md \ doc/c-style-guide.md \ doc/command_line_tool.md \ diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index 41296d921a0..b52a3b61804 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -762,6 +762,7 @@ WARN_LOGFILE = INPUT = doc/PROTOCOL-HTTP2.md \ doc/PROTOCOL-WEB.md \ +doc/bazel_support.md \ doc/binary-logging.md \ doc/c-style-guide.md \ doc/command_line_tool.md \ @@ -1510,6 +1511,8 @@ src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c \ src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.h \ src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls.upb.c \ src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls.upb.h \ +src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls_config.upb.c \ +src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls_config.upb.h \ src/core/ext/upb-generated/udpa/annotations/migrate.upb.c \ src/core/ext/upb-generated/udpa/annotations/migrate.upb.h \ src/core/ext/upb-generated/udpa/annotations/security.upb.c \ @@ -1778,6 +1781,8 @@ src/core/ext/upbdefs-generated/google/rpc/status.upbdefs.c \ src/core/ext/upbdefs-generated/google/rpc/status.upbdefs.h \ src/core/ext/upbdefs-generated/opencensus/proto/trace/v1/trace_config.upbdefs.c \ src/core/ext/upbdefs-generated/opencensus/proto/trace/v1/trace_config.upbdefs.h \ +src/core/ext/upbdefs-generated/src/proto/grpc/lookup/v1/rls_config.upbdefs.c \ +src/core/ext/upbdefs-generated/src/proto/grpc/lookup/v1/rls_config.upbdefs.h \ src/core/ext/upbdefs-generated/udpa/annotations/migrate.upbdefs.c \ src/core/ext/upbdefs-generated/udpa/annotations/migrate.upbdefs.h \ src/core/ext/upbdefs-generated/udpa/annotations/security.upbdefs.c \ @@ -1845,6 +1850,8 @@ src/core/ext/xds/xds_client_stats.cc \ src/core/ext/xds/xds_client_stats.h \ src/core/ext/xds/xds_cluster.cc \ src/core/ext/xds/xds_cluster.h \ +src/core/ext/xds/xds_cluster_specifier_plugin.cc \ +src/core/ext/xds/xds_cluster_specifier_plugin.h \ src/core/ext/xds/xds_common_types.cc \ src/core/ext/xds/xds_common_types.h \ src/core/ext/xds/xds_endpoint.cc \ diff --git a/tools/doxygen/Doxyfile.core b/tools/doxygen/Doxyfile.core index 564e79f2e6c..a68b5f87d02 100644 --- a/tools/doxygen/Doxyfile.core +++ b/tools/doxygen/Doxyfile.core @@ -762,6 +762,7 @@ WARN_LOGFILE = INPUT = doc/PROTOCOL-HTTP2.md \ doc/PROTOCOL-WEB.md \ +doc/bazel_support.md \ doc/binary-logging.md \ doc/c-style-guide.md \ doc/command_line_tool.md \ diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index 00920470885..0af44d7495f 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -762,6 +762,7 @@ WARN_LOGFILE = INPUT = doc/PROTOCOL-HTTP2.md \ doc/PROTOCOL-WEB.md \ +doc/bazel_support.md \ doc/binary-logging.md \ doc/c-style-guide.md \ doc/command_line_tool.md \ @@ -1300,6 +1301,8 @@ src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c \ src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.h \ src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls.upb.c \ src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls.upb.h \ +src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls_config.upb.c \ +src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls_config.upb.h \ src/core/ext/upb-generated/udpa/annotations/migrate.upb.c \ src/core/ext/upb-generated/udpa/annotations/migrate.upb.h \ src/core/ext/upb-generated/udpa/annotations/security.upb.c \ @@ -1568,6 +1571,8 @@ src/core/ext/upbdefs-generated/google/rpc/status.upbdefs.c \ src/core/ext/upbdefs-generated/google/rpc/status.upbdefs.h \ src/core/ext/upbdefs-generated/opencensus/proto/trace/v1/trace_config.upbdefs.c \ src/core/ext/upbdefs-generated/opencensus/proto/trace/v1/trace_config.upbdefs.h \ +src/core/ext/upbdefs-generated/src/proto/grpc/lookup/v1/rls_config.upbdefs.c \ +src/core/ext/upbdefs-generated/src/proto/grpc/lookup/v1/rls_config.upbdefs.h \ src/core/ext/upbdefs-generated/udpa/annotations/migrate.upbdefs.c \ src/core/ext/upbdefs-generated/udpa/annotations/migrate.upbdefs.h \ src/core/ext/upbdefs-generated/udpa/annotations/security.upbdefs.c \ @@ -1635,6 +1640,8 @@ src/core/ext/xds/xds_client_stats.cc \ src/core/ext/xds/xds_client_stats.h \ src/core/ext/xds/xds_cluster.cc \ src/core/ext/xds/xds_cluster.h \ +src/core/ext/xds/xds_cluster_specifier_plugin.cc \ +src/core/ext/xds/xds_cluster_specifier_plugin.h \ src/core/ext/xds/xds_common_types.cc \ src/core/ext/xds/xds_common_types.h \ src/core/ext/xds/xds_endpoint.cc \ diff --git a/tools/doxygen/Doxyfile.objc b/tools/doxygen/Doxyfile.objc index 3760fc2df69..96f9f0a3b9e 100644 --- a/tools/doxygen/Doxyfile.objc +++ b/tools/doxygen/Doxyfile.objc @@ -762,6 +762,7 @@ WARN_LOGFILE = INPUT = doc/PROTOCOL-HTTP2.md \ doc/PROTOCOL-WEB.md \ +doc/bazel_support.md \ doc/binary-logging.md \ doc/c-style-guide.md \ doc/command_line_tool.md \ diff --git a/tools/doxygen/Doxyfile.objc.internal b/tools/doxygen/Doxyfile.objc.internal index b8a60232b1b..b2c1c2d63da 100644 --- a/tools/doxygen/Doxyfile.objc.internal +++ b/tools/doxygen/Doxyfile.objc.internal @@ -762,6 +762,7 @@ WARN_LOGFILE = INPUT = doc/PROTOCOL-HTTP2.md \ doc/PROTOCOL-WEB.md \ +doc/bazel_support.md \ doc/binary-logging.md \ doc/c-style-guide.md \ doc/command_line_tool.md \ diff --git a/tools/doxygen/Doxyfile.php b/tools/doxygen/Doxyfile.php index 0fb063a2b45..ce84cfaf1e9 100644 --- a/tools/doxygen/Doxyfile.php +++ b/tools/doxygen/Doxyfile.php @@ -762,6 +762,7 @@ WARN_LOGFILE = INPUT = doc/PROTOCOL-HTTP2.md \ doc/PROTOCOL-WEB.md \ +doc/bazel_support.md \ doc/binary-logging.md \ doc/c-style-guide.md \ doc/command_line_tool.md \ diff --git a/tools/internal_ci/helper_scripts/install_python_interpreters.ps1 b/tools/internal_ci/helper_scripts/install_python_interpreters.ps1 index f0e0e6a61c7..262f93b4ebc 100644 --- a/tools/internal_ci/helper_scripts/install_python_interpreters.ps1 +++ b/tools/internal_ci/helper_scripts/install_python_interpreters.ps1 @@ -63,51 +63,51 @@ function Install-Python { # Python 3.8 $Python38x86Config = @{ - PythonVersion = "3.8.0" - PythonInstaller = "python-3.8.0" + PythonVersion = "3.8.10" + PythonInstaller = "python-3.8.10" PythonInstallPath = "C:\Python38_32bit" - PythonInstallerHash = "412a649d36626d33b8ca5593cf18318c" + PythonInstallerHash = "b355cfc84b681ace8908ae50908e8761" } Install-Python @Python38x86Config $Python38x64Config = @{ - PythonVersion = "3.8.0" - PythonInstaller = "python-3.8.0-amd64" + PythonVersion = "3.8.10" + PythonInstaller = "python-3.8.10-amd64" PythonInstallPath = "C:\Python38" - PythonInstallerHash = "29ea87f24c32f5e924b7d63f8a08ee8d" + PythonInstallerHash = "62cf1a12a5276b0259e8761d4cf4fe42" } Install-Python @Python38x64Config # Python 3.9 $Python39x86Config = @{ - PythonVersion = "3.9.0" - PythonInstaller = "python-3.9.0" + PythonVersion = "3.9.11" + PythonInstaller = "python-3.9.11" PythonInstallPath = "C:\Python39_32bit" - PythonInstallerHash = "4a2812db8ab9f2e522c96c7728cfcccb" + PythonInstallerHash = "4210652b14a030517046cdf111c09c1e" } Install-Python @Python39x86Config $Python39x64Config = @{ - PythonVersion = "3.9.0" - PythonInstaller = "python-3.9.0-amd64" + PythonVersion = "3.9.11" + PythonInstaller = "python-3.9.11-amd64" PythonInstallPath = "C:\Python39" - PythonInstallerHash = "b61a33dc28f13b561452f3089c87eb63" + PythonInstallerHash = "fef52176a572efd48b7148f006b25801" } Install-Python @Python39x64Config # Python 3.10 $Python310x86Config = @{ - PythonVersion = "3.10.0" - PythonInstaller = "python-3.10.0rc1" + PythonVersion = "3.10.3" + PythonInstaller = "python-3.10.3" PythonInstallPath = "C:\Python310_32bit" - PythonInstallerHash = "6de353f2f7422aa030d4ccc788ffa75e" + PythonInstallerHash = "6a336cb2aca62dd05805316ab3aaf2b5" } Install-Python @Python310x86Config $Python310x64Config = @{ - PythonVersion = "3.10.0" - PythonInstaller = "python-3.10.0rc1-amd64" + PythonVersion = "3.10.3" + PythonInstaller = "python-3.10.3-amd64" PythonInstallPath = "C:\Python310" - PythonInstallerHash = "39135519b044757f0a3b09d63612b0da" + PythonInstallerHash = "9ea305690dbfd424a632b6a659347c1e" } Install-Python @Python310x64Config diff --git a/tools/internal_ci/linux/grpc_bazel_build_in_docker.sh b/tools/internal_ci/linux/grpc_bazel_build_in_docker.sh index 5043e312b98..77fb993124c 100755 --- a/tools/internal_ci/linux/grpc_bazel_build_in_docker.sh +++ b/tools/internal_ci/linux/grpc_bazel_build_in_docker.sh @@ -53,7 +53,7 @@ bazel build --define=use_strict_warning=true --define=use_abseil_status=true \ bazel build //test/cpp/end2end:end2end_test --define=grpc_no_xds=true # Test that builds that need xDS do not build with --define=grpc_no_xds=true EXIT_CODE=0 -bazel build //test/cpp/end2end:xds_end2end_test --define=grpc_no_xds=true || EXIT_CODE=$? +bazel build //test/cpp/end2end/xds:xds_end2end_test --define=grpc_no_xds=true || EXIT_CODE=$? if [ $EXIT_CODE -eq 0 ] then echo "Building xds_end2end_test succeeded even with --define=grpc_no_xds=true" diff --git a/tools/profiling/memory/memory_diff.py b/tools/profiling/memory/memory_diff.py index 457a7fd2c45..fd205b41a1c 100755 --- a/tools/profiling/memory/memory_diff.py +++ b/tools/profiling/memory/memory_diff.py @@ -49,6 +49,11 @@ _INTERESTING = { (rb'server call memory usage: ([0-9\.]+) bytes per call', float), } +_SCENARIOS = { + 'default': [], + 'minstack': ['--minstack'], +} + def _run(): """Build with Bazel, then run, and extract interesting lines from the output.""" @@ -56,24 +61,27 @@ def _run(): 'tools/bazel', 'build', '-c', 'opt', 'test/core/memory_usage/memory_usage_test' ]) - output = subprocess.check_output([ - 'bazel-bin/test/core/memory_usage/memory_usage_test', - '--warmup=10000', - '--benchmark=50000', - ]) ret = {} - for line in output.splitlines(): - for key, (pattern, conversion) in _INTERESTING.items(): - m = re.match(pattern, line) - if m: - ret[key] = conversion(m.group(1)) + for scenario, extra_args in _SCENARIOS.items(): + try: + output = subprocess.check_output([ + 'bazel-bin/test/core/memory_usage/memory_usage_test', + '--warmup=10000', + '--benchmark=50000', + ] + extra_args) + except subprocess.CalledProcessError as e: + print('Error running benchmark:', e) + continue + for line in output.splitlines(): + for key, (pattern, conversion) in _INTERESTING.items(): + m = re.match(pattern, line) + if m: + ret[scenario + ': ' + key] = conversion(m.group(1)) return ret cur = _run() -new = None - -print(cur) +old = None if args.diff_base: where_am_i = subprocess.check_output( @@ -81,24 +89,28 @@ if args.diff_base: # checkout the diff base (="old") subprocess.check_call(['git', 'checkout', args.diff_base]) try: - new = _run() + old = _run() finally: - # restore the original revision (="new") + # restore the original revision (="cur") subprocess.check_call(['git', 'checkout', where_am_i]) text = '' -if new is None: - for key, value in cur.items(): +if old is None: + print(cur) + for key, value in sorted(cur.items()): text += '{}: {}\n'.format(key, value) else: + print(cur, old) diff_size = 0 - for key, value in _INTERESTING.items(): - if key in cur: - if key not in new: - text += '{}: {}\n'.format(key, value) - else: - diff_size += cur[key] - new[key] - text += '{}: {} -> {}\n'.format(key, cur[key], new[key]) + for scenario in _SCENARIOS.keys(): + for key, value in sorted(_INTERESTING.items()): + key = scenario + ': ' + key + if key in cur: + if key not in old: + text += '{}: {}\n'.format(key, cur[key]) + else: + diff_size += cur[key] - old[key] + text += '{}: {} -> {}\n'.format(key, old[key], cur[key]) print("DIFF_SIZE: %f" % diff_size) check_on_pr.label_increase_decrease_on_pr('per-call-memory', diff_size, 64) diff --git a/tools/release/update_supported_bazel_versions.sh b/tools/release/update_supported_bazel_versions.sh new file mode 100755 index 00000000000..83eecd59ee6 --- /dev/null +++ b/tools/release/update_supported_bazel_versions.sh @@ -0,0 +1,46 @@ +#!/bin/bash +#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. + +# This script can be used to manually update the specific versions of Bazel +# tested by the Bazel distribtests and advertised as supported in documentation. +# This will update the supported_versions.txt file, which will be templated into +# the bazel_support.md document. + +# This script selects the latest patch release of the two most recent major +# versions of Bazel. If you want to include other versions in the set of +# supported versions, then you will need to manually edit the ifle. + +set -xeuo pipefail + +cd "$(dirname "$0")/../.." + +# The number of most recent supported major Bazel versions. +SUPPORT_RANGE="2" + +# Retrieve all git tags from the Bazel git repo. +TAGS=$(git ls-remote --tags git@github.com:bazelbuild/bazel.git | awk '{print $2;}' | sed 's|refs/tags/||g') + +# Find the n most recent major versions. +MAJOR_VERSIONS=$(echo "$TAGS" | egrep '^[0-9]+\.[0-9]+\.[0-9]+$' | cut -d'.' -f1 | sort -r | uniq | head -n"$SUPPORT_RANGE") + +SUPPORTED_VERSIONS="" + +# For each major version selected, find the most recent patch release. +while read -r MAJOR_VERSION; do + LATEST_PATCH=$(echo "$TAGS" | egrep "^${MAJOR_VERSION}\.[0-9]+\.[0-9]+$" | sort -nr | head -n1) + SUPPORTED_VERSIONS="$SUPPORTED_VERSIONS$LATEST_PATCH\n" +done<<<"$MAJOR_VERSIONS" + +printf "$SUPPORTED_VERSIONS" | tee bazel/supported_versions.txt