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