Merge branch 'non_per_call_metrics_wrr' into non_per_call_metrics_pf

pull/35984/head
Mark D. Roth 1 year ago
commit 239009cc81
  1. 1
      BUILD
  2. 76
      CMakeLists.txt
  3. 24
      bazel/experiments.bzl
  4. 154
      build_autogenerated.yaml
  5. 2
      doc/python/sphinx/grpc_observability.rst
  6. 1
      doc/python/sphinx/index.rst
  7. 2
      grpc.gyp
  8. 8
      requirements.bazel.txt
  9. 1
      src/core/ext/filters/channel_idle/channel_idle_filter.cc
  10. 2
      src/core/ext/transport/chaotic_good/client/chaotic_good_connector.cc
  11. 2
      src/core/ext/transport/chaotic_good/server/chaotic_good_server.cc
  12. 38
      src/core/ext/transport/chttp2/transport/chttp2_transport.cc
  13. 23
      src/core/ext/transport/chttp2/transport/context_list_entry.h
  14. 4
      src/core/ext/transport/chttp2/transport/internal.h
  15. 36
      src/core/ext/transport/chttp2/transport/writing.cc
  16. 43
      src/core/ext/xds/xds_client_grpc.cc
  17. 13
      src/core/ext/xds/xds_client_grpc.h
  18. 4
      src/core/ext/xds/xds_server_config_fetcher.cc
  19. 8
      src/core/lib/channel/promise_based_filter.h
  20. 1
      src/core/lib/event_engine/posix_engine/posix_engine_listener_utils.cc
  21. 2
      src/core/lib/experiments/config.cc
  22. 2
      src/core/lib/experiments/experiments.cc
  23. 3
      src/core/lib/experiments/experiments.h
  24. 7
      src/core/lib/experiments/rollouts.yaml
  25. 3
      src/core/lib/resource_quota/arena.h
  26. 27
      src/core/lib/security/credentials/tls/grpc_tls_crl_provider.cc
  27. 39
      src/core/lib/surface/call.cc
  28. 8
      src/core/lib/surface/init.cc
  29. 3
      src/core/resolver/xds/xds_resolver.cc
  30. 9
      src/core/tsi/ssl_transport_security.cc
  31. 70
      src/core/tsi/ssl_transport_security_utils.cc
  32. 18
      src/core/tsi/ssl_transport_security_utils.h
  33. 54
      src/python/grpcio/grpc/_observability.py
  34. 2
      src/python/grpcio/grpc/aio/_interceptor.py
  35. 2
      src/python/grpcio_observability/README.rst
  36. 2
      test/core/security/BUILD
  37. 67
      test/core/security/grpc_tls_crl_provider_test.cc
  38. 11
      test/core/tsi/BUILD
  39. 208
      test/core/tsi/ssl_transport_security_utils_test.cc
  40. 1
      test/core/tsi/test_creds/crl_data/BUILD
  41. 5
      test/core/tsi/test_creds/crl_data/README
  42. 2
      test/core/tsi/test_creds/crl_data/crls/BUILD
  43. 15
      test/core/tsi/test_creds/crl_data/crls/invalid_content.crl
  44. 15
      test/core/tsi/test_creds/crl_data/crls/invalid_signature.crl
  45. 28
      test/core/tsi/test_creds/crl_data/evil_ca.key
  46. 21
      test/core/tsi/test_creds/crl_data/evil_ca.pem
  47. 18
      test/core/tsi/test_creds/crl_data/evil_ca_gen.sh
  48. 2
      test/core/tsi/test_creds/crl_data/intermediate_gen.sh
  49. 24
      test/core/tsi/transport_security_test_lib.cc
  50. 8
      test/core/tsi/transport_security_test_lib.h
  51. 2
      test/core/util/BUILD
  52. 525
      test/core/util/passthru_endpoint.cc
  53. 58
      test/core/util/passthru_endpoint.h
  54. 132
      test/cpp/end2end/xds/xds_core_end2end_test.cc
  55. 79
      test/cpp/end2end/xds/xds_csds_end2end_test.cc
  56. 11
      test/cpp/end2end/xds/xds_end2end_test_lib.cc
  57. 7
      test/cpp/end2end/xds/xds_wrr_end2end_test.cc
  58. 18
      test/cpp/microbenchmarks/bm_fullstack_streaming_ping_pong.cc
  59. 6
      test/cpp/microbenchmarks/bm_fullstack_streaming_pump.cc
  60. 55
      test/cpp/microbenchmarks/bm_fullstack_unary_ping_pong.cc
  61. 41
      test/cpp/microbenchmarks/fullstack_fixtures.h

@ -3880,6 +3880,7 @@ grpc_cc_library(
external_deps = [ external_deps = [
"absl/base:core_headers", "absl/base:core_headers",
"absl/status", "absl/status",
"absl/status:statusor",
"absl/strings", "absl/strings",
"libcrypto", "libcrypto",
"libssl", "libssl",

76
CMakeLists.txt generated

@ -3942,7 +3942,6 @@ add_library(benchmark_helpers ${_gRPC_STATIC_WIN32}
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -4715,7 +4714,6 @@ add_library(grpc++_test_util
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -5692,7 +5690,6 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -5854,7 +5851,6 @@ add_executable(test_core_iomgr_timer_list_test
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -5996,7 +5992,6 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -6119,7 +6114,6 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -6664,7 +6658,6 @@ add_executable(alts_security_connector_test
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -7040,7 +7033,6 @@ add_executable(auth_context_test
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -7135,7 +7127,6 @@ add_executable(authorization_matchers_test
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -7275,7 +7266,6 @@ add_executable(aws_request_signer_test
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -7579,7 +7569,6 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -7636,7 +7625,6 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -8250,7 +8238,6 @@ add_executable(buffer_list_test
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -9307,7 +9294,6 @@ add_executable(cel_authorization_engine_test
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -9682,7 +9668,6 @@ add_executable(channel_creds_registry_test
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -10015,7 +10000,6 @@ add_executable(check_gcp_environment_linux_test
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -10067,7 +10051,6 @@ add_executable(check_gcp_environment_windows_test
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -10867,7 +10850,6 @@ add_executable(cmdline_test
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -11008,7 +10990,6 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -11378,7 +11359,6 @@ add_executable(connectivity_state_test
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -12773,7 +12753,6 @@ add_executable(endpoint_pair_test
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -12924,7 +12903,6 @@ add_executable(error_test
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -12976,7 +12954,6 @@ add_executable(error_utils_test
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -13028,7 +13005,6 @@ add_executable(evaluate_args_test
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -13670,7 +13646,6 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -14390,7 +14365,6 @@ add_executable(format_request_test
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -14893,7 +14867,6 @@ add_executable(grpc_alts_credentials_options_test
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -14988,7 +14961,6 @@ add_executable(grpc_authorization_engine_test
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -15040,7 +15012,6 @@ add_executable(grpc_authorization_policy_provider_test
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -15428,7 +15399,6 @@ add_executable(grpc_ipv6_loopback_available_test
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -15670,7 +15640,6 @@ add_executable(grpc_tls_certificate_distributor_test
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -15722,7 +15691,6 @@ add_executable(grpc_tls_certificate_provider_test
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -15774,7 +15742,6 @@ add_executable(grpc_tls_certificate_verifier_test
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -15826,7 +15793,6 @@ add_executable(grpc_tls_credentials_options_comparator_test
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -15878,7 +15844,6 @@ add_executable(grpc_tls_credentials_options_test
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -15934,6 +15899,7 @@ add_executable(grpc_tls_crl_provider_test
test/core/event_engine/event_engine_test_utils.cc test/core/event_engine/event_engine_test_utils.cc
test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.cc test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.cc
test/core/security/grpc_tls_crl_provider_test.cc test/core/security/grpc_tls_crl_provider_test.cc
test/core/tsi/transport_security_test_lib.cc
) )
if(WIN32 AND MSVC) if(WIN32 AND MSVC)
if(BUILD_SHARED_LIBS) if(BUILD_SHARED_LIBS)
@ -16613,7 +16579,6 @@ add_executable(histogram_test
test/core/util/histogram_test.cc test/core/util/histogram_test.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -16707,7 +16672,6 @@ add_executable(hpack_encoder_test
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -16759,7 +16723,6 @@ add_executable(hpack_parser_table_test
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -16811,7 +16774,6 @@ add_executable(hpack_parser_test
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -17531,7 +17493,6 @@ add_executable(insecure_security_connector_test
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -18196,7 +18157,6 @@ add_executable(json_token_test
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -18248,7 +18208,6 @@ add_executable(jwt_verifier_test
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -18983,7 +18942,6 @@ add_executable(matchers_test
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -19471,7 +19429,6 @@ add_executable(message_compress_test
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -19565,7 +19522,6 @@ add_executable(metadata_map_test
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -20870,7 +20826,6 @@ add_executable(parser_test
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -21194,7 +21149,6 @@ add_executable(ping_abuse_policy_test
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -21288,7 +21242,6 @@ add_executable(ping_configuration_test
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -21402,7 +21355,6 @@ add_executable(ping_rate_policy_test
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -22886,7 +22838,6 @@ add_executable(rbac_translator_test
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -23254,7 +23205,6 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -23308,7 +23258,6 @@ add_executable(resolve_address_using_ares_resolver_test
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -23362,7 +23311,6 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -23416,7 +23364,6 @@ add_executable(resolve_address_using_native_resolver_test
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -26121,7 +26068,6 @@ add_executable(secure_endpoint_test
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -26173,7 +26119,6 @@ add_executable(security_connector_test
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -26392,7 +26337,6 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -26464,7 +26408,6 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -26931,7 +26874,6 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -27242,7 +27184,6 @@ add_executable(settings_timeout_test
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -27968,7 +27909,6 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -28135,6 +28075,7 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_executable(ssl_transport_security_utils_test add_executable(ssl_transport_security_utils_test
test/core/tsi/ssl_transport_security_utils_test.cc test/core/tsi/ssl_transport_security_utils_test.cc
test/core/tsi/transport_security_test_lib.cc
) )
if(WIN32 AND MSVC) if(WIN32 AND MSVC)
if(BUILD_SHARED_LIBS) if(BUILD_SHARED_LIBS)
@ -28355,7 +28296,6 @@ add_executable(status_conversion_test
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -28703,7 +28643,6 @@ add_executable(streams_not_seen_test
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -28926,7 +28865,6 @@ add_executable(system_roots_test
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -29013,7 +28951,6 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -29112,7 +29049,6 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX)
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -29166,7 +29102,6 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -29603,7 +29538,6 @@ add_executable(test_core_iomgr_timer_heap_test
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -29655,7 +29589,6 @@ add_executable(test_core_security_credentials_test
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -29707,7 +29640,6 @@ add_executable(test_core_security_ssl_credentials_test
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -30634,7 +30566,6 @@ add_executable(timeout_encoding_test
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -30936,7 +30867,6 @@ add_executable(tls_security_connector_test
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -32503,7 +32433,6 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc
@ -33601,7 +33530,6 @@ add_executable(xds_credentials_test
test/core/util/histogram.cc test/core/util/histogram.cc
test/core/util/mock_endpoint.cc test/core/util/mock_endpoint.cc
test/core/util/parse_hexstring.cc test/core/util/parse_hexstring.cc
test/core/util/passthru_endpoint.cc
test/core/util/resolve_localhost_ip46.cc test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc test/core/util/slice_splitter.cc
test/core/util/tracer_util.cc test/core/util/tracer_util.cc

@ -73,11 +73,9 @@ EXPERIMENTS = {
], ],
"core_end2end_test": [ "core_end2end_test": [
"promise_based_server_call", "promise_based_server_call",
"work_serializer_dispatch",
], ],
"cpp_end2end_test": [ "cpp_end2end_test": [
"promise_based_server_call", "promise_based_server_call",
"work_serializer_dispatch",
], ],
"endpoint_test": [ "endpoint_test": [
"tcp_frame_size_tuning", "tcp_frame_size_tuning",
@ -90,9 +88,6 @@ EXPERIMENTS = {
"tcp_frame_size_tuning", "tcp_frame_size_tuning",
"tcp_rcv_lowat", "tcp_rcv_lowat",
], ],
"lb_unit_test": [
"work_serializer_dispatch",
],
"logging_test": [ "logging_test": [
"promise_based_server_call", "promise_based_server_call",
], ],
@ -102,7 +97,6 @@ EXPERIMENTS = {
], ],
"xds_end2end_test": [ "xds_end2end_test": [
"promise_based_server_call", "promise_based_server_call",
"work_serializer_dispatch",
], ],
}, },
"on": { "on": {
@ -144,11 +138,9 @@ EXPERIMENTS = {
], ],
"core_end2end_test": [ "core_end2end_test": [
"promise_based_server_call", "promise_based_server_call",
"work_serializer_dispatch",
], ],
"cpp_end2end_test": [ "cpp_end2end_test": [
"promise_based_server_call", "promise_based_server_call",
"work_serializer_dispatch",
], ],
"endpoint_test": [ "endpoint_test": [
"tcp_frame_size_tuning", "tcp_frame_size_tuning",
@ -161,9 +153,6 @@ EXPERIMENTS = {
"tcp_frame_size_tuning", "tcp_frame_size_tuning",
"tcp_rcv_lowat", "tcp_rcv_lowat",
], ],
"lb_unit_test": [
"work_serializer_dispatch",
],
"logging_test": [ "logging_test": [
"promise_based_server_call", "promise_based_server_call",
], ],
@ -173,7 +162,6 @@ EXPERIMENTS = {
], ],
"xds_end2end_test": [ "xds_end2end_test": [
"promise_based_server_call", "promise_based_server_call",
"work_serializer_dispatch",
], ],
}, },
"on": { "on": {
@ -212,11 +200,9 @@ EXPERIMENTS = {
"event_engine_client", "event_engine_client",
"promise_based_client_call", "promise_based_client_call",
"promise_based_server_call", "promise_based_server_call",
"work_serializer_dispatch",
], ],
"cpp_end2end_test": [ "cpp_end2end_test": [
"promise_based_server_call", "promise_based_server_call",
"work_serializer_dispatch",
], ],
"endpoint_test": [ "endpoint_test": [
"tcp_frame_size_tuning", "tcp_frame_size_tuning",
@ -235,9 +221,6 @@ EXPERIMENTS = {
"lame_client_test": [ "lame_client_test": [
"promise_based_client_call", "promise_based_client_call",
], ],
"lb_unit_test": [
"work_serializer_dispatch",
],
"logging_test": [ "logging_test": [
"promise_based_server_call", "promise_based_server_call",
], ],
@ -247,7 +230,6 @@ EXPERIMENTS = {
], ],
"xds_end2end_test": [ "xds_end2end_test": [
"promise_based_server_call", "promise_based_server_call",
"work_serializer_dispatch",
], ],
}, },
"on": { "on": {
@ -256,6 +238,10 @@ EXPERIMENTS = {
], ],
"core_end2end_test": [ "core_end2end_test": [
"event_engine_listener", "event_engine_listener",
"work_serializer_dispatch",
],
"cpp_end2end_test": [
"work_serializer_dispatch",
], ],
"cpp_lb_end2end_test": [ "cpp_lb_end2end_test": [
"pick_first_happy_eyeballs", "pick_first_happy_eyeballs",
@ -271,6 +257,7 @@ EXPERIMENTS = {
"lb_unit_test": [ "lb_unit_test": [
"pick_first_happy_eyeballs", "pick_first_happy_eyeballs",
"round_robin_delegate_to_pick_first", "round_robin_delegate_to_pick_first",
"work_serializer_dispatch",
"wrr_delegate_to_pick_first", "wrr_delegate_to_pick_first",
], ],
"resolver_component_tests_runner_invoker": [ "resolver_component_tests_runner_invoker": [
@ -282,6 +269,7 @@ EXPERIMENTS = {
"xds_end2end_test": [ "xds_end2end_test": [
"pick_first_happy_eyeballs", "pick_first_happy_eyeballs",
"round_robin_delegate_to_pick_first", "round_robin_delegate_to_pick_first",
"work_serializer_dispatch",
"wrr_delegate_to_pick_first", "wrr_delegate_to_pick_first",
], ],
}, },

File diff suppressed because it is too large Load Diff

@ -1,5 +1,5 @@
gRPC Python Observability gRPC Python Observability
==================== =========================
Module Contents Module Contents
--------------- ---------------

@ -18,6 +18,7 @@ API Reference
grpc_reflection grpc_reflection
grpc_status grpc_status
grpc_testing grpc_testing
grpc_observability
glossary glossary

2
grpc.gyp generated

@ -1796,7 +1796,6 @@
'test/core/util/histogram.cc', 'test/core/util/histogram.cc',
'test/core/util/mock_endpoint.cc', 'test/core/util/mock_endpoint.cc',
'test/core/util/parse_hexstring.cc', 'test/core/util/parse_hexstring.cc',
'test/core/util/passthru_endpoint.cc',
'test/core/util/resolve_localhost_ip46.cc', 'test/core/util/resolve_localhost_ip46.cc',
'test/core/util/slice_splitter.cc', 'test/core/util/slice_splitter.cc',
'test/core/util/tracer_util.cc', 'test/core/util/tracer_util.cc',
@ -1954,7 +1953,6 @@
'test/core/util/histogram.cc', 'test/core/util/histogram.cc',
'test/core/util/mock_endpoint.cc', 'test/core/util/mock_endpoint.cc',
'test/core/util/parse_hexstring.cc', 'test/core/util/parse_hexstring.cc',
'test/core/util/passthru_endpoint.cc',
'test/core/util/resolve_localhost_ip46.cc', 'test/core/util/resolve_localhost_ip46.cc',
'test/core/util/slice_splitter.cc', 'test/core/util/slice_splitter.cc',
'test/core/util/tracer_util.cc', 'test/core/util/tracer_util.cc',

@ -3,7 +3,6 @@ coverage==4.5.4
cython==0.29.21 cython==0.29.21
protobuf>=3.5.0.post1, < 4.0dev protobuf>=3.5.0.post1, < 4.0dev
wheel==0.38.1 wheel==0.38.1
google-auth==1.24.0
oauth2client==4.1.0 oauth2client==4.1.0
requests==2.25.1 requests==2.25.1
urllib3==1.26.18 urllib3==1.26.18
@ -13,12 +12,11 @@ idna==2.7
gevent==22.08.0 gevent==22.08.0
zope.event==4.5.0 zope.event==4.5.0
setuptools==44.1.1 setuptools==44.1.1
xds-protos==0.0.11
absl-py==1.4.0 absl-py==1.4.0
google-cloud-trace==1.11.3 google-cloud-trace==1.11.3
opencensus-context==0.1.3 opencensus-context==0.1.3
google-cloud-monitoring==2.16.0 google-cloud-monitoring==2.16.0
google-api-core==2.14.0 google-api-core==1.34.1
proto-plus==1.22.3 proto-plus==1.22.3
google-auth==2.23.4 google-auth==2.23.4
googleapis-common-protos==1.61.0 googleapis-common-protos==1.61.0
@ -30,9 +28,9 @@ greenlet==1.1.3.post0
zope.interface==6.1 zope.interface==6.1
opentelemetry-sdk==1.21.0 opentelemetry-sdk==1.21.0
opentelemetry-api==1.21.0 opentelemetry-api==1.21.0
importlib-metadata==7.0.1 importlib-metadata==6.11.0
Deprecated==1.2.14 Deprecated==1.2.14
opentelemetry-semantic-conventions==0.43b0 opentelemetry-semantic-conventions==0.42b0
typing-extensions==4.9.0 typing-extensions==4.9.0
pyasn1-modules==0.3.0 pyasn1-modules==0.3.0
zipp==3.17.0 zipp==3.17.0

@ -294,6 +294,7 @@ const grpc_channel_filter MaxAgeFilter::kFilter =
MakePromiseBasedFilter<MaxAgeFilter, FilterEndpoint::kServer>("max_age"); MakePromiseBasedFilter<MaxAgeFilter, FilterEndpoint::kServer>("max_age");
void RegisterChannelIdleFilters(CoreConfiguration::Builder* builder) { void RegisterChannelIdleFilters(CoreConfiguration::Builder* builder) {
GPR_ASSERT(MaxAgeFilter::kFilter.init_call != nullptr);
if (!IsV3ChannelIdleFiltersEnabled()) return; if (!IsV3ChannelIdleFiltersEnabled()) return;
builder->channel_init() builder->channel_init()
->RegisterFilter<ClientIdleFilter>(GRPC_CLIENT_CHANNEL) ->RegisterFilter<ClientIdleFilter>(GRPC_CLIENT_CHANNEL)

@ -67,7 +67,7 @@ namespace chaotic_good {
using grpc_event_engine::experimental::EventEngine; using grpc_event_engine::experimental::EventEngine;
namespace { namespace {
const int32_t kDataAlignmentBytes = 64; const int32_t kDataAlignmentBytes = 64;
const int32_t kTimeoutSecs = 5; const int32_t kTimeoutSecs = 120;
} // namespace } // namespace
ChaoticGoodConnector::ChaoticGoodConnector( ChaoticGoodConnector::ChaoticGoodConnector(

@ -70,7 +70,7 @@ namespace grpc_core {
namespace chaotic_good { namespace chaotic_good {
namespace { namespace {
const Duration kConnectionDeadline = Duration::Seconds(5); const Duration kConnectionDeadline = Duration::Seconds(120);
} // namespace } // namespace
using grpc_event_engine::experimental::EventEngine; using grpc_event_engine::experimental::EventEngine;

@ -1300,7 +1300,6 @@ static void null_then_sched_closure(grpc_closure** closure) {
} }
void grpc_chttp2_complete_closure_step(grpc_chttp2_transport* t, void grpc_chttp2_complete_closure_step(grpc_chttp2_transport* t,
grpc_chttp2_stream* s,
grpc_closure** pclosure, grpc_closure** pclosure,
grpc_error_handle error, grpc_error_handle error,
const char* desc, const char* desc,
@ -1325,12 +1324,6 @@ void grpc_chttp2_complete_closure_step(grpc_chttp2_transport* t,
write_state_name(t->write_state), whence.file(), whence.line()); write_state_name(t->write_state), whence.file(), whence.line());
} }
if (s->call_tracer) {
s->call_tracer->RecordAnnotation(
absl::StrFormat("on_complete: s=%p %p desc=%s err=%s", s, closure, desc,
grpc_core::StatusToString(error).c_str()));
}
if (!error.ok()) { if (!error.ok()) {
grpc_error_handle cl_err = grpc_error_handle cl_err =
grpc_core::internal::StatusMoveFromHeapPtr(closure->error_data.error); grpc_core::internal::StatusMoveFromHeapPtr(closure->error_data.error);
@ -1405,13 +1398,6 @@ static void perform_stream_op_locked(void* stream_op,
} }
} }
if (s->call_tracer) {
s->call_tracer->RecordAnnotation(absl::StrFormat(
"perform_stream_op_locked[s=%p; op=%p]: %s; on_complete = %p", s, op,
grpc_transport_stream_op_batch_string(op, true).c_str(),
op->on_complete));
}
grpc_closure* on_complete = op->on_complete; grpc_closure* on_complete = op->on_complete;
// on_complete will be null if and only if there are no send ops in the batch. // on_complete will be null if and only if there are no send ops in the batch.
if (on_complete != nullptr) { if (on_complete != nullptr) {
@ -1483,7 +1469,7 @@ static void perform_stream_op_locked(void* stream_op,
} else { } else {
s->send_initial_metadata = nullptr; s->send_initial_metadata = nullptr;
grpc_chttp2_complete_closure_step( grpc_chttp2_complete_closure_step(
t, s, &s->send_initial_metadata_finished, t, &s->send_initial_metadata_finished,
GRPC_ERROR_CREATE_REFERENCING( GRPC_ERROR_CREATE_REFERENCING(
"Attempt to send initial metadata after stream was closed", "Attempt to send initial metadata after stream was closed",
&s->write_closed_error, 1), &s->write_closed_error, 1),
@ -1503,7 +1489,7 @@ static void perform_stream_op_locked(void* stream_op,
// We should NOT return an error here, so as to avoid a cancel OP being // We should NOT return an error here, so as to avoid a cancel OP being
// started. The surface layer will notice that the stream has been closed // started. The surface layer will notice that the stream has been closed
// for writes and fail the send message op. // for writes and fail the send message op.
grpc_chttp2_complete_closure_step(t, s, &s->send_message_finished, grpc_chttp2_complete_closure_step(t, &s->send_message_finished,
absl::OkStatus(), absl::OkStatus(),
"fetching_send_message_finished"); "fetching_send_message_finished");
} else { } else {
@ -1543,7 +1529,7 @@ static void perform_stream_op_locked(void* stream_op,
int64_t notify_offset = s->next_message_end_offset; int64_t notify_offset = s->next_message_end_offset;
if (notify_offset <= s->flow_controlled_bytes_written) { if (notify_offset <= s->flow_controlled_bytes_written) {
grpc_chttp2_complete_closure_step(t, s, &s->send_message_finished, grpc_chttp2_complete_closure_step(t, &s->send_message_finished,
absl::OkStatus(), absl::OkStatus(),
"fetching_send_message_finished"); "fetching_send_message_finished");
} else { } else {
@ -1587,7 +1573,7 @@ static void perform_stream_op_locked(void* stream_op,
s->send_trailing_metadata = nullptr; s->send_trailing_metadata = nullptr;
s->sent_trailing_metadata_op = nullptr; s->sent_trailing_metadata_op = nullptr;
grpc_chttp2_complete_closure_step( grpc_chttp2_complete_closure_step(
t, s, &s->send_trailing_metadata_finished, t, &s->send_trailing_metadata_finished,
op->payload->send_trailing_metadata.send_trailing_metadata->empty() op->payload->send_trailing_metadata.send_trailing_metadata->empty()
? absl::OkStatus() ? absl::OkStatus()
: GRPC_ERROR_CREATE("Attempt to send trailing metadata after " : GRPC_ERROR_CREATE("Attempt to send trailing metadata after "
@ -1640,7 +1626,7 @@ static void perform_stream_op_locked(void* stream_op,
} }
if (on_complete != nullptr) { if (on_complete != nullptr) {
grpc_chttp2_complete_closure_step(t, s, &on_complete, absl::OkStatus(), grpc_chttp2_complete_closure_step(t, &on_complete, absl::OkStatus(),
"op->on_complete"); "op->on_complete");
} }
@ -2307,13 +2293,13 @@ static grpc_error_handle removal_error(grpc_error_handle extra_error,
return error; return error;
} }
static void flush_write_list(grpc_chttp2_transport* t, grpc_chttp2_stream* s, static void flush_write_list(grpc_chttp2_transport* t,
grpc_chttp2_write_cb** list, grpc_chttp2_write_cb** list,
grpc_error_handle error) { grpc_error_handle error) {
while (*list) { while (*list) {
grpc_chttp2_write_cb* cb = *list; grpc_chttp2_write_cb* cb = *list;
*list = cb->next; *list = cb->next;
grpc_chttp2_complete_closure_step(t, s, &cb->closure, error, grpc_chttp2_complete_closure_step(t, &cb->closure, error,
"on_write_finished_cb"); "on_write_finished_cb");
cb->next = t->write_cb_pool; cb->next = t->write_cb_pool;
t->write_cb_pool = cb; t->write_cb_pool = cb;
@ -2326,18 +2312,18 @@ void grpc_chttp2_fail_pending_writes(grpc_chttp2_transport* t,
error = error =
removal_error(error, s, "Pending writes failed due to stream closure"); removal_error(error, s, "Pending writes failed due to stream closure");
s->send_initial_metadata = nullptr; s->send_initial_metadata = nullptr;
grpc_chttp2_complete_closure_step(t, s, &s->send_initial_metadata_finished, grpc_chttp2_complete_closure_step(t, &s->send_initial_metadata_finished,
error, "send_initial_metadata_finished"); error, "send_initial_metadata_finished");
s->send_trailing_metadata = nullptr; s->send_trailing_metadata = nullptr;
s->sent_trailing_metadata_op = nullptr; s->sent_trailing_metadata_op = nullptr;
grpc_chttp2_complete_closure_step(t, s, &s->send_trailing_metadata_finished, grpc_chttp2_complete_closure_step(t, &s->send_trailing_metadata_finished,
error, "send_trailing_metadata_finished"); error, "send_trailing_metadata_finished");
grpc_chttp2_complete_closure_step(t, s, &s->send_message_finished, error, grpc_chttp2_complete_closure_step(t, &s->send_message_finished, error,
"fetching_send_message_finished"); "fetching_send_message_finished");
flush_write_list(t, s, &s->on_write_finished_cbs, error); flush_write_list(t, &s->on_write_finished_cbs, error);
flush_write_list(t, s, &s->on_flow_controlled_cbs, error); flush_write_list(t, &s->on_flow_controlled_cbs, error);
} }
grpc_chttp2_transport::RemovedStreamHandle grpc_chttp2_mark_stream_closed( grpc_chttp2_transport::RemovedStreamHandle grpc_chttp2_mark_stream_closed(

@ -38,38 +38,41 @@ namespace grpc_core {
// sent over the wire. A data chunk being written over the wire is multiplexed // sent over the wire. A data chunk being written over the wire is multiplexed
// with bytes from multiple RPCs. If one such RPC is traced, we store the // with bytes from multiple RPCs. If one such RPC is traced, we store the
// following information about the traced RPC: // following information about the traced RPC:
// - byte_offset_in_stream: Number of bytes belonging to that traced RPC which
// have been sent so far from the start of the RPC stream.
// - relative_start_pos_in_chunk: Starting offset of the traced RPC within
// the current chunk that is being sent.
// - num_traced_bytes_in_chunk: Number of bytes belonging to the traced RPC
// within the current chunk.
class ContextListEntry { class ContextListEntry {
public: public:
ContextListEntry(void* context, int64_t relative_start_pos, ContextListEntry(void* context, int64_t outbuf_offset,
int64_t num_traced_bytes, size_t byte_offset, int64_t num_traced_bytes, size_t byte_offset,
size_t stream_index,
std::shared_ptr<TcpTracerInterface> tcp_tracer) std::shared_ptr<TcpTracerInterface> tcp_tracer)
: trace_context_(context), : trace_context_(context),
relative_start_pos_in_chunk_(relative_start_pos), outbuf_offset_(outbuf_offset),
num_traced_bytes_in_chunk_(num_traced_bytes), num_traced_bytes_in_chunk_(num_traced_bytes),
byte_offset_in_stream_(byte_offset), byte_offset_in_stream_(byte_offset),
stream_index_(stream_index),
tcp_tracer_(std::move(tcp_tracer)) {} tcp_tracer_(std::move(tcp_tracer)) {}
ContextListEntry() = delete; ContextListEntry() = delete;
void* TraceContext() { return trace_context_; } void* TraceContext() { return trace_context_; }
int64_t RelativeStartPosInChunk() { return relative_start_pos_in_chunk_; } int64_t OutbufOffset() { return outbuf_offset_; }
int64_t NumTracedBytesInChunk() { return num_traced_bytes_in_chunk_; } int64_t NumTracedBytesInChunk() { return num_traced_bytes_in_chunk_; }
size_t ByteOffsetInStream() { return byte_offset_in_stream_; } size_t ByteOffsetInStream() { return byte_offset_in_stream_; }
size_t StreamIndex() { return stream_index_; }
std::shared_ptr<TcpTracerInterface> ReleaseTcpTracer() { std::shared_ptr<TcpTracerInterface> ReleaseTcpTracer() {
return std::move(tcp_tracer_); return std::move(tcp_tracer_);
} }
private: private:
void* trace_context_; void* trace_context_;
int64_t relative_start_pos_in_chunk_; // Offset of the head of the current chunk in the output buffer.
int64_t outbuf_offset_;
// Number of bytes traced in the current chunk.
int64_t num_traced_bytes_in_chunk_; int64_t num_traced_bytes_in_chunk_;
// Offset of the head of the current chunk in the RPC stream.
size_t byte_offset_in_stream_; size_t byte_offset_in_stream_;
// Index of the current chunk in the RPC stream.
// Set to zero for the first chunk of the RPC stream.
size_t stream_index_;
std::shared_ptr<TcpTracerInterface> tcp_tracer_; std::shared_ptr<TcpTracerInterface> tcp_tracer_;
}; };

@ -640,6 +640,9 @@ struct grpc_chttp2_stream {
/// Byte counter for number of bytes written /// Byte counter for number of bytes written
size_t byte_counter = 0; size_t byte_counter = 0;
/// Number of times written
int64_t write_counter = 0;
/// Only set when enabled. /// Only set when enabled.
grpc_core::CallTracerInterface* call_tracer = nullptr; grpc_core::CallTracerInterface* call_tracer = nullptr;
@ -775,7 +778,6 @@ void grpc_chttp2_add_incoming_goaway(grpc_chttp2_transport* t,
void grpc_chttp2_parsing_become_skip_parser(grpc_chttp2_transport* t); void grpc_chttp2_parsing_become_skip_parser(grpc_chttp2_transport* t);
void grpc_chttp2_complete_closure_step(grpc_chttp2_transport* t, void grpc_chttp2_complete_closure_step(grpc_chttp2_transport* t,
grpc_chttp2_stream* s,
grpc_closure** pclosure, grpc_closure** pclosure,
grpc_error_handle error, grpc_error_handle error,
const char* desc, const char* desc,

@ -82,10 +82,9 @@ static void add_to_write_list(grpc_chttp2_write_cb** list,
*list = cb; *list = cb;
} }
static void finish_write_cb(grpc_chttp2_transport* t, grpc_chttp2_stream* s, static void finish_write_cb(grpc_chttp2_transport* t, grpc_chttp2_write_cb* cb,
grpc_chttp2_write_cb* cb, grpc_error_handle error) { grpc_error_handle error) {
grpc_chttp2_complete_closure_step(t, s, &cb->closure, error, grpc_chttp2_complete_closure_step(t, &cb->closure, error, "finish_write_cb");
"finish_write_cb");
cb->next = t->write_cb_pool; cb->next = t->write_cb_pool;
t->write_cb_pool = cb; t->write_cb_pool = cb;
} }
@ -186,9 +185,9 @@ static void maybe_initiate_ping(grpc_chttp2_transport* t) {
}); });
} }
static bool update_list(grpc_chttp2_transport* t, grpc_chttp2_stream* s, static bool update_list(grpc_chttp2_transport* t, int64_t send_bytes,
int64_t send_bytes, grpc_chttp2_write_cb** list, grpc_chttp2_write_cb** list, int64_t* ctr,
int64_t* ctr, grpc_error_handle error) { grpc_error_handle error) {
bool sched_any = false; bool sched_any = false;
grpc_chttp2_write_cb* cb = *list; grpc_chttp2_write_cb* cb = *list;
*list = nullptr; *list = nullptr;
@ -197,7 +196,7 @@ static bool update_list(grpc_chttp2_transport* t, grpc_chttp2_stream* s,
grpc_chttp2_write_cb* next = cb->next; grpc_chttp2_write_cb* next = cb->next;
if (cb->call_at_byte <= *ctr) { if (cb->call_at_byte <= *ctr) {
sched_any = true; sched_any = true;
finish_write_cb(t, s, cb, error); finish_write_cb(t, cb, error);
} else { } else {
add_to_write_list(list, cb); add_to_write_list(list, cb);
} }
@ -424,8 +423,7 @@ class DataSendContext {
void CallCallbacks() { void CallCallbacks() {
if (update_list( if (update_list(
t_, s_, t_, static_cast<int64_t>(s_->sending_bytes - sending_bytes_before_),
static_cast<int64_t>(s_->sending_bytes - sending_bytes_before_),
&s_->on_flow_controlled_cbs, &s_->flow_controlled_bytes_flowed, &s_->on_flow_controlled_cbs, &s_->flow_controlled_bytes_flowed,
absl::OkStatus())) { absl::OkStatus())) {
write_context_->NoteScheduledResults(); write_context_->NoteScheduledResults();
@ -484,9 +482,9 @@ class StreamWriteContext {
s_->send_initial_metadata = nullptr; s_->send_initial_metadata = nullptr;
s_->sent_initial_metadata = true; s_->sent_initial_metadata = true;
write_context_->NoteScheduledResults(); write_context_->NoteScheduledResults();
grpc_chttp2_complete_closure_step( grpc_chttp2_complete_closure_step(t_, &s_->send_initial_metadata_finished,
t_, s_, &s_->send_initial_metadata_finished, absl::OkStatus(), absl::OkStatus(),
"send_initial_metadata_finished"); "send_initial_metadata_finished");
if (s_->call_tracer) { if (s_->call_tracer) {
grpc_core::HttpAnnotation::WriteStats write_stats; grpc_core::HttpAnnotation::WriteStats write_stats;
write_stats.target_write_size = write_context_->target_write_size(); write_stats.target_write_size = write_context_->target_write_size();
@ -583,9 +581,9 @@ class StreamWriteContext {
SentLastFrame(); SentLastFrame();
write_context_->NoteScheduledResults(); write_context_->NoteScheduledResults();
grpc_chttp2_complete_closure_step( grpc_chttp2_complete_closure_step(t_, &s_->send_trailing_metadata_finished,
t_, s_, &s_->send_trailing_metadata_finished, absl::OkStatus(), absl::OkStatus(),
"send_trailing_metadata_finished"); "send_trailing_metadata_finished");
} }
bool stream_became_writable() { return stream_became_writable_; } bool stream_became_writable() { return stream_became_writable_; }
@ -665,6 +663,7 @@ grpc_chttp2_begin_write_result grpc_chttp2_begin_write(
// Add this stream to the list of the contexts to be traced at TCP // Add this stream to the list of the contexts to be traced at TCP
num_stream_bytes = t->outbuf.c_slice_buffer()->length - orig_len; num_stream_bytes = t->outbuf.c_slice_buffer()->length - orig_len;
s->byte_counter += static_cast<size_t>(num_stream_bytes); s->byte_counter += static_cast<size_t>(num_stream_bytes);
++s->write_counter;
if (s->traced && grpc_endpoint_can_track_err(t->ep)) { if (s->traced && grpc_endpoint_can_track_err(t->ep)) {
grpc_core::CopyContextFn copy_context_fn = grpc_core::CopyContextFn copy_context_fn =
grpc_core::GrpcHttp2GetCopyContextFn(); grpc_core::GrpcHttp2GetCopyContextFn();
@ -672,7 +671,8 @@ grpc_chttp2_begin_write_result grpc_chttp2_begin_write(
grpc_core::GrpcHttp2GetWriteTimestampsCallback() != nullptr) { grpc_core::GrpcHttp2GetWriteTimestampsCallback() != nullptr) {
t->cl->emplace_back(copy_context_fn(s->context), t->cl->emplace_back(copy_context_fn(s->context),
outbuf_relative_start_pos, num_stream_bytes, outbuf_relative_start_pos, num_stream_bytes,
s->byte_counter, s->tcp_tracer); s->byte_counter, s->write_counter - 1,
s->tcp_tracer);
} }
} }
outbuf_relative_start_pos += num_stream_bytes; outbuf_relative_start_pos += num_stream_bytes;
@ -744,7 +744,7 @@ void grpc_chttp2_end_write(grpc_chttp2_transport* t, grpc_error_handle error) {
while (grpc_chttp2_list_pop_writing_stream(t, &s)) { while (grpc_chttp2_list_pop_writing_stream(t, &s)) {
if (s->sending_bytes != 0) { if (s->sending_bytes != 0) {
update_list(t, s, static_cast<int64_t>(s->sending_bytes), update_list(t, static_cast<int64_t>(s->sending_bytes),
&s->on_write_finished_cbs, &s->flow_controlled_bytes_written, &s->on_write_finished_cbs, &s->flow_controlled_bytes_written,
error); error);
s->sending_bytes = 0; s->sending_bytes = 0;

@ -92,7 +92,9 @@ namespace {
Mutex* g_mu = new Mutex; Mutex* g_mu = new Mutex;
const grpc_channel_args* g_channel_args ABSL_GUARDED_BY(*g_mu) = nullptr; const grpc_channel_args* g_channel_args ABSL_GUARDED_BY(*g_mu) = nullptr;
GrpcXdsClient* g_xds_client ABSL_GUARDED_BY(*g_mu) = nullptr; // Key bytes live in clients so they outlive the entries in this map
NoDestruct<std::map<absl::string_view, GrpcXdsClient*>> g_xds_client_map
ABSL_GUARDED_BY(*g_mu);
char* g_fallback_bootstrap_config ABSL_GUARDED_BY(*g_mu) = nullptr; char* g_fallback_bootstrap_config ABSL_GUARDED_BY(*g_mu) = nullptr;
} // namespace } // namespace
@ -139,9 +141,9 @@ absl::StatusOr<std::string> GetBootstrapContents(const char* fallback_config) {
std::vector<RefCountedPtr<GrpcXdsClient>> GetAllXdsClients() { std::vector<RefCountedPtr<GrpcXdsClient>> GetAllXdsClients() {
MutexLock lock(g_mu); MutexLock lock(g_mu);
std::vector<RefCountedPtr<GrpcXdsClient>> xds_clients; std::vector<RefCountedPtr<GrpcXdsClient>> xds_clients;
if (g_xds_client != nullptr) { for (const auto& key_client : *g_xds_client_map) {
auto xds_client = auto xds_client =
g_xds_client->RefIfNonZero(DEBUG_LOCATION, "DumpAllClientConfigs"); key_client.second->RefIfNonZero(DEBUG_LOCATION, "DumpAllClientConfigs");
if (xds_client != nullptr) { if (xds_client != nullptr) {
xds_clients.emplace_back(xds_client.TakeAsSubclass<GrpcXdsClient>()); xds_clients.emplace_back(xds_client.TakeAsSubclass<GrpcXdsClient>());
} }
@ -152,7 +154,7 @@ std::vector<RefCountedPtr<GrpcXdsClient>> GetAllXdsClients() {
} // namespace } // namespace
absl::StatusOr<RefCountedPtr<GrpcXdsClient>> GrpcXdsClient::GetOrCreate( absl::StatusOr<RefCountedPtr<GrpcXdsClient>> GrpcXdsClient::GetOrCreate(
const ChannelArgs& args, const char* reason) { absl::string_view key, const ChannelArgs& args, const char* reason) {
// If getting bootstrap from channel args, create a local XdsClient // If getting bootstrap from channel args, create a local XdsClient
// instance for the channel or server instead of using the global instance. // instance for the channel or server instead of using the global instance.
absl::optional<absl::string_view> bootstrap_config = args.GetString( absl::optional<absl::string_view> bootstrap_config = args.GetString(
@ -164,13 +166,14 @@ absl::StatusOr<RefCountedPtr<GrpcXdsClient>> GrpcXdsClient::GetOrCreate(
GRPC_ARG_TEST_ONLY_DO_NOT_USE_IN_PROD_XDS_CLIENT_CHANNEL_ARGS); GRPC_ARG_TEST_ONLY_DO_NOT_USE_IN_PROD_XDS_CLIENT_CHANNEL_ARGS);
auto channel_args = ChannelArgs::FromC(xds_channel_args); auto channel_args = ChannelArgs::FromC(xds_channel_args);
return MakeRefCounted<GrpcXdsClient>( return MakeRefCounted<GrpcXdsClient>(
std::move(*bootstrap), channel_args, key, std::move(*bootstrap), channel_args,
MakeOrphanable<GrpcXdsTransportFactory>(channel_args)); MakeOrphanable<GrpcXdsTransportFactory>(channel_args));
} }
// Otherwise, use the global instance. // Otherwise, use the global instance.
MutexLock lock(g_mu); MutexLock lock(g_mu);
if (g_xds_client != nullptr) { auto it = g_xds_client_map->find(key);
auto xds_client = g_xds_client->RefIfNonZero(DEBUG_LOCATION, reason); if (it != g_xds_client_map->end()) {
auto xds_client = it->second->RefIfNonZero(DEBUG_LOCATION, reason);
if (xds_client != nullptr) { if (xds_client != nullptr) {
return xds_client.TakeAsSubclass<GrpcXdsClient>(); return xds_client.TakeAsSubclass<GrpcXdsClient>();
} }
@ -188,9 +191,13 @@ absl::StatusOr<RefCountedPtr<GrpcXdsClient>> GrpcXdsClient::GetOrCreate(
// Instantiate XdsClient. // Instantiate XdsClient.
auto channel_args = ChannelArgs::FromC(g_channel_args); auto channel_args = ChannelArgs::FromC(g_channel_args);
auto xds_client = MakeRefCounted<GrpcXdsClient>( auto xds_client = MakeRefCounted<GrpcXdsClient>(
std::move(*bootstrap), channel_args, key, std::move(*bootstrap), channel_args,
MakeOrphanable<GrpcXdsTransportFactory>(channel_args)); MakeOrphanable<GrpcXdsTransportFactory>(channel_args));
g_xds_client = xds_client.get(); g_xds_client_map->emplace(xds_client->key(), xds_client.get());
if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) {
gpr_log(GPR_INFO, "xDS client for key: %s was created",
std::string(key).c_str());
}
return xds_client; return xds_client;
} }
@ -211,6 +218,8 @@ grpc_slice GrpcXdsClient::DumpAllClientConfigs()
arena.ptr()); arena.ptr());
xds_client->mu()->Lock(); xds_client->mu()->Lock();
xds_client->DumpClientConfig(&string_pool, arena.ptr(), client_config); xds_client->DumpClientConfig(&string_pool, arena.ptr(), client_config);
envoy_service_status_v3_ClientConfig_set_client_scope(
client_config, StdStringToUpbString(xds_client->key()));
} }
// Serialize the upb message to bytes // Serialize the upb message to bytes
size_t output_length; size_t output_length;
@ -223,7 +232,8 @@ grpc_slice GrpcXdsClient::DumpAllClientConfigs()
} }
GrpcXdsClient::GrpcXdsClient( GrpcXdsClient::GrpcXdsClient(
std::unique_ptr<GrpcXdsBootstrap> bootstrap, const ChannelArgs& args, absl::string_view key, std::unique_ptr<GrpcXdsBootstrap> bootstrap,
const ChannelArgs& args,
OrphanablePtr<XdsTransportFactory> transport_factory) OrphanablePtr<XdsTransportFactory> transport_factory)
: XdsClient( : XdsClient(
std::move(bootstrap), std::move(transport_factory), std::move(bootstrap), std::move(transport_factory),
@ -237,13 +247,18 @@ GrpcXdsClient::GrpcXdsClient(
args.GetDurationFromIntMillis( args.GetDurationFromIntMillis(
GRPC_ARG_XDS_RESOURCE_DOES_NOT_EXIST_TIMEOUT_MS) GRPC_ARG_XDS_RESOURCE_DOES_NOT_EXIST_TIMEOUT_MS)
.value_or(Duration::Seconds(15)))), .value_or(Duration::Seconds(15)))),
key_(key),
certificate_provider_store_(MakeOrphanable<CertificateProviderStore>( certificate_provider_store_(MakeOrphanable<CertificateProviderStore>(
static_cast<const GrpcXdsBootstrap&>(this->bootstrap()) static_cast<const GrpcXdsBootstrap&>(this->bootstrap())
.certificate_providers())) {} .certificate_providers())) {}
GrpcXdsClient::~GrpcXdsClient() { void GrpcXdsClient::Orphan() {
MutexLock lock(g_mu); MutexLock lock(g_mu);
if (g_xds_client == this) g_xds_client = nullptr; auto it = g_xds_client_map->find(key_);
if (it != g_xds_client_map->end() && it->second == this) {
g_xds_client_map->erase(it);
}
XdsClient::Orphan();
} }
grpc_pollset_set* GrpcXdsClient::interested_parties() const { grpc_pollset_set* GrpcXdsClient::interested_parties() const {
@ -258,9 +273,9 @@ void SetXdsChannelArgsForTest(grpc_channel_args* args) {
g_channel_args = args; g_channel_args = args;
} }
void UnsetGlobalXdsClientForTest() { void UnsetGlobalXdsClientsForTest() {
MutexLock lock(g_mu); MutexLock lock(g_mu);
g_xds_client = nullptr; g_xds_client_map->clear();
} }
void SetXdsFallbackBootstrapConfig(const char* config) { void SetXdsFallbackBootstrapConfig(const char* config) {

@ -43,7 +43,7 @@ class GrpcXdsClient : public XdsClient {
public: public:
// Factory function to get or create the global XdsClient instance. // Factory function to get or create the global XdsClient instance.
static absl::StatusOr<RefCountedPtr<GrpcXdsClient>> GetOrCreate( static absl::StatusOr<RefCountedPtr<GrpcXdsClient>> GetOrCreate(
const ChannelArgs& args, const char* reason); absl::string_view key, const ChannelArgs& args, const char* reason);
// Builds ClientStatusResponse containing all resources from all XdsClients // Builds ClientStatusResponse containing all resources from all XdsClients
static grpc_slice DumpAllClientConfigs(); static grpc_slice DumpAllClientConfigs();
@ -60,10 +60,12 @@ class GrpcXdsClient : public XdsClient {
// work for callers that use interested_parties() but not for callers // work for callers that use interested_parties() but not for callers
// that also use certificate_provider_store(), but we should consider // that also use certificate_provider_store(), but we should consider
// alternatives for that case as well. // alternatives for that case as well.
GrpcXdsClient(std::unique_ptr<GrpcXdsBootstrap> bootstrap, GrpcXdsClient(absl::string_view key,
std::unique_ptr<GrpcXdsBootstrap> bootstrap,
const ChannelArgs& args, const ChannelArgs& args,
OrphanablePtr<XdsTransportFactory> transport_factory); OrphanablePtr<XdsTransportFactory> transport_factory);
~GrpcXdsClient() override;
void Orphan() override;
// Helpers for encoding the XdsClient object in channel args. // Helpers for encoding the XdsClient object in channel args.
static absl::string_view ChannelArgName() { static absl::string_view ChannelArgName() {
@ -79,13 +81,16 @@ class GrpcXdsClient : public XdsClient {
return *certificate_provider_store_; return *certificate_provider_store_;
} }
absl::string_view key() const { return key_; }
private: private:
std::string key_;
OrphanablePtr<CertificateProviderStore> certificate_provider_store_; OrphanablePtr<CertificateProviderStore> certificate_provider_store_;
}; };
namespace internal { namespace internal {
void SetXdsChannelArgsForTest(grpc_channel_args* args); void SetXdsChannelArgsForTest(grpc_channel_args* args);
void UnsetGlobalXdsClientForTest(); void UnsetGlobalXdsClientsForTest();
// Sets bootstrap config to be used when no env var is set. // Sets bootstrap config to be used when no env var is set.
// Does not take ownership of config. // Does not take ownership of config.
void SetXdsFallbackBootstrapConfig(const char* config); void SetXdsFallbackBootstrapConfig(const char* config);

@ -94,6 +94,8 @@ namespace {
using ReadDelayHandle = XdsClient::ReadDelayHandle; using ReadDelayHandle = XdsClient::ReadDelayHandle;
constexpr absl::string_view kServerXdsClientKey = "#server";
TraceFlag grpc_xds_server_config_fetcher_trace(false, TraceFlag grpc_xds_server_config_fetcher_trace(false,
"xds_server_config_fetcher"); "xds_server_config_fetcher");
@ -1372,7 +1374,7 @@ grpc_server_config_fetcher* grpc_server_config_fetcher_xds_create(
"update=%p, user_data=%p}, args=%p)", "update=%p, user_data=%p}, args=%p)",
3, (notifier.on_serving_status_update, notifier.user_data, args)); 3, (notifier.on_serving_status_update, notifier.user_data, args));
auto xds_client = grpc_core::GrpcXdsClient::GetOrCreate( auto xds_client = grpc_core::GrpcXdsClient::GetOrCreate(
channel_args, "XdsServerConfigFetcher"); grpc_core::kServerXdsClientKey, channel_args, "XdsServerConfigFetcher");
if (!xds_client.ok()) { if (!xds_client.ok()) {
gpr_log(GPR_ERROR, "Failed to create xds client: %s", gpr_log(GPR_ERROR, "Failed to create xds client: %s",
xds_client.status().ToString().c_str()); xds_client.status().ToString().c_str());

@ -1065,8 +1065,10 @@ MakeFilterCall(Derived* derived) {
// the filter does not intercept call finalization. // the filter does not intercept call finalization.
// - void OnFinalize(const grpc_call_final_info*): // - void OnFinalize(const grpc_call_final_info*):
// the filter intercepts call finalization. // the filter intercepts call finalization.
class ImplementChannelFilterTag {};
template <typename Derived> template <typename Derived>
class ImplementChannelFilter : public ChannelFilter { class ImplementChannelFilter : public ChannelFilter,
public ImplementChannelFilterTag {
public: public:
// Natively construct a v3 call. // Natively construct a v3 call.
void InitCall(CallSpineInterface* call_spine) { void InitCall(CallSpineInterface* call_spine) {
@ -1914,7 +1916,7 @@ struct ChannelFilterWithFlagsMethods {
template <typename F, FilterEndpoint kEndpoint, uint8_t kFlags = 0> template <typename F, FilterEndpoint kEndpoint, uint8_t kFlags = 0>
absl::enable_if_t< absl::enable_if_t<
std::is_base_of<ChannelFilter, F>::value && std::is_base_of<ChannelFilter, F>::value &&
!std::is_base_of<ImplementChannelFilter<F>, F>::value && !std::is_base_of<ImplementChannelFilterTag, F>::value &&
!std::is_base_of<HackyHackyHackySkipInV3FilterStacks, F>::value, !std::is_base_of<HackyHackyHackySkipInV3FilterStacks, F>::value,
grpc_channel_filter> grpc_channel_filter>
MakePromiseBasedFilter(const char* name) { MakePromiseBasedFilter(const char* name) {
@ -2001,7 +2003,7 @@ MakePromiseBasedFilter(const char* name) {
} }
template <typename F, FilterEndpoint kEndpoint, uint8_t kFlags = 0> template <typename F, FilterEndpoint kEndpoint, uint8_t kFlags = 0>
absl::enable_if_t<std::is_base_of<ImplementChannelFilter<F>, F>::value, absl::enable_if_t<std::is_base_of<ImplementChannelFilterTag, F>::value,
grpc_channel_filter> grpc_channel_filter>
MakePromiseBasedFilter(const char* name) { MakePromiseBasedFilter(const char* name) {
using CallData = promise_filter_detail::CallData<kEndpoint>; using CallData = promise_filter_detail::CallData<kEndpoint>;

@ -169,6 +169,7 @@ absl::Status PrepareSocket(const PosixTcpOptions& options,
!ResolvedAddressIsVSock(socket.addr)) { !ResolvedAddressIsVSock(socket.addr)) {
GRPC_RETURN_IF_ERROR(socket.sock.SetSocketLowLatency(1)); GRPC_RETURN_IF_ERROR(socket.sock.SetSocketLowLatency(1));
GRPC_RETURN_IF_ERROR(socket.sock.SetSocketReuseAddr(1)); GRPC_RETURN_IF_ERROR(socket.sock.SetSocketReuseAddr(1));
GRPC_RETURN_IF_ERROR(socket.sock.SetSocketDscp(options.dscp));
socket.sock.TrySetSocketTcpUserTimeout(options, false); socket.sock.TrySetSocketTcpUserTimeout(options, false);
} }
GRPC_RETURN_IF_ERROR(socket.sock.SetSocketNoSigpipeIfPossible()); GRPC_RETURN_IF_ERROR(socket.sock.SetSocketNoSigpipeIfPossible());

@ -201,7 +201,7 @@ void PrintExperimentsList() {
for (auto name_index : visitation_order) { for (auto name_index : visitation_order) {
const size_t i = name_index.second; const size_t i = name_index.second;
gpr_log( gpr_log(
GPR_DEBUG, "%s", GPR_INFO, "%s",
absl::StrCat( absl::StrCat(
"gRPC EXPERIMENT ", g_experiment_metadata[i].name, "gRPC EXPERIMENT ", g_experiment_metadata[i].name,
std::string(max_experiment_length - std::string(max_experiment_length -

@ -792,7 +792,7 @@ const ExperimentMetadata g_experiment_metadata[] = {
true}, true},
{"work_serializer_dispatch", description_work_serializer_dispatch, {"work_serializer_dispatch", description_work_serializer_dispatch,
additional_constraints_work_serializer_dispatch, additional_constraints_work_serializer_dispatch,
required_experiments_work_serializer_dispatch, 1, false, true}, required_experiments_work_serializer_dispatch, 1, true, true},
{"wrr_delegate_to_pick_first", description_wrr_delegate_to_pick_first, {"wrr_delegate_to_pick_first", description_wrr_delegate_to_pick_first,
additional_constraints_wrr_delegate_to_pick_first, nullptr, 0, true, true}, additional_constraints_wrr_delegate_to_pick_first, nullptr, 0, true, true},
}; };

@ -232,7 +232,8 @@ inline bool IsV3CompressionFilterEnabled() { return false; }
inline bool IsV3ServerAuthFilterEnabled() { return false; } inline bool IsV3ServerAuthFilterEnabled() { return false; }
#define GRPC_EXPERIMENT_IS_INCLUDED_WORK_SERIALIZER_CLEARS_TIME_CACHE #define GRPC_EXPERIMENT_IS_INCLUDED_WORK_SERIALIZER_CLEARS_TIME_CACHE
inline bool IsWorkSerializerClearsTimeCacheEnabled() { return true; } inline bool IsWorkSerializerClearsTimeCacheEnabled() { return true; }
inline bool IsWorkSerializerDispatchEnabled() { return false; } #define GRPC_EXPERIMENT_IS_INCLUDED_WORK_SERIALIZER_DISPATCH
inline bool IsWorkSerializerDispatchEnabled() { return true; }
#define GRPC_EXPERIMENT_IS_INCLUDED_WRR_DELEGATE_TO_PICK_FIRST #define GRPC_EXPERIMENT_IS_INCLUDED_WRR_DELEGATE_TO_PICK_FIRST
inline bool IsWrrDelegateToPickFirstEnabled() { return true; } inline bool IsWrrDelegateToPickFirstEnabled() { return true; }
#endif #endif

@ -123,6 +123,11 @@
- name: work_serializer_clears_time_cache - name: work_serializer_clears_time_cache
default: true default: true
- name: work_serializer_dispatch - name: work_serializer_dispatch
default: false default:
# TODO(ysseung): Not fully tested.
ios: broken
posix: true
# TODO(ysseung): Test flakes not fully resolved.
windows: broken
- name: wrr_delegate_to_pick_first - name: wrr_delegate_to_pick_first
default: true default: true

@ -173,6 +173,8 @@ class Arena {
} }
} }
// Allocates T from the arena.
// The caller is responsible for calling p->~T(), but should NOT delete.
// TODO(roth): We currently assume that all callers need alignment of 16 // TODO(roth): We currently assume that all callers need alignment of 16
// bytes, which may be wrong in some cases. When we have time, we should // bytes, which may be wrong in some cases. When we have time, we should
// change this to instead use the alignment of the type being allocated by // change this to instead use the alignment of the type being allocated by
@ -185,6 +187,7 @@ class Arena {
} }
// Like New, but has the arena call p->~T() at arena destruction time. // Like New, but has the arena call p->~T() at arena destruction time.
// The caller should NOT delete.
template <typename T, typename... Args> template <typename T, typename... Args>
T* ManagedNew(Args&&... args) { T* ManagedNew(Args&&... args) {
auto* p = New<ManagedNewImpl<T>>(std::forward<Args>(args)...); auto* p = New<ManagedNewImpl<T>>(std::forward<Args>(args)...);

@ -53,15 +53,22 @@ namespace grpc_core {
namespace experimental { namespace experimental {
namespace { namespace {
std::string IssuerFromCrl(X509_CRL* crl) { // TODO(gtcooke94) Move ssl_transport_security_utils to it's own BUILD target
// and add this to it.
absl::StatusOr<std::string> IssuerFromCrl(X509_CRL* crl) {
if (crl == nullptr) { if (crl == nullptr) {
return ""; return absl::InvalidArgumentError("crl cannot be null");
} }
char* buf = X509_NAME_oneline(X509_CRL_get_issuer(crl), nullptr, 0); X509_NAME* issuer = X509_CRL_get_issuer(crl);
std::string ret; if (issuer == nullptr) {
if (buf != nullptr) { return absl::InvalidArgumentError("crl cannot have null issuer");
ret = buf;
} }
unsigned char* buf = nullptr;
int len = i2d_X509_NAME(issuer, &buf);
if (len < 0 || buf == nullptr) {
return absl::InvalidArgumentError("crl cannot have null issuer");
}
std::string ret(reinterpret_cast<char const*>(buf), len);
OPENSSL_free(buf); OPENSSL_free(buf);
return ret; return ret;
} }
@ -103,11 +110,11 @@ absl::StatusOr<std::unique_ptr<Crl>> Crl::Parse(absl::string_view crl_string) {
} }
absl::StatusOr<std::unique_ptr<CrlImpl>> CrlImpl::Create(X509_CRL* crl) { absl::StatusOr<std::unique_ptr<CrlImpl>> CrlImpl::Create(X509_CRL* crl) {
std::string issuer = IssuerFromCrl(crl); absl::StatusOr<std::string> issuer = IssuerFromCrl(crl);
if (issuer.empty()) { if (!issuer.ok()) {
return absl::InvalidArgumentError("Issuer of crl cannot be empty"); return issuer.status();
} }
return std::make_unique<CrlImpl>(crl, issuer); return std::make_unique<CrlImpl>(crl, *issuer);
} }
CrlImpl::~CrlImpl() { X509_CRL_free(crl_); } CrlImpl::~CrlImpl() { X509_CRL_free(crl_); }

@ -648,31 +648,12 @@ class FilterStackCall final : public Call {
} }
bool completed_batch_step(PendingOp op) { bool completed_batch_step(PendingOp op) {
auto mask = PendingOpMask(op); auto mask = PendingOpMask(op);
// Acquire call tracer before ops_pending_.fetch_sub to avoid races with
// call_ being set to nullptr in PostCompletion method. Store the
// call_tracer_ and call_ variables locally as well because they could be
// modified by another thread after the fetch_sub operation.
CallTracerAnnotationInterface* call_tracer = call_tracer_;
FilterStackCall* call = call_;
bool is_call_trace_enabled = grpc_call_trace.enabled();
bool is_call_ops_annotate_enabled =
(IsTraceRecordCallopsEnabled() && call_tracer != nullptr);
if (is_call_ops_annotate_enabled) {
call->InternalRef("Call ops annotate");
}
auto r = ops_pending_.fetch_sub(mask, std::memory_order_acq_rel); auto r = ops_pending_.fetch_sub(mask, std::memory_order_acq_rel);
if (is_call_trace_enabled || is_call_ops_annotate_enabled) { if (grpc_call_trace.enabled()) {
std::string trace_string = absl::StrFormat( gpr_log(GPR_DEBUG, "BATCH:%p COMPLETE:%s REMAINING:%s (tag:%p)", this,
"BATCH:%p COMPLETE:%s REMAINING:%s (tag:%p)", this, PendingOpString(mask).c_str(),
PendingOpString(mask).c_str(), PendingOpString(r & ~mask).c_str(), PendingOpString(r & ~mask).c_str(),
completion_data_.notify_tag.tag); completion_data_.notify_tag.tag);
if (is_call_trace_enabled) {
gpr_log(GPR_DEBUG, "%s", trace_string.c_str());
}
if (is_call_ops_annotate_enabled) {
call_tracer->RecordAnnotation(trace_string);
call->InternalUnref("Call ops annotate");
}
} }
GPR_ASSERT((r & mask) != 0); GPR_ASSERT((r & mask) != 0);
return r == mask; return r == mask;
@ -1538,7 +1519,6 @@ grpc_call_error FilterStackCall::StartBatch(const grpc_op* ops, size_t nops,
grpc_transport_stream_op_batch_payload* stream_op_payload; grpc_transport_stream_op_batch_payload* stream_op_payload;
uint32_t seen_ops = 0; uint32_t seen_ops = 0;
intptr_t pending_ops = 0; intptr_t pending_ops = 0;
CallTracerAnnotationInterface* call_tracer = nullptr;
for (i = 0; i < nops; i++) { for (i = 0; i < nops; i++) {
if (seen_ops & (1u << ops[i].op)) { if (seen_ops & (1u << ops[i].op)) {
@ -1899,15 +1879,6 @@ grpc_call_error FilterStackCall::StartBatch(const grpc_op* ops, size_t nops,
stream_op->on_complete = &bctl->finish_batch_; stream_op->on_complete = &bctl->finish_batch_;
} }
call_tracer = static_cast<CallTracerAnnotationInterface*>(
ContextGet(GRPC_CONTEXT_CALL_TRACER_ANNOTATION_INTERFACE));
if ((IsTraceRecordCallopsEnabled() && call_tracer != nullptr)) {
call_tracer->RecordAnnotation(absl::StrFormat(
"BATCH:%p START:%s BATCH:%s (tag:%p)", bctl,
PendingOpString(pending_ops).c_str(),
grpc_transport_stream_op_batch_string(stream_op, true).c_str(),
bctl->completion_data_.notify_tag.tag));
}
if (grpc_call_trace.enabled()) { if (grpc_call_trace.enabled()) {
gpr_log(GPR_DEBUG, "BATCH:%p START:%s BATCH:%s (tag:%p)", bctl, gpr_log(GPR_DEBUG, "BATCH:%p START:%s BATCH:%s (tag:%p)", bctl,
PendingOpString(pending_ops).c_str(), PendingOpString(pending_ops).c_str(),

@ -136,8 +136,8 @@ void grpc_shutdown_internal_locked(void)
g_shutting_down_cv->SignalAll(); g_shutting_down_cv->SignalAll();
} }
void grpc_shutdown_internal(void* /*ignored*/) { void grpc_shutdown_from_cleanup_thread(void* /*ignored*/) {
GRPC_API_TRACE("grpc_shutdown_internal", 0, ()); GRPC_API_TRACE("grpc_shutdown_from_cleanup_thread", 0, ());
grpc_core::MutexLock lock(g_init_mu); grpc_core::MutexLock lock(g_init_mu);
// We have released lock from the shutdown thread and it is possible that // We have released lock from the shutdown thread and it is possible that
// another grpc_init has been called, and do nothing if that is the case. // another grpc_init has been called, and do nothing if that is the case.
@ -145,6 +145,7 @@ void grpc_shutdown_internal(void* /*ignored*/) {
return; return;
} }
grpc_shutdown_internal_locked(); grpc_shutdown_internal_locked();
gpr_log(GPR_DEBUG, "grpc_shutdown from cleanup thread done");
} }
void grpc_shutdown(void) { void grpc_shutdown(void) {
@ -165,6 +166,7 @@ void grpc_shutdown(void) {
gpr_log(GPR_DEBUG, "grpc_shutdown starts clean-up now"); gpr_log(GPR_DEBUG, "grpc_shutdown starts clean-up now");
g_shutting_down = true; g_shutting_down = true;
grpc_shutdown_internal_locked(); grpc_shutdown_internal_locked();
gpr_log(GPR_DEBUG, "grpc_shutdown done");
} else { } else {
// spawn a detached thread to do the actual clean up in case we are // spawn a detached thread to do the actual clean up in case we are
// currently in an executor thread. // currently in an executor thread.
@ -172,7 +174,7 @@ void grpc_shutdown(void) {
g_initializations++; g_initializations++;
g_shutting_down = true; g_shutting_down = true;
grpc_core::Thread cleanup_thread( grpc_core::Thread cleanup_thread(
"grpc_shutdown", grpc_shutdown_internal, nullptr, nullptr, "grpc_shutdown", grpc_shutdown_from_cleanup_thread, nullptr, nullptr,
grpc_core::Thread::Options().set_joinable(false).set_tracked(false)); grpc_core::Thread::Options().set_joinable(false).set_tracked(false));
cleanup_thread.Start(); cleanup_thread.Start();
} }

@ -880,7 +880,8 @@ void XdsResolver::ClusterSelectionFilter::Call::OnClientInitialMetadata(
// //
void XdsResolver::StartLocked() { void XdsResolver::StartLocked() {
auto xds_client = GrpcXdsClient::GetOrCreate(args_, "xds resolver"); auto xds_client =
GrpcXdsClient::GetOrCreate(uri_.ToString(), args_, "xds resolver");
if (!xds_client.ok()) { if (!xds_client.ok()) {
gpr_log(GPR_ERROR, gpr_log(GPR_ERROR,
"Failed to create xds client -- channel will remain in " "Failed to create xds client -- channel will remain in "

@ -1004,15 +1004,14 @@ static int GetCrlFromProvider(X509_STORE_CTX* ctx, X509_CRL** crl_out,
auto* provider = static_cast<grpc_core::experimental::CrlProvider*>( auto* provider = static_cast<grpc_core::experimental::CrlProvider*>(
SSL_CTX_get_ex_data(ssl_ctx, g_ssl_ctx_ex_crl_provider_index)); SSL_CTX_get_ex_data(ssl_ctx, g_ssl_ctx_ex_crl_provider_index));
char* buf = X509_NAME_oneline(X509_get_issuer_name(cert), nullptr, 0); absl::StatusOr<std::string> issuer_name = grpc_core::IssuerFromCert(cert);
if (buf == nullptr) { if (!issuer_name.ok()) {
gpr_log(GPR_ERROR, "Certificate has null issuer, cannot do CRL lookup"); gpr_log(GPR_INFO, "Could not get certificate issuer name");
return 0; return 0;
} }
grpc_core::experimental::CertificateInfoImpl cert_impl(buf); grpc_core::experimental::CertificateInfoImpl cert_impl(*issuer_name);
std::shared_ptr<grpc_core::experimental::Crl> internal_crl = std::shared_ptr<grpc_core::experimental::Crl> internal_crl =
provider->GetCrl(cert_impl); provider->GetCrl(cert_impl);
OPENSSL_free(buf);
// There wasn't a CRL found in the provider. Returning 0 will end up causing // There wasn't a CRL found in the provider. Returning 0 will end up causing
// OpenSSL to return X509_V_ERR_UNABLE_TO_GET_CRL. We then catch that error // OpenSSL to return X509_V_ERR_UNABLE_TO_GET_CRL. We then catch that error
// and behave how we want for a missing CRL. // and behave how we want for a missing CRL.

@ -23,6 +23,10 @@
#include <openssl/crypto.h> #include <openssl/crypto.h>
#include <openssl/err.h> #include <openssl/err.h>
#include <openssl/ssl.h> #include <openssl/ssl.h>
#include <openssl/x509v3.h>
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "src/core/tsi/transport_security_interface.h" #include "src/core/tsi/transport_security_interface.h"
@ -247,4 +251,70 @@ tsi_result SslProtectorUnprotect(const unsigned char* protected_frames_bytes,
return result; return result;
} }
bool VerifyCrlSignature(X509_CRL* crl, X509* issuer) {
if (issuer == nullptr || crl == nullptr) {
return false;
}
EVP_PKEY* ikey = X509_get_pubkey(issuer);
if (ikey == nullptr) {
// Can't verify signature because we couldn't get the pubkey, fail the
// check.
EVP_PKEY_free(ikey);
return false;
}
bool ret = X509_CRL_verify(crl, ikey) == 1;
EVP_PKEY_free(ikey);
return ret;
}
bool VerifyCrlCertIssuerNamesMatch(X509_CRL* crl, X509* cert) {
if (cert == nullptr || crl == nullptr) {
return false;
}
X509_NAME* cert_issuer_name = X509_get_issuer_name(cert);
if (cert == nullptr) {
return false;
}
X509_NAME* crl_issuer_name = X509_CRL_get_issuer(crl);
if (crl_issuer_name == nullptr) {
return false;
}
return X509_NAME_cmp(cert_issuer_name, crl_issuer_name) == 0;
}
bool HasCrlSignBit(X509* cert) {
if (cert == nullptr) {
return false;
}
// X509_get_key_usage was introduced in 1.1.1
// A missing key usage extension means all key usages are valid.
#if OPENSSL_VERSION_NUMBER < 0x10100000
// X509_check_ca sets cert->ex_flags. We dont use the return value, but those
// flags being set is important.
// https://github.com/openssl/openssl/blob/e818b74be2170fbe957a07b0da4401c2b694b3b8/crypto/x509v3/v3_purp.c#L585
X509_check_ca(cert);
if (!(cert->ex_flags & EXFLAG_KUSAGE)) {
return true;
}
return (cert->ex_kusage & KU_CRL_SIGN) != 0;
#else
return (X509_get_key_usage(cert) & KU_CRL_SIGN) != 0;
#endif // OPENSSL_VERSION_NUMBER < 0x10100000
}
absl::StatusOr<std::string> IssuerFromCert(X509* cert) {
if (cert == nullptr) {
return absl::InvalidArgumentError("cert cannot be null");
}
X509_NAME* issuer = X509_get_issuer_name(cert);
unsigned char* buf = nullptr;
int len = i2d_X509_NAME(issuer, &buf);
if (len < 0 || buf == nullptr) {
return absl::InvalidArgumentError("could not read issuer name from cert");
}
std::string ret(reinterpret_cast<char const*>(buf), len);
OPENSSL_free(buf);
return ret;
}
} // namespace grpc_core } // namespace grpc_core

@ -23,6 +23,8 @@
#include <openssl/x509.h> #include <openssl/x509.h>
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/string_view.h" #include "absl/strings/string_view.h"
#include <grpc/grpc_security_constants.h> #include <grpc/grpc_security_constants.h>
@ -142,6 +144,22 @@ tsi_result SslProtectorUnprotect(const unsigned char* protected_frames_bytes,
unsigned char* unprotected_bytes, unsigned char* unprotected_bytes,
size_t* unprotected_bytes_size); size_t* unprotected_bytes_size);
// Verifies that `crl` was signed by `issuer.
// return: true if valid, false otherwise.
bool VerifyCrlSignature(X509_CRL* crl, X509* issuer);
// Verifies the CRL issuer and certificate issuer name match.
// return: true if equal, false if not.
bool VerifyCrlCertIssuerNamesMatch(X509_CRL* crl, X509* cert);
// Verifies the certificate in question has the cRLSign bit present.
// return: true if cRLSign bit is present, false otherwise.
bool HasCrlSignBit(X509* cert);
// Gets a stable representation of the issuer name from an X509 certificate.
// return: a std::string of the DER encoding of the X509_NAME issuer name.
absl::StatusOr<std::string> IssuerFromCert(X509* cert);
} // namespace grpc_core } // namespace grpc_core
#endif // GRPC_SRC_CORE_TSI_SSL_TRANSPORT_SECURITY_UTILS_H #endif // GRPC_SRC_CORE_TSI_SSL_TRANSPORT_SECURITY_UTILS_H

@ -74,11 +74,11 @@ class ObservabilityPlugin(
interface and wrapped in a PyCapsule using `client_call_tracer` as name. interface and wrapped in a PyCapsule using `client_call_tracer` as name.
Args: Args:
method_name: The method name of the call in byte format. method_name: The method name of the call in byte format.
target: The channel target of the call in byte format. target: The channel target of the call in byte format.
Returns: Returns:
A PyCapsule which stores a ClientCallTracer object. A PyCapsule which stores a ClientCallTracer object.
""" """
raise NotImplementedError() raise NotImplementedError()
@ -95,7 +95,7 @@ class ObservabilityPlugin(
interface and wrapped in a PyCapsule using `client_call_tracer` as name. interface and wrapped in a PyCapsule using `client_call_tracer` as name.
Args: Args:
client_call_tracer: A PyCapsule which stores a ClientCallTracer object. client_call_tracer: A PyCapsule which stores a ClientCallTracer object.
""" """
raise NotImplementedError() raise NotImplementedError()
@ -111,12 +111,12 @@ class ObservabilityPlugin(
This method can be used to propagate census context. This method can be used to propagate census context.
Args: Args:
trace_id: The identifier for the trace associated with the span as a trace_id: The identifier for the trace associated with the span as a
32-character hexadecimal encoded string, 32-character hexadecimal encoded string,
e.g. 26ed0036f2eff2b7317bccce3e28d01f e.g. 26ed0036f2eff2b7317bccce3e28d01f
span_id: The identifier for the span as a 16-character hexadecimal encoded span_id: The identifier for the span as a 16-character hexadecimal encoded
string. e.g. 113ec879e62583bc string. e.g. 113ec879e62583bc
is_sampled: A bool indicates whether the span is sampled. is_sampled: A bool indicates whether the span is sampled.
""" """
raise NotImplementedError() raise NotImplementedError()
@ -135,7 +135,7 @@ class ObservabilityPlugin(
using `server_call_tracer_factory` as name. using `server_call_tracer_factory` as name.
Returns: Returns:
A PyCapsule which stores a ServerCallTracerFactory object. A PyCapsule which stores a ServerCallTracerFactory object.
""" """
raise NotImplementedError() raise NotImplementedError()
@ -149,12 +149,12 @@ class ObservabilityPlugin(
called at the end of each RPC. called at the end of each RPC.
Args: Args:
method: The fully-qualified name of the RPC method being invoked. method: The fully-qualified name of the RPC method being invoked.
target: The target name of the RPC method being invoked. target: The target name of the RPC method being invoked.
rpc_latency: The latency for the RPC in seconds, equals to the time between rpc_latency: The latency for the RPC in seconds, equals to the time between
when the client invokes the RPC and when the client receives the status. when the client invokes the RPC and when the client receives the status.
status_code: An element of grpc.StatusCode in string format representing the status_code: An element of grpc.StatusCode in string format representing the
final status for the RPC. final status for the RPC.
""" """
raise NotImplementedError() raise NotImplementedError()
@ -162,7 +162,7 @@ class ObservabilityPlugin(
"""Enable or disable tracing. """Enable or disable tracing.
Args: Args:
enable: A bool indicates whether tracing should be enabled. enable: A bool indicates whether tracing should be enabled.
""" """
self._tracing_enabled = enable self._tracing_enabled = enable
@ -170,7 +170,7 @@ class ObservabilityPlugin(
"""Enable or disable stats(metrics). """Enable or disable stats(metrics).
Args: Args:
enable: A bool indicates whether stats should be enabled. enable: A bool indicates whether stats should be enabled.
""" """
self._stats_enabled = enable self._stats_enabled = enable
@ -192,7 +192,7 @@ def get_plugin() -> Generator[Optional[ObservabilityPlugin], None, None]:
"""Get the ObservabilityPlugin in _observability module. """Get the ObservabilityPlugin in _observability module.
Returns: Returns:
The ObservabilityPlugin currently registered with the _observability The ObservabilityPlugin currently registered with the _observability
module. Or None if no plugin exists at the time of calling this method. module. Or None if no plugin exists at the time of calling this method.
""" """
with _plugin_lock: with _plugin_lock:
@ -203,11 +203,11 @@ def set_plugin(observability_plugin: Optional[ObservabilityPlugin]) -> None:
"""Save ObservabilityPlugin to _observability module. """Save ObservabilityPlugin to _observability module.
Args: Args:
observability_plugin: The ObservabilityPlugin to save. observability_plugin: The ObservabilityPlugin to save.
Raises: Raises:
ValueError: If an ObservabilityPlugin was already registered at the ValueError: If an ObservabilityPlugin was already registered at the
time of calling this method. time of calling this method.
""" """
global _OBSERVABILITY_PLUGIN # pylint: disable=global-statement global _OBSERVABILITY_PLUGIN # pylint: disable=global-statement
with _plugin_lock: with _plugin_lock:
@ -223,11 +223,11 @@ def observability_init(observability_plugin: ObservabilityPlugin) -> None:
channels/servers are built. channels/servers are built.
Args: Args:
observability_plugin: The ObservabilityPlugin to use. observability_plugin: The ObservabilityPlugin to use.
Raises: Raises:
ValueError: If an ObservabilityPlugin was already registered at the ValueError: If an ObservabilityPlugin was already registered at the
time of calling this method. time of calling this method.
""" """
set_plugin(observability_plugin) set_plugin(observability_plugin)
try: try:
@ -256,7 +256,7 @@ def delete_call_tracer(client_call_tracer_capsule: Any) -> None:
interface and wrapped in a PyCapsule using `client_call_tracer` as the name. interface and wrapped in a PyCapsule using `client_call_tracer` as the name.
Args: Args:
client_call_tracer_capsule: A PyCapsule which stores a ClientCallTracer object. client_call_tracer_capsule: A PyCapsule which stores a ClientCallTracer object.
""" """
with get_plugin() as plugin: with get_plugin() as plugin:
if not (plugin and plugin.observability_enabled): if not (plugin and plugin.observability_enabled):
@ -270,8 +270,8 @@ def maybe_record_rpc_latency(state: "_channel._RPCState") -> None:
This method will be called at the end of each RPC. This method will be called at the end of each RPC.
Args: Args:
state: a grpc._channel._RPCState object which contains the stats related to the state: a grpc._channel._RPCState object which contains the stats related to the
RPC. RPC.
""" """
# TODO(xuanwn): use channel args to exclude those metrics. # TODO(xuanwn): use channel args to exclude those metrics.
for exclude_prefix in _SERVICES_TO_EXCLUDE: for exclude_prefix in _SERVICES_TO_EXCLUDE:

@ -476,7 +476,7 @@ class _InterceptedStreamResponseMixin:
_response_aiter: Optional[AsyncIterable[ResponseType]] _response_aiter: Optional[AsyncIterable[ResponseType]]
def _init_stream_response_mixin(self) -> None: def _init_stream_response_mixin(self) -> None:
# Is initalized later, otherwise if the iterator is not finnally # Is initalized later, otherwise if the iterator is not finally
# consumed a logging warning is emmited by Asyncio. # consumed a logging warning is emmited by Asyncio.
self._response_aiter = None self._response_aiter = None

@ -57,7 +57,7 @@ GCC-like stuff, but you may end up having a bad time.
Dependencies Dependencies
------------------------- ------------
gRPC Python Observability Depends on the following packages: gRPC Python Observability Depends on the following packages:
:: ::

@ -569,6 +569,7 @@ grpc_cc_test(
srcs = ["grpc_tls_crl_provider_test.cc"], srcs = ["grpc_tls_crl_provider_test.cc"],
data = [ data = [
"//test/core/tsi/test_creds/crl_data:ca.pem", "//test/core/tsi/test_creds/crl_data:ca.pem",
"//test/core/tsi/test_creds/crl_data:intermediate_ca.pem",
"//test/core/tsi/test_creds/crl_data/crls:ab06acdd.r0", "//test/core/tsi/test_creds/crl_data/crls:ab06acdd.r0",
"//test/core/tsi/test_creds/crl_data/crls:b9322cac.r0", "//test/core/tsi/test_creds/crl_data/crls:b9322cac.r0",
"//test/core/tsi/test_creds/crl_data/crls:current.crl", "//test/core/tsi/test_creds/crl_data/crls:current.crl",
@ -585,6 +586,7 @@ grpc_cc_test(
"//test/core/event_engine:event_engine_test_utils", "//test/core/event_engine:event_engine_test_utils",
"//test/core/event_engine/fuzzing_event_engine", "//test/core/event_engine/fuzzing_event_engine",
"//test/core/event_engine/fuzzing_event_engine:fuzzing_event_engine_proto", "//test/core/event_engine/fuzzing_event_engine:fuzzing_event_engine_proto",
"//test/core/tsi:transport_security_test_lib",
"//test/core/util:fuzz_config_vars_proto", "//test/core/util:fuzz_config_vars_proto",
"//test/core/util:grpc_test_util", "//test/core/util:grpc_test_util",
], ],

@ -40,16 +40,15 @@
#include "test/core/event_engine/event_engine_test_utils.h" #include "test/core/event_engine/event_engine_test_utils.h"
#include "test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.h" #include "test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.h"
#include "test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.pb.h" #include "test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.pb.h"
#include "test/core/tsi/transport_security_test_lib.h"
#include "test/core/util/test_config.h" #include "test/core/util/test_config.h"
#include "test/core/util/tls_utils.h" #include "test/core/util/tls_utils.h"
static constexpr absl::string_view kCrlPath = static constexpr absl::string_view kCrlPath =
"test/core/tsi/test_creds/crl_data/crls/current.crl"; "test/core/tsi/test_creds/crl_data/crls/current.crl";
static constexpr absl::string_view kCrlName = "current.crl"; static constexpr absl::string_view kCrlName = "current.crl";
static constexpr absl::string_view kCrlIssuer = static constexpr absl::string_view kCrlIntermediateIssuerPath =
"/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=testca"; "test/core/tsi/test_creds/crl_data/intermediate_ca.pem";
static constexpr absl::string_view kCrlIntermediateIssuer =
"/CN=intermediatecert.example.com";
static constexpr absl::string_view kCrlDirectory = static constexpr absl::string_view kCrlDirectory =
"test/core/tsi/test_creds/crl_data/crls"; "test/core/tsi/test_creds/crl_data/crls";
static constexpr absl::string_view kRootCert = static constexpr absl::string_view kRootCert =
@ -88,9 +87,35 @@ class FakeDirectoryReader : public DirectoryReader {
std::vector<std::string>(); std::vector<std::string>();
}; };
class DirectoryReloaderCrlProviderTest : public ::testing::Test { class CrlProviderTest : public ::testing::Test {
public: public:
void SetUp() override { void SetUp() override {
std::string pem_cert = GetFileContents(kRootCert.data());
X509* issuer = ReadPemCert(pem_cert);
auto base_crl_issuer = IssuerFromCert(issuer);
ASSERT_EQ(base_crl_issuer.status(), absl::OkStatus());
base_crl_issuer_ = *base_crl_issuer;
std::string intermediate_string =
GetFileContents(kCrlIntermediateIssuerPath.data());
X509* intermediate_issuer = ReadPemCert(intermediate_string);
auto intermediate_crl_issuer = IssuerFromCert(intermediate_issuer);
ASSERT_EQ(intermediate_crl_issuer.status(), absl::OkStatus());
intermediate_crl_issuer_ = *intermediate_crl_issuer;
X509_free(issuer);
X509_free(intermediate_issuer);
}
void TearDown() override {}
protected:
std::string base_crl_issuer_;
std::string intermediate_crl_issuer_;
};
class DirectoryReloaderCrlProviderTest : public CrlProviderTest {
public:
void SetUp() override {
CrlProviderTest::SetUp();
event_engine_ = event_engine_ =
std::make_shared<grpc_event_engine::experimental::FuzzingEventEngine>( std::make_shared<grpc_event_engine::experimental::FuzzingEventEngine>(
grpc_event_engine::experimental::FuzzingEventEngine::Options(), grpc_event_engine::experimental::FuzzingEventEngine::Options(),
@ -140,15 +165,15 @@ class DirectoryReloaderCrlProviderTest : public ::testing::Test {
event_engine_; event_engine_;
}; };
TEST(CrlProviderTest, CanParseCrl) { TEST_F(CrlProviderTest, CanParseCrl) {
std::string crl_string = GetFileContents(kCrlPath.data()); std::string crl_string = GetFileContents(kCrlPath.data());
absl::StatusOr<std::shared_ptr<Crl>> crl = Crl::Parse(crl_string); absl::StatusOr<std::shared_ptr<Crl>> crl = Crl::Parse(crl_string);
ASSERT_TRUE(crl.ok()) << crl.status(); ASSERT_TRUE(crl.ok()) << crl.status();
ASSERT_NE(*crl, nullptr); ASSERT_NE(*crl, nullptr);
EXPECT_EQ((*crl)->Issuer(), kCrlIssuer); EXPECT_EQ((*crl)->Issuer(), base_crl_issuer_);
} }
TEST(CrlProviderTest, InvalidFile) { TEST_F(CrlProviderTest, InvalidFile) {
std::string crl_string = "INVALID CRL FILE"; std::string crl_string = "INVALID CRL FILE";
absl::StatusOr<std::shared_ptr<Crl>> crl = Crl::Parse(crl_string); absl::StatusOr<std::shared_ptr<Crl>> crl = Crl::Parse(crl_string);
EXPECT_EQ(crl.status(), EXPECT_EQ(crl.status(),
@ -156,18 +181,18 @@ TEST(CrlProviderTest, InvalidFile) {
"Conversion from PEM string to X509 CRL failed.")); "Conversion from PEM string to X509 CRL failed."));
} }
TEST(CrlProviderTest, StaticCrlProviderLookup) { TEST_F(CrlProviderTest, StaticCrlProviderLookup) {
std::vector<std::string> crl_strings = {GetFileContents(kCrlPath.data())}; std::vector<std::string> crl_strings = {GetFileContents(kCrlPath.data())};
absl::StatusOr<std::shared_ptr<CrlProvider>> provider = absl::StatusOr<std::shared_ptr<CrlProvider>> provider =
experimental::CreateStaticCrlProvider(crl_strings); experimental::CreateStaticCrlProvider(crl_strings);
ASSERT_TRUE(provider.ok()) << provider.status(); ASSERT_TRUE(provider.ok()) << provider.status();
CertificateInfoImpl cert(kCrlIssuer); CertificateInfoImpl cert(base_crl_issuer_);
auto crl = (*provider)->GetCrl(cert); auto crl = (*provider)->GetCrl(cert);
ASSERT_NE(crl, nullptr); ASSERT_NE(crl, nullptr);
EXPECT_EQ(crl->Issuer(), kCrlIssuer); EXPECT_EQ(crl->Issuer(), base_crl_issuer_);
} }
TEST(CrlProviderTest, StaticCrlProviderLookupIssuerNotFound) { TEST_F(CrlProviderTest, StaticCrlProviderLookupIssuerNotFound) {
std::vector<std::string> crl_strings = {GetFileContents(kCrlPath.data())}; std::vector<std::string> crl_strings = {GetFileContents(kCrlPath.data())};
absl::StatusOr<std::shared_ptr<CrlProvider>> provider = absl::StatusOr<std::shared_ptr<CrlProvider>> provider =
experimental::CreateStaticCrlProvider(crl_strings); experimental::CreateStaticCrlProvider(crl_strings);
@ -181,14 +206,14 @@ TEST_F(DirectoryReloaderCrlProviderTest, CrlLookupGood) {
auto provider = auto provider =
CreateCrlProvider(kCrlDirectory, std::chrono::seconds(60), nullptr); CreateCrlProvider(kCrlDirectory, std::chrono::seconds(60), nullptr);
ASSERT_TRUE(provider.ok()) << provider.status(); ASSERT_TRUE(provider.ok()) << provider.status();
CertificateInfoImpl cert(kCrlIssuer); CertificateInfoImpl cert(base_crl_issuer_);
auto crl = (*provider)->GetCrl(cert); auto crl = (*provider)->GetCrl(cert);
ASSERT_NE(crl, nullptr); ASSERT_NE(crl, nullptr);
EXPECT_EQ(crl->Issuer(), kCrlIssuer); EXPECT_EQ(crl->Issuer(), base_crl_issuer_);
CertificateInfoImpl intermediate(kCrlIntermediateIssuer); CertificateInfoImpl intermediate(intermediate_crl_issuer_);
auto intermediate_crl = (*provider)->GetCrl(intermediate); auto intermediate_crl = (*provider)->GetCrl(intermediate);
ASSERT_NE(intermediate_crl, nullptr); ASSERT_NE(intermediate_crl, nullptr);
EXPECT_EQ(intermediate_crl->Issuer(), kCrlIntermediateIssuer); EXPECT_EQ(intermediate_crl->Issuer(), intermediate_crl_issuer_);
} }
TEST_F(DirectoryReloaderCrlProviderTest, CrlLookupMissingIssuer) { TEST_F(DirectoryReloaderCrlProviderTest, CrlLookupMissingIssuer) {
@ -204,7 +229,7 @@ TEST_F(DirectoryReloaderCrlProviderTest, ReloadsAndDeletes) {
const std::chrono::seconds kRefreshDuration(60); const std::chrono::seconds kRefreshDuration(60);
auto provider = CreateCrlProvider(kRefreshDuration, nullptr); auto provider = CreateCrlProvider(kRefreshDuration, nullptr);
ASSERT_TRUE(provider.ok()) << provider.status(); ASSERT_TRUE(provider.ok()) << provider.status();
CertificateInfoImpl cert(kCrlIssuer); CertificateInfoImpl cert(base_crl_issuer_);
auto should_be_no_crl = (*provider)->GetCrl(cert); auto should_be_no_crl = (*provider)->GetCrl(cert);
ASSERT_EQ(should_be_no_crl, nullptr); ASSERT_EQ(should_be_no_crl, nullptr);
// Give the provider files to find in the directory // Give the provider files to find in the directory
@ -212,7 +237,7 @@ TEST_F(DirectoryReloaderCrlProviderTest, ReloadsAndDeletes) {
event_engine_->TickForDuration(kRefreshDuration); event_engine_->TickForDuration(kRefreshDuration);
auto crl = (*provider)->GetCrl(cert); auto crl = (*provider)->GetCrl(cert);
ASSERT_NE(crl, nullptr); ASSERT_NE(crl, nullptr);
EXPECT_EQ(crl->Issuer(), kCrlIssuer); EXPECT_EQ(crl->Issuer(), base_crl_issuer_);
// Now we won't see any files in our directory // Now we won't see any files in our directory
directory_reader_->SetFilesInDirectory({}); directory_reader_->SetFilesInDirectory({});
event_engine_->TickForDuration(kRefreshDuration); event_engine_->TickForDuration(kRefreshDuration);
@ -229,10 +254,10 @@ TEST_F(DirectoryReloaderCrlProviderTest, WithCorruption) {
auto provider = auto provider =
CreateCrlProvider(kRefreshDuration, std::move(reload_error_callback)); CreateCrlProvider(kRefreshDuration, std::move(reload_error_callback));
ASSERT_TRUE(provider.ok()) << provider.status(); ASSERT_TRUE(provider.ok()) << provider.status();
CertificateInfoImpl cert(kCrlIssuer); CertificateInfoImpl cert(base_crl_issuer_);
auto crl = (*provider)->GetCrl(cert); auto crl = (*provider)->GetCrl(cert);
ASSERT_NE(crl, nullptr); ASSERT_NE(crl, nullptr);
EXPECT_EQ(crl->Issuer(), kCrlIssuer); EXPECT_EQ(crl->Issuer(), base_crl_issuer_);
EXPECT_EQ(reload_errors.size(), 0); EXPECT_EQ(reload_errors.size(), 0);
// Point the provider at a non-crl file so loading fails // Point the provider at a non-crl file so loading fails
// Should result in the CRL Reloader keeping the old CRL data // Should result in the CRL Reloader keeping the old CRL data
@ -240,7 +265,7 @@ TEST_F(DirectoryReloaderCrlProviderTest, WithCorruption) {
event_engine_->TickForDuration(kRefreshDuration); event_engine_->TickForDuration(kRefreshDuration);
auto crl_post_update = (*provider)->GetCrl(cert); auto crl_post_update = (*provider)->GetCrl(cert);
ASSERT_NE(crl_post_update, nullptr); ASSERT_NE(crl_post_update, nullptr);
EXPECT_EQ(crl_post_update->Issuer(), kCrlIssuer); EXPECT_EQ(crl_post_update->Issuer(), base_crl_issuer_);
EXPECT_EQ(reload_errors.size(), 1); EXPECT_EQ(reload_errors.size(), 1);
} }

@ -64,12 +64,23 @@ grpc_cc_test(
grpc_cc_test( grpc_cc_test(
name = "ssl_transport_security_utils_test", name = "ssl_transport_security_utils_test",
srcs = ["ssl_transport_security_utils_test.cc"], srcs = ["ssl_transport_security_utils_test.cc"],
data = [
"//test/core/tsi/test_creds/crl_data:ca.pem",
"//test/core/tsi/test_creds/crl_data:evil_ca.pem",
"//test/core/tsi/test_creds/crl_data:intermediate_ca.pem",
"//test/core/tsi/test_creds/crl_data:leaf_signed_by_intermediate.pem",
"//test/core/tsi/test_creds/crl_data/crls:current.crl",
"//test/core/tsi/test_creds/crl_data/crls:intermediate.crl",
"//test/core/tsi/test_creds/crl_data/crls:invalid_content.crl",
"//test/core/tsi/test_creds/crl_data/crls:invalid_signature.crl",
],
external_deps = ["gtest"], external_deps = ["gtest"],
language = "C++", language = "C++",
tags = ["no_windows"], tags = ["no_windows"],
deps = [ deps = [
"//:gpr", "//:gpr",
"//:grpc", "//:grpc",
"//test/core/tsi:transport_security_test_lib",
"//test/core/util:grpc_test_util", "//test/core/util:grpc_test_util",
], ],
) )

@ -25,6 +25,7 @@
#include <openssl/bio.h> #include <openssl/bio.h>
#include <openssl/crypto.h> #include <openssl/crypto.h>
#include <openssl/ssl.h> #include <openssl/ssl.h>
#include <openssl/x509.h>
#include "absl/status/status.h" #include "absl/status/status.h"
#include "absl/status/statusor.h" #include "absl/status/statusor.h"
@ -32,13 +33,30 @@
#include "absl/strings/str_cat.h" #include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h" #include "absl/strings/string_view.h"
#include "src/core/lib/gprpp/load_file.h"
#include "src/core/lib/slice/slice.h"
#include "src/core/tsi/transport_security.h" #include "src/core/tsi/transport_security.h"
#include "src/core/tsi/transport_security_interface.h" #include "src/core/tsi/transport_security_interface.h"
#include "test/core/tsi/transport_security_test_lib.h"
#include "test/core/util/test_config.h" #include "test/core/util/test_config.h"
namespace grpc_core { namespace grpc_core {
namespace testing { namespace testing {
const char* kValidCrl = "test/core/tsi/test_creds/crl_data/crls/current.crl";
const char* kCrlIssuer = "test/core/tsi/test_creds/crl_data/ca.pem";
const char* kModifiedSignature =
"test/core/tsi/test_creds/crl_data/crls/invalid_signature.crl";
const char* kModifiedContent =
"test/core/tsi/test_creds/crl_data/crls/invalid_content.crl";
const char* kIntermediateCrl =
"test/core/tsi/test_creds/crl_data/crls/intermediate.crl";
const char* kIntermediateCrlIssuer =
"test/core/tsi/test_creds/crl_data/intermediate_ca.pem";
const char* kLeafCert =
"test/core/tsi/test_creds/crl_data/leaf_signed_by_intermediate.pem";
const char* kEvilCa = "test/core/tsi/test_creds/crl_data/evil_ca.pem";
using ::testing::ContainerEq; using ::testing::ContainerEq;
using ::testing::NotNull; using ::testing::NotNull;
using ::testing::TestWithParam; using ::testing::TestWithParam;
@ -316,8 +334,8 @@ TEST_P(FlowTest,
&protected_output_frames_size), &protected_output_frames_size),
tsi_result::TSI_OK); tsi_result::TSI_OK);
// If |GetParam().plaintext_size| is larger than the inner client_buffer size // If |GetParam().plaintext_size| is larger than the inner client_buffer
// (kMaxPlaintextBytesPerTlsRecord), then |Protect| will copy up to // size (kMaxPlaintextBytesPerTlsRecord), then |Protect| will copy up to
// |kMaxPlaintextBytesPerTlsRecord| bytes and output the protected // |kMaxPlaintextBytesPerTlsRecord| bytes and output the protected
// frame. Otherwise we need to manually flush the copied data in order // frame. Otherwise we need to manually flush the copied data in order
// to get the protected frame. // to get the protected frame.
@ -378,8 +396,8 @@ TEST_P(FlowTest,
&protected_output_frames_size), &protected_output_frames_size),
tsi_result::TSI_OK); tsi_result::TSI_OK);
// If |GetParam().plaintext_size| is larger than the inner server_buffer size // If |GetParam().plaintext_size| is larger than the inner server_buffer
// (kMaxPlaintextBytesPerTlsRecord), then |Protect| will copy up to // size (kMaxPlaintextBytesPerTlsRecord), then |Protect| will copy up to
// |kMaxPlaintextBytesPerTlsRecord| bytes and output the protected // |kMaxPlaintextBytesPerTlsRecord| bytes and output the protected
// frame. Otherwise we need to manually flush the copied data in order // frame. Otherwise we need to manually flush the copied data in order
// to get the protected frame. // to get the protected frame.
@ -429,6 +447,188 @@ INSTANTIATE_TEST_SUITE_P(FrameProtectorUtil, FlowTest,
#endif // OPENSSL_IS_BORINGSSL #endif // OPENSSL_IS_BORINGSSL
class CrlUtils : public ::testing::Test {
public:
static void SetUpTestSuite() {
#if OPENSSL_VERSION_NUMBER >= 0x10100000
OPENSSL_init_ssl(/*opts=*/0, /*settings=*/nullptr);
#else
SSL_library_init();
SSL_load_error_strings();
OpenSSL_add_all_algorithms();
#endif
}
void SetUp() override {
absl::StatusOr<Slice> root_crl = LoadFile(kValidCrl, false);
ASSERT_EQ(root_crl.status(), absl::OkStatus()) << root_crl.status();
root_crl_ = ReadCrl(root_crl->as_string_view());
absl::StatusOr<Slice> intermediate_crl = LoadFile(kIntermediateCrl, false);
ASSERT_EQ(intermediate_crl.status(), absl::OkStatus())
<< intermediate_crl.status();
intermediate_crl_ = ReadCrl(intermediate_crl->as_string_view());
absl::StatusOr<Slice> invalid_signature_crl =
LoadFile(kModifiedSignature, false);
ASSERT_EQ(invalid_signature_crl.status(), absl::OkStatus())
<< invalid_signature_crl.status();
invalid_signature_crl_ = ReadCrl(invalid_signature_crl->as_string_view());
absl::StatusOr<Slice> root_ca = LoadFile(kCrlIssuer, false);
ASSERT_EQ(root_ca.status(), absl::OkStatus());
root_ca_ = ReadPemCert(root_ca->as_string_view());
absl::StatusOr<Slice> intermediate_ca =
LoadFile(kIntermediateCrlIssuer, false);
ASSERT_EQ(intermediate_ca.status(), absl::OkStatus());
intermediate_ca_ = ReadPemCert(intermediate_ca->as_string_view());
absl::StatusOr<Slice> leaf_cert = LoadFile(kLeafCert, false);
ASSERT_EQ(leaf_cert.status(), absl::OkStatus());
leaf_cert_ = ReadPemCert(leaf_cert->as_string_view());
absl::StatusOr<Slice> evil_ca = LoadFile(kEvilCa, false);
ASSERT_EQ(evil_ca.status(), absl::OkStatus());
evil_ca_ = ReadPemCert(evil_ca->as_string_view());
}
void TearDown() override {
X509_CRL_free(root_crl_);
X509_CRL_free(intermediate_crl_);
X509_CRL_free(invalid_signature_crl_);
X509_free(root_ca_);
X509_free(intermediate_ca_);
X509_free(leaf_cert_);
X509_free(evil_ca_);
}
protected:
X509_CRL* root_crl_;
X509_CRL* intermediate_crl_;
X509_CRL* invalid_signature_crl_;
X509* root_ca_;
X509* intermediate_ca_;
X509* leaf_cert_;
X509* evil_ca_;
};
TEST_F(CrlUtils, VerifySignatureValid) {
EXPECT_TRUE(VerifyCrlSignature(root_crl_, root_ca_));
}
TEST_F(CrlUtils, VerifySignatureIntermediateValid) {
EXPECT_TRUE(VerifyCrlSignature(intermediate_crl_, intermediate_ca_));
}
TEST_F(CrlUtils, VerifySignatureModifiedSignature) {
EXPECT_FALSE(VerifyCrlSignature(invalid_signature_crl_, root_ca_));
}
TEST_F(CrlUtils, VerifySignatureModifiedContent) {
absl::StatusOr<Slice> crl_slice = LoadFile(kModifiedContent, false);
ASSERT_EQ(crl_slice.status(), absl::OkStatus()) << crl_slice.status();
X509_CRL* crl = ReadCrl(crl_slice->as_string_view());
EXPECT_EQ(crl, nullptr);
}
TEST_F(CrlUtils, VerifySignatureWrongIssuer) {
EXPECT_FALSE(VerifyCrlSignature(root_crl_, intermediate_ca_));
}
TEST_F(CrlUtils, VerifySignatureWrongIssuer2) {
EXPECT_FALSE(VerifyCrlSignature(intermediate_crl_, root_ca_));
}
TEST_F(CrlUtils, VerifySignatureNullCrl) {
EXPECT_FALSE(VerifyCrlSignature(nullptr, root_ca_));
}
TEST_F(CrlUtils, VerifySignatureNullCert) {
EXPECT_FALSE(VerifyCrlSignature(intermediate_crl_, nullptr));
}
TEST_F(CrlUtils, VerifySignatureNullCrlAndCert) {
EXPECT_FALSE(VerifyCrlSignature(nullptr, nullptr));
}
TEST_F(CrlUtils, VerifyIssuerNamesMatch) {
EXPECT_TRUE(VerifyCrlCertIssuerNamesMatch(root_crl_, root_ca_));
}
TEST_F(CrlUtils, VerifyIssuerNamesDontMatch) {
EXPECT_FALSE(VerifyCrlCertIssuerNamesMatch(root_crl_, leaf_cert_));
}
TEST_F(CrlUtils, DuplicatedIssuerNamePassesButSignatureCheckFails) {
// The issuer names will match, but it should fail a signature check
EXPECT_TRUE(VerifyCrlCertIssuerNamesMatch(root_crl_, evil_ca_));
EXPECT_FALSE(VerifyCrlSignature(root_crl_, evil_ca_));
}
TEST_F(CrlUtils, VerifyIssuerNameNullCrl) {
EXPECT_FALSE(VerifyCrlCertIssuerNamesMatch(nullptr, root_ca_));
}
TEST_F(CrlUtils, VerifyIssuerNameNullCert) {
EXPECT_FALSE(VerifyCrlCertIssuerNamesMatch(intermediate_crl_, nullptr));
}
TEST_F(CrlUtils, VerifyIssuerNameNullCrlAndCert) {
EXPECT_FALSE(VerifyCrlCertIssuerNamesMatch(nullptr, nullptr));
}
TEST_F(CrlUtils, HasCrlSignBitExists) { EXPECT_TRUE(HasCrlSignBit(root_ca_)); }
TEST_F(CrlUtils, HasCrlSignBitMissing) {
EXPECT_FALSE(HasCrlSignBit(leaf_cert_));
}
TEST_F(CrlUtils, HasCrlSignBitNullCert) {
EXPECT_FALSE(HasCrlSignBit(nullptr));
}
TEST_F(CrlUtils, IssuerFromIntermediateCert) {
auto issuer = IssuerFromCert(intermediate_ca_);
// Build the known name for comparison
unsigned char* buf = nullptr;
X509_NAME* expected_issuer_name = X509_NAME_new();
ASSERT_TRUE(
X509_NAME_add_entry_by_txt(expected_issuer_name, "C", MBSTRING_ASC,
(const unsigned char*)"AU", -1, -1, 0));
ASSERT_TRUE(X509_NAME_add_entry_by_txt(
expected_issuer_name, "ST", MBSTRING_ASC,
(const unsigned char*)"Some-State", -1, -1, 0));
ASSERT_TRUE(X509_NAME_add_entry_by_txt(
expected_issuer_name, "O", MBSTRING_ASC,
(const unsigned char*)"Internet Widgits Pty Ltd", -1, -1, 0));
ASSERT_TRUE(
X509_NAME_add_entry_by_txt(expected_issuer_name, "CN", MBSTRING_ASC,
(const unsigned char*)"testca", -1, -1, 0));
int len = i2d_X509_NAME(expected_issuer_name, &buf);
std::string expected_issuer_name_der(reinterpret_cast<char const*>(buf), len);
OPENSSL_free(buf);
X509_NAME_free(expected_issuer_name);
ASSERT_EQ(issuer.status(), absl::OkStatus());
EXPECT_EQ(*issuer, expected_issuer_name_der);
}
TEST_F(CrlUtils, IssuerFromLeaf) {
auto issuer = IssuerFromCert(leaf_cert_);
// Build the known name for comparison
unsigned char* buf = nullptr;
X509_NAME* expected_issuer_name = X509_NAME_new();
ASSERT_TRUE(X509_NAME_add_entry_by_txt(
expected_issuer_name, "CN", MBSTRING_ASC,
(const unsigned char*)"intermediatecert.example.com", -1, -1, 0));
int len = i2d_X509_NAME(expected_issuer_name, &buf);
std::string expected_issuer_name_der(reinterpret_cast<char const*>(buf), len);
OPENSSL_free(buf);
X509_NAME_free(expected_issuer_name);
ASSERT_EQ(issuer.status(), absl::OkStatus());
EXPECT_EQ(*issuer, expected_issuer_name_der);
}
TEST_F(CrlUtils, IssuerFromCertNull) {
auto issuer = IssuerFromCert(nullptr);
EXPECT_EQ(issuer.status().code(), absl::StatusCode::kInvalidArgument);
}
} // namespace testing } // namespace testing
} // namespace grpc_core } // namespace grpc_core

@ -25,4 +25,5 @@ exports_files([
"leaf_and_intermediate_chain.pem", "leaf_and_intermediate_chain.pem",
"intermediate_ca.key", "intermediate_ca.key",
"intermediate_ca.pem", "intermediate_ca.pem",
"evil_ca.pem",
]) ])

@ -46,6 +46,11 @@ Generate a chain with a leaf cert signed by an intermediate CA and revoke the in
Run `intermediate_gen.sh` from the `test/core/tsi/test_creds/crl_data` directory Run `intermediate_gen.sh` from the `test/core/tsi/test_creds/crl_data` directory
Generate a CA with the same issuer name but a different public key than the base CA
----------------------------------------------------------------------------
Run `evil_ca_gen.sh` from the `test/core/tsi/test_creds/crl_data` directory
Clean up: Clean up:
--------- ---------

@ -19,4 +19,6 @@ exports_files([
"b9322cac.r0", "b9322cac.r0",
"current.crl", "current.crl",
"intermediate.crl", "intermediate.crl",
"invalid_signature.crl",
"invalid_content.crl",
]) ])

@ -0,0 +1,15 @@
-----BEGIN X509 CRL-----
AIICUDCCATgCAQEwDQYJKoZIhvcNAQELBQAwVjELMAkGA1UEBhMCQVUxEzARBgNV
BAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0
ZDEPMA0GA1UEAwwGdGVzdGNhFw0yMzAzMDMxODA2NDNaFw0zMzAyMjgxODA2NDNa
MIGcMCUCFEpMyQOrk+uXDu20PhHwDJeua83mFw0yMzAzMDMxNjU5NTNaMCUCFEpM
yQOrk+uXDu20PhHwDJeua83nFw0yMzAzMDMxNzMxNDBaMCUCFEpMyQOrk+uXDu20
PhHwDJeua83xFw0yMzAzMDMxODA2NDNaMCUCFFIgumScY9chZ0u8tUhjsOUh38hB
Fw0yMjAyMDQyMjExMTFaoA8wDTALBgNVHRQEBAICEAgwDQYJKoZIhvcNAQELBQAD
ggEBADohIZwm/gWLIc2yFJJbKzkdRmOq1s/MqnJxi5NutNumXTIPrZJqGzk8O4U6
VasicIB2YD0o3arzUxCDyHv7VyJI7SVS0lqlmOxoOEOv2+CB6MxAOdKItkzbVVxu
0erx5HcKAGa7ZIAeekX1F1DcAgpN5Gt5uGhkMw3ObTCpEFRw+ZKET3WFQ6bG4AJ6
GwOnNYG1LjaNigxG/k4K7A+grs/XnsNcpULbCROl7Qw4kyf1esrjS9utEO0YQQz4
LgBTPZzQHlsirmxp+e5WR8LiDsKmbmAaBL+gV1Bkjj73c4pNJvoV/V1Ubdv0LCvH
DjrJtp10F0RGMRm6m9OuZYUSFzs=
-----END X509 CRL-----

@ -0,0 +1,15 @@
-----BEGIN X509 CRL-----
MIICUDCCATgCAQEwDQYJKoZIhvcNAQELBQAwVjELMAkGA1UEBhMCQVUxEzARBgNV
BAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0
ZDEPMA0GA1UEAwwGdGVzdGNhFw0yMzAzMDMxODA2NDNaFw0zMzAyMjgxODA2NDNa
MIGcMCUCFEpMyQOrk+uXDu20PhHwDJeua83mFw0yMzAzMDMxNjU5NTNaMCUCFEpM
yQOrk+uXDu20PhHwDJeua83nFw0yMzAzMDMxNzMxNDBaMCUCFEpMyQOrk+uXDu20
PhHwDJeua83xFw0yMzAzMDMxODA2NDNaMCUCFFIgumScY9chZ0u8tUhjsOUh38hB
Fw0yMjAyMDQyMjExMTFaoA8wDTALBgNVHRQEBAICEAgwDQYJKoZIhvcNAQELBQAD
ggEBADohIZwm/gWLIc2yFJJbKzkdRmOq1s/MqnJxi5NutNumXTIPrZJqGzk8O4U6
VasicIB2YD0o3arzUxCDyHv7VyJI7SVS0lqlmOxoOEOv2+CB6MxAOdKItkzbVVxu
0erx5HcKAGa7ZIAeekX1F1DcAgpN5Gt5uGhkMw3ObTCpEFRw+ZKET3WFQ6bG4AJ6
GwOnNYG1LjaNigxG/k4K7A+grs/XnsNcpULbCROl7Qw4kyf1esrjS9utEO0YQQz4
LgBTPZzQHlsirmxp+e5WR8LiDsKmbmAaBL+gV1Bkjj73c4pNJvoV/V1Ubdv0LCvH
DjrJtp10F0RGMRm6m9OuZYUSFza=
-----END X509 CRL-----

@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC7RwHo8bWaioeI
oqq4qRkiRfqAl/XlaRCyygkMtkjuOy0LA42+LFXXNvDD8eVvVd3615Qopm0XzABd
iz2QiJBZH9qvvmZFg7vG4rbNMCHIN+0YYIOp5tJuyBUVhZ+/f/jZ+LoJeZgTRngQ
tMUmhs7kn4ttT+DC7ZHKhPf5vUokSPG4N2tBx21y2BzRup36q09vfvZeVEe5YxAM
KGWEOcCY/S5vTVeEJCqP2OfMmskIHq2cYWr6ZJzBpdhJXX6rTDWYlCzX49mzPrn6
povhA/bENv9Gy1OHqPKt+EWEJCaurerkFwF74OG9zp/jCKZJTVkyxnCYjT2rYiDX
gWvNwdeHAgMBAAECggEADyya44Mzj0Y6jXV8tsIA0YLxCrAFZ7q3ydIj9z3ih+cP
PcK3yUPHYCJJUjR3PipWIP03Dy949xd7pMNjpXfjQPgbRz0lWpboxUiDvk7FlfcD
b4O2d12cCbI4Px+uHh1M48B1tnnTOtCYFDvJc6yITARUuZ03cs6UDwrvcB1dygsO
2sZLUOkWQb2DCMq86bxmkHvjuh3gj/CMTJv0Kprlo3YcKNgCwiNygEzlusyIcwpf
dU/SNoWcxY+F0F6wFC0uj75wWqDB6bmfCpY8Bb3Ey7TgWDTWjsB/NQsWbSxZ9o5i
qjQ6WSLKpLLLB/8dXxhk3Nz9tfonavBpLB+4fNpFFQKBgQDi61A3/U88iEo+sxMm
L3i0OS9g/mAnYQ7zYjq42eVyDTfa+eBck1Jmp1KEblfy7Eo3iyApNFoIzFz8va8N
tPNFK/K4mrf1aiFOk0SnvCstW8SBS99hBHXqrMnXrRh+L/OafM4sj88P4RbZxcIs
9RNiDIqcXAPDVU5aHIhs7CFzYwKBgQDTRyOR9PoTQnu0HV0ODDNzmP1eRWrXZ62N
khe9bm0TIG25Q1wsoR6MT5fxZlTe62FH7A5QgEheRtMctr+XGC2H+3N3MUxsTy37
knPFiDl6Gs5DqKroewiDNbkziMOgctG/z6ORPiGghTRsn6y5dBaMstfvgip8fj5z
ytzgSfiujQKBgHZraOSfK++iDGTmHRMraOlcgm4ysck7LIs08wIurD+1yDVde4m0
VCdAIJ792qXqS9zqnPED4gx/YfN/pdAYY2/wvG08SM4pAZK45fZHC51TK5xyFPPT
WRoL7BXCvmpz6cPwZ8P3lI5r3/nr6yZ9Cw17EAcDOe+BIC+EfmmhXN+TAoGBAIp0
oDbSV9+vPen3JDhEfqNOqxvQWgf3haC1EKGvcAOMyNsT7Z/BpodE0cn8ybmcfw/m
/ip7JvHBcC/tAvk9evkWK8D8qZyA9x1aCEx2zVPbpThpnDbmCdoSpt/CzJClLheJ
NyPDl73eDVDyAvs1vGFQAnqOztDu2nZ/huflEfcxAoGAbLUQV5PjqJrsIosEMXsv
qOzQZ5BBEk/jo9zqYSNXWVs0I9Invj5iAYewoM5qn9DFQ3q3O/mPHxF6HT7JHfjn
T8wdOTQk5L1yaaSFsiti3C3AQ2zShT1k6m3V+mf0iWJw878LCURQQFNIHu7zVdXy
4xwQpVw2CN7iufRYN7kOcDo=
-----END PRIVATE KEY-----

@ -0,0 +1,21 @@
-----BEGIN CERTIFICATE-----
MIIDeTCCAmGgAwIBAgIUULA9nt1NB3W1i4RevrKeRQQLkaIwDQYJKoZIhvcNAQEL
BQAwVjELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM
GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEPMA0GA1UEAwwGdGVzdGNhMB4XDTI0
MDEyMjIxNDAyMFoXDTM0MDExOTIxNDAyMFowVjELMAkGA1UEBhMCQVUxEzARBgNV
BAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0
ZDEPMA0GA1UEAwwGdGVzdGNhMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
AQEAu0cB6PG1moqHiKKquKkZIkX6gJf15WkQssoJDLZI7jstCwONvixV1zbww/Hl
b1Xd+teUKKZtF8wAXYs9kIiQWR/ar75mRYO7xuK2zTAhyDftGGCDqebSbsgVFYWf
v3/42fi6CXmYE0Z4ELTFJobO5J+LbU/gwu2RyoT3+b1KJEjxuDdrQcdtctgc0bqd
+qtPb372XlRHuWMQDChlhDnAmP0ub01XhCQqj9jnzJrJCB6tnGFq+mScwaXYSV1+
q0w1mJQs1+PZsz65+qaL4QP2xDb/RstTh6jyrfhFhCQmrq3q5BcBe+Dhvc6f4wim
SU1ZMsZwmI09q2Ig14FrzcHXhwIDAQABoz8wPTAMBgNVHRMEBTADAQH/MA4GA1Ud
DwEB/wQEAwIBBjAdBgNVHQ4EFgQUjcQvfJ6kAUgljgToPpQ0DmCW0Q8wDQYJKoZI
hvcNAQELBQADggEBALLNhOYqlhOcCsTD1SPfm9MAjfpV1EjSjDCpIfwCk5gI2CUX
g7MyUzn2gQJUiYx74BKmjv6W/sLzNxqR0wZQUr4d/7HX+Lm0xCCYdIUELEM8lZ30
maBJ599cQnLXDB1ZFEekj3DMM6jL7OQnBaDs5jW4GcDcuwd5cgXfgIaZVjBVJ11Y
CFAhIuh5CM8xhqxWYWY+h0VLU64s8WCNrBEy1OU5KpQRfpd4cvpoWn7E1SfhK1Iq
Bp+1k4oDBpGGw4NLXI3i1aU8x1+KoXxNRg5dOED0OLgppvaWB2yIpqBlcZDaNpq4
P+WFGBiSUpWU5yYwCDvQAgTWtWkmyflVwslHaGs=
-----END CERTIFICATE-----

@ -0,0 +1,18 @@
#!/bin/bash
# Copyright 2024 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.
# Generates a CA with the same issuer name as the good CA in this directory
openssl req -x509 -new -newkey rsa:2048 -nodes -keyout evil_ca.key -out evil_ca.pem \
-config ca-openssl.cnf -days 3650 -extensions v3_req

@ -62,11 +62,9 @@ cp "./intermediate_ca/intermediate.crl" ./crls
cp current.crl ./crls/ cp current.crl ./crls/
openssl rehash ./crls/ openssl rehash ./crls/
mkdir crls_missing_intermediate
cp current.crl ./crls_missing_intermediate/ cp current.crl ./crls_missing_intermediate/
openssl rehash ./crls_missing_intermediate/ openssl rehash ./crls_missing_intermediate/
mkdir crls_missing_root
cp intermediate.crl ./crls_missing_root/ cp intermediate.crl ./crls_missing_root/
openssl rehash ./crls_missing_root/ openssl rehash ./crls_missing_root/

@ -762,3 +762,27 @@ std::string GenerateSelfSignedCertificate(
BN_free(n); BN_free(n);
return pem; return pem;
} }
X509* ReadPemCert(absl::string_view pem_cert) {
BIO* cert_bio =
BIO_new_mem_buf(pem_cert.data(), static_cast<int>(pem_cert.size()));
// Errors on BIO
if (cert_bio == nullptr) {
return nullptr;
}
X509* cert = PEM_read_bio_X509(cert_bio, nullptr, nullptr, nullptr);
BIO_free(cert_bio);
return cert;
}
X509_CRL* ReadCrl(absl::string_view crl_pem) {
BIO* crl_bio =
BIO_new_mem_buf(crl_pem.data(), static_cast<int>(crl_pem.size()));
// Errors on BIO
if (crl_bio == nullptr) {
return nullptr;
}
X509_CRL* crl = PEM_read_bio_X509_CRL(crl_bio, nullptr, nullptr, nullptr);
BIO_free(crl_bio);
return crl;
}

@ -19,6 +19,8 @@
#ifndef GRPC_TEST_CORE_TSI_TRANSPORT_SECURITY_TEST_LIB_H #ifndef GRPC_TEST_CORE_TSI_TRANSPORT_SECURITY_TEST_LIB_H
#define GRPC_TEST_CORE_TSI_TRANSPORT_SECURITY_TEST_LIB_H #define GRPC_TEST_CORE_TSI_TRANSPORT_SECURITY_TEST_LIB_H
#include <openssl/x509v3.h>
#include <grpc/support/sync.h> #include <grpc/support/sync.h>
#include "src/core/tsi/transport_security_interface.h" #include "src/core/tsi/transport_security_interface.h"
@ -238,4 +240,10 @@ struct SelfSignedCertificateOptions {
std::string GenerateSelfSignedCertificate( std::string GenerateSelfSignedCertificate(
const SelfSignedCertificateOptions& options); const SelfSignedCertificateOptions& options);
// Returns the OpenSSL representation of a PEM cert.
X509* ReadPemCert(absl::string_view pem_cert);
// Returns the OpenSSL representation of a CRL.
X509_CRL* ReadCrl(absl::string_view crl_pem);
#endif // GRPC_TEST_CORE_TSI_TRANSPORT_SECURITY_TEST_LIB_H #endif // GRPC_TEST_CORE_TSI_TRANSPORT_SECURITY_TEST_LIB_H

@ -63,7 +63,6 @@ grpc_cc_library(
"histogram.cc", "histogram.cc",
"mock_endpoint.cc", "mock_endpoint.cc",
"parse_hexstring.cc", "parse_hexstring.cc",
"passthru_endpoint.cc",
"resolve_localhost_ip46.cc", "resolve_localhost_ip46.cc",
"slice_splitter.cc", "slice_splitter.cc",
"tracer_util.cc", "tracer_util.cc",
@ -77,7 +76,6 @@ grpc_cc_library(
"mock_authorization_endpoint.h", "mock_authorization_endpoint.h",
"mock_endpoint.h", "mock_endpoint.h",
"parse_hexstring.h", "parse_hexstring.h",
"passthru_endpoint.h",
"resolve_localhost_ip46.h", "resolve_localhost_ip46.h",
"slice_splitter.h", "slice_splitter.h",
"tracer_util.h", "tracer_util.h",

@ -1,525 +0,0 @@
//
//
// Copyright 2016 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/core/util/passthru_endpoint.h"
#include <string.h>
#include <algorithm>
#include <functional>
#include <memory>
#include <string>
#include "absl/status/status.h"
#include "absl/strings/str_format.h"
#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
#include <grpc/event_engine/event_engine.h>
#include <grpc/slice.h>
#include <grpc/slice_buffer.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include "src/core/lib/event_engine/default_event_engine.h"
#include "src/core/lib/gprpp/debug_location.h"
#include "src/core/lib/gprpp/time.h"
#include "src/core/lib/iomgr/closure.h"
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/iomgr/exec_ctx.h"
#include "src/core/lib/iomgr/iomgr_fwd.h"
using ::grpc_event_engine::experimental::EventEngine;
using ::grpc_event_engine::experimental::GetDefaultEventEngine;
typedef struct passthru_endpoint passthru_endpoint;
typedef struct {
bool is_armed;
grpc_endpoint* ep;
grpc_slice_buffer* slices;
grpc_closure* cb;
} pending_op;
typedef struct {
absl::optional<EventEngine::TaskHandle> timer_handle;
uint64_t allowed_write_bytes;
uint64_t allowed_read_bytes;
std::vector<grpc_passthru_endpoint_channel_action> actions;
std::function<void()> on_complete;
} grpc_passthru_endpoint_channel_effects;
typedef struct {
grpc_endpoint base;
passthru_endpoint* parent;
grpc_slice_buffer read_buffer;
grpc_slice_buffer write_buffer;
grpc_slice_buffer* on_read_out;
grpc_closure* on_read;
pending_op pending_read_op;
pending_op pending_write_op;
uint64_t bytes_read_so_far;
uint64_t bytes_written_so_far;
} half;
struct passthru_endpoint {
gpr_mu mu;
int halves;
grpc_passthru_endpoint_stats* stats;
grpc_passthru_endpoint_channel_effects* channel_effects;
bool simulate_channel_actions;
bool shutdown;
half client;
half server;
};
static void do_pending_read_op_locked(half* m, grpc_error_handle error) {
GPR_ASSERT(m->pending_read_op.is_armed);
GPR_ASSERT(m->bytes_read_so_far <=
m->parent->channel_effects->allowed_read_bytes);
if (m->parent->shutdown) {
grpc_core::ExecCtx::Run(DEBUG_LOCATION, m->pending_read_op.cb,
GRPC_ERROR_CREATE("Already shutdown"));
// Move any pending data into pending_read_op.slices so that it may be
// free'ed by the executing callback.
grpc_slice_buffer_move_into(&m->read_buffer, m->pending_read_op.slices);
m->pending_read_op.is_armed = false;
return;
}
if (m->bytes_read_so_far == m->parent->channel_effects->allowed_read_bytes) {
// Keep it in pending state.
return;
}
// This delayed processing should only be invoked when read_buffer has
// something in it.
GPR_ASSERT(m->read_buffer.count > 0);
uint64_t readable_length = std::min<uint64_t>(
m->read_buffer.length,
m->parent->channel_effects->allowed_read_bytes - m->bytes_read_so_far);
GPR_ASSERT(readable_length > 0);
grpc_slice_buffer_move_first(&m->read_buffer, readable_length,
m->pending_read_op.slices);
grpc_core::ExecCtx::Run(DEBUG_LOCATION, m->pending_read_op.cb, error);
if (m->parent->simulate_channel_actions) {
m->bytes_read_so_far += readable_length;
}
m->pending_read_op.is_armed = false;
}
static void me_read(grpc_endpoint* ep, grpc_slice_buffer* slices,
grpc_closure* cb, bool /*urgent*/,
int /*min_progress_size*/) {
half* m = reinterpret_cast<half*>(ep);
gpr_mu_lock(&m->parent->mu);
if (m->parent->shutdown) {
grpc_core::ExecCtx::Run(DEBUG_LOCATION, cb,
GRPC_ERROR_CREATE("Already shutdown"));
} else if (m->read_buffer.count > 0) {
GPR_ASSERT(!m->pending_read_op.is_armed);
GPR_ASSERT(!m->on_read);
m->pending_read_op.is_armed = true;
m->pending_read_op.cb = cb;
m->pending_read_op.ep = ep;
m->pending_read_op.slices = slices;
do_pending_read_op_locked(m, absl::OkStatus());
} else {
GPR_ASSERT(!m->pending_read_op.is_armed);
m->on_read = cb;
m->on_read_out = slices;
}
gpr_mu_unlock(&m->parent->mu);
}
// Copy src slice and split the copy at n bytes into two separate slices
void grpc_slice_copy_split(grpc_slice src, uint64_t n, grpc_slice& split1,
grpc_slice& split2) {
GPR_ASSERT(n <= GRPC_SLICE_LENGTH(src));
if (n == GRPC_SLICE_LENGTH(src)) {
split1 = grpc_slice_copy(src);
split2 = grpc_empty_slice();
return;
}
split1 = GRPC_SLICE_MALLOC(n);
memcpy(GRPC_SLICE_START_PTR(split1), GRPC_SLICE_START_PTR(src), n);
split2 = GRPC_SLICE_MALLOC(GRPC_SLICE_LENGTH(src) - n);
memcpy(GRPC_SLICE_START_PTR(split2), GRPC_SLICE_START_PTR(src) + n,
GRPC_SLICE_LENGTH(src) - n);
}
static half* other_half(half* h) {
if (h == &h->parent->client) return &h->parent->server;
return &h->parent->client;
}
static void do_pending_write_op_locked(half* m, grpc_error_handle error) {
GPR_ASSERT(m->pending_write_op.is_armed);
GPR_ASSERT(m->bytes_written_so_far <=
m->parent->channel_effects->allowed_write_bytes);
if (m->parent->shutdown) {
grpc_core::ExecCtx::Run(DEBUG_LOCATION, m->pending_write_op.cb,
GRPC_ERROR_CREATE("Already shutdown"));
m->pending_write_op.is_armed = false;
grpc_slice_buffer_reset_and_unref(m->pending_write_op.slices);
return;
}
if (m->bytes_written_so_far ==
m->parent->channel_effects->allowed_write_bytes) {
// Keep it in pending state.
return;
}
half* other = other_half(m);
uint64_t max_writable =
std::min<uint64_t>(m->pending_write_op.slices->length,
m->parent->channel_effects->allowed_write_bytes -
m->bytes_written_so_far);
uint64_t max_readable = other->parent->channel_effects->allowed_read_bytes -
other->bytes_read_so_far;
uint64_t immediate_bytes_read =
other->on_read != nullptr ? std::min<uint64_t>(max_readable, max_writable)
: 0;
GPR_ASSERT(max_writable > 0);
GPR_ASSERT(max_readable >= 0);
// At the end of this process, we should have written max_writable bytes;
if (m->parent->simulate_channel_actions) {
m->bytes_written_so_far += max_writable;
}
// Estimate if the original write would still be pending at the end of this
// process
bool would_write_be_pending =
max_writable < m->pending_write_op.slices->length;
if (!m->parent->simulate_channel_actions) {
GPR_ASSERT(!would_write_be_pending);
}
grpc_slice_buffer* slices = m->pending_write_op.slices;
grpc_slice_buffer* dest =
other->on_read != nullptr ? other->on_read_out : &other->read_buffer;
while (max_writable > 0) {
grpc_slice slice = grpc_slice_buffer_take_first(slices);
uint64_t slice_length = GRPC_SLICE_LENGTH(slice);
GPR_ASSERT(slice_length > 0);
grpc_slice split1, split2;
uint64_t split_length = 0;
if (slice_length <= max_readable) {
split_length = std::min<uint64_t>(slice_length, max_writable);
} else if (max_readable > 0) {
// slice_length > max_readable
split_length = std::min<uint64_t>(max_readable, max_writable);
} else {
// slice_length still > max_readable but max_readable is 0.
// In this case put the bytes into other->read_buffer. During a future
// read if max_readable still remains zero at the time of read, the
// pending read logic will kick in.
dest = &other->read_buffer;
split_length = std::min<uint64_t>(slice_length, max_writable);
}
grpc_slice_copy_split(slice, split_length, split1, split2);
grpc_slice_unref(slice);
// Write a copy of the slice to the destination to be read
grpc_slice_buffer_add_indexed(dest, split1);
// Re-insert split2 into source for next iteration.
if (GRPC_SLICE_LENGTH(split2) > 0) {
grpc_slice_buffer_undo_take_first(slices, split2);
} else {
grpc_slice_unref(split2);
}
if (max_readable > 0) {
GPR_ASSERT(max_readable >= static_cast<uint64_t>(split_length));
max_readable -= split_length;
}
GPR_ASSERT(max_writable >= static_cast<uint64_t>(split_length));
max_writable -= split_length;
}
if (immediate_bytes_read > 0) {
GPR_ASSERT(!other->pending_read_op.is_armed);
if (m->parent->simulate_channel_actions) {
other->bytes_read_so_far += immediate_bytes_read;
}
grpc_core::ExecCtx::Run(DEBUG_LOCATION, other->on_read, error);
other->on_read = nullptr;
}
if (!would_write_be_pending) {
// No slices should be left
GPR_ASSERT(m->pending_write_op.slices->count == 0);
grpc_slice_buffer_reset_and_unref(m->pending_write_op.slices);
m->pending_write_op.is_armed = false;
grpc_core::ExecCtx::Run(DEBUG_LOCATION, m->pending_write_op.cb, error);
}
}
static void me_write(grpc_endpoint* ep, grpc_slice_buffer* slices,
grpc_closure* cb, void* /*arg*/, int /*max_frame_size*/) {
half* m = reinterpret_cast<half*>(ep);
gpr_mu_lock(&m->parent->mu);
gpr_atm_full_fetch_add(&m->parent->stats->num_writes, (gpr_atm)1);
if (m->parent->shutdown) {
grpc_core::ExecCtx::Run(DEBUG_LOCATION, cb,
GRPC_ERROR_CREATE("Endpoint already shutdown"));
} else {
GPR_ASSERT(!m->pending_write_op.is_armed);
// Copy slices into m->pending_write_op.slices
m->pending_write_op.slices = &m->write_buffer;
GPR_ASSERT(m->pending_write_op.slices->count == 0);
for (int i = 0; i < static_cast<int>(slices->count); i++) {
if (GRPC_SLICE_LENGTH(slices->slices[i]) > 0) {
grpc_slice_buffer_add_indexed(m->pending_write_op.slices,
grpc_slice_copy(slices->slices[i]));
}
}
if (m->pending_write_op.slices->count > 0) {
m->pending_write_op.is_armed = true;
m->pending_write_op.cb = cb;
m->pending_write_op.ep = ep;
do_pending_write_op_locked(m, absl::OkStatus());
} else {
// There is nothing to write. Schedule callback to be run right away.
grpc_core::ExecCtx::Run(DEBUG_LOCATION, cb, absl::OkStatus());
}
}
gpr_mu_unlock(&m->parent->mu);
}
void flush_pending_ops_locked(half* m, grpc_error_handle error) {
if (m->pending_read_op.is_armed) {
do_pending_read_op_locked(m, error);
}
if (m->pending_write_op.is_armed) {
do_pending_write_op_locked(m, error);
}
}
static void me_add_to_pollset(grpc_endpoint* /*ep*/,
grpc_pollset* /*pollset*/) {}
static void me_add_to_pollset_set(grpc_endpoint* /*ep*/,
grpc_pollset_set* /*pollset*/) {}
static void me_delete_from_pollset_set(grpc_endpoint* /*ep*/,
grpc_pollset_set* /*pollset*/) {}
static void shutdown_locked(half* m, grpc_error_handle why) {
m->parent->shutdown = true;
flush_pending_ops_locked(m, absl::OkStatus());
if (m->on_read) {
grpc_core::ExecCtx::Run(DEBUG_LOCATION, m->on_read,
GRPC_ERROR_CREATE_REFERENCING("Shutdown", &why, 1));
m->on_read = nullptr;
}
m = other_half(m);
flush_pending_ops_locked(m, absl::OkStatus());
if (m->on_read) {
grpc_core::ExecCtx::Run(DEBUG_LOCATION, m->on_read,
GRPC_ERROR_CREATE_REFERENCING("Shutdown", &why, 1));
m->on_read = nullptr;
}
}
static void me_shutdown(grpc_endpoint* ep, grpc_error_handle why) {
half* m = reinterpret_cast<half*>(ep);
gpr_mu_lock(&m->parent->mu);
shutdown_locked(m, why);
gpr_mu_unlock(&m->parent->mu);
}
void grpc_passthru_endpoint_destroy(passthru_endpoint* p) {
gpr_mu_destroy(&p->mu);
grpc_passthru_endpoint_stats_destroy(p->stats);
delete p->channel_effects;
grpc_slice_buffer_destroy(&p->client.read_buffer);
grpc_slice_buffer_destroy(&p->server.read_buffer);
grpc_slice_buffer_destroy(&p->client.write_buffer);
grpc_slice_buffer_destroy(&p->server.write_buffer);
gpr_free(p);
}
static void do_next_sched_channel_action(void* arg, grpc_error_handle error);
static void me_destroy(grpc_endpoint* ep) {
passthru_endpoint* p = (reinterpret_cast<half*>(ep))->parent;
gpr_mu_lock(&p->mu);
if (0 == --p->halves && p->channel_effects->actions.empty()) {
// no pending channel actions exist
gpr_mu_unlock(&p->mu);
grpc_passthru_endpoint_destroy(p);
} else {
if (p->halves == 0 && p->simulate_channel_actions) {
if (p->channel_effects->timer_handle.has_value()) {
if (GetDefaultEventEngine()->Cancel(
*p->channel_effects->timer_handle)) {
gpr_mu_unlock(&p->mu);
// This will destroy the passthru endpoint so just return after that.
do_next_sched_channel_action(ep, absl::CancelledError());
return;
}
p->channel_effects->timer_handle.reset();
}
}
gpr_mu_unlock(&p->mu);
}
}
static absl::string_view me_get_peer(grpc_endpoint* ep) {
passthru_endpoint* p = (reinterpret_cast<half*>(ep))->parent;
return (reinterpret_cast<half*>(ep)) == &p->client
? "fake:mock_client_endpoint"
: "fake:mock_server_endpoint";
}
static absl::string_view me_get_local_address(grpc_endpoint* ep) {
passthru_endpoint* p = (reinterpret_cast<half*>(ep))->parent;
return (reinterpret_cast<half*>(ep)) == &p->client
? "fake:mock_client_endpoint"
: "fake:mock_server_endpoint";
}
static int me_get_fd(grpc_endpoint* /*ep*/) { return -1; }
static bool me_can_track_err(grpc_endpoint* /*ep*/) { return false; }
static const grpc_endpoint_vtable vtable = {
me_read,
me_write,
me_add_to_pollset,
me_add_to_pollset_set,
me_delete_from_pollset_set,
me_shutdown,
me_destroy,
me_get_peer,
me_get_local_address,
me_get_fd,
me_can_track_err,
};
static void half_init(half* m, passthru_endpoint* parent,
const char* half_name) {
m->base.vtable = &vtable;
m->parent = parent;
grpc_slice_buffer_init(&m->read_buffer);
grpc_slice_buffer_init(&m->write_buffer);
m->pending_write_op.slices = nullptr;
m->on_read = nullptr;
m->bytes_read_so_far = 0;
m->bytes_written_so_far = 0;
m->pending_write_op.is_armed = false;
m->pending_read_op.is_armed = false;
std::string name =
absl::StrFormat("passthru_endpoint_%s_%p", half_name, parent);
}
void grpc_passthru_endpoint_create(grpc_endpoint** client,
grpc_endpoint** server,
grpc_passthru_endpoint_stats* stats,
bool simulate_channel_actions) {
passthru_endpoint* m =
static_cast<passthru_endpoint*>(gpr_malloc(sizeof(*m)));
m->halves = 2;
m->shutdown = false;
if (stats == nullptr) {
m->stats = grpc_passthru_endpoint_stats_create();
} else {
gpr_ref(&stats->refs);
m->stats = stats;
}
m->channel_effects = new grpc_passthru_endpoint_channel_effects();
m->simulate_channel_actions = simulate_channel_actions;
if (!simulate_channel_actions) {
m->channel_effects->allowed_read_bytes = UINT64_MAX;
m->channel_effects->allowed_write_bytes = UINT64_MAX;
}
half_init(&m->client, m, "client");
half_init(&m->server, m, "server");
gpr_mu_init(&m->mu);
*client = &m->client.base;
*server = &m->server.base;
}
grpc_passthru_endpoint_stats* grpc_passthru_endpoint_stats_create() {
grpc_passthru_endpoint_stats* stats =
static_cast<grpc_passthru_endpoint_stats*>(
gpr_malloc(sizeof(grpc_passthru_endpoint_stats)));
memset(stats, 0, sizeof(*stats));
gpr_ref_init(&stats->refs, 1);
return stats;
}
void grpc_passthru_endpoint_stats_destroy(grpc_passthru_endpoint_stats* stats) {
if (gpr_unref(&stats->refs)) {
gpr_free(stats);
}
}
static void sched_next_channel_action_locked(half* m);
static void do_next_sched_channel_action(void* arg, grpc_error_handle error) {
half* m = reinterpret_cast<half*>(arg);
gpr_mu_lock(&m->parent->mu);
GPR_ASSERT(!m->parent->channel_effects->actions.empty());
if (m->parent->halves == 0) {
gpr_mu_unlock(&m->parent->mu);
grpc_passthru_endpoint_destroy(m->parent);
return;
}
auto curr_action = m->parent->channel_effects->actions[0];
m->parent->channel_effects->actions.erase(
m->parent->channel_effects->actions.begin());
m->parent->channel_effects->allowed_read_bytes +=
curr_action.add_n_readable_bytes;
m->parent->channel_effects->allowed_write_bytes +=
curr_action.add_n_writable_bytes;
flush_pending_ops_locked(m, error);
flush_pending_ops_locked(other_half(m), error);
sched_next_channel_action_locked(m);
gpr_mu_unlock(&m->parent->mu);
}
static void sched_next_channel_action_locked(half* m) {
if (m->parent->channel_effects->actions.empty()) {
grpc_error_handle err = GRPC_ERROR_CREATE("Channel actions complete");
shutdown_locked(m, err);
return;
}
m->parent->channel_effects->timer_handle = GetDefaultEventEngine()->RunAfter(
grpc_core::Duration::Milliseconds(
m->parent->channel_effects->actions[0].wait_ms),
[m] {
grpc_core::ApplicationCallbackExecCtx callback_exec_ctx;
grpc_core::ExecCtx exec_ctx;
do_next_sched_channel_action(m, absl::OkStatus());
});
}
void start_scheduling_grpc_passthru_endpoint_channel_effects(
grpc_endpoint* ep,
const std::vector<grpc_passthru_endpoint_channel_action>& actions) {
half* m = reinterpret_cast<half*>(ep);
gpr_mu_lock(&m->parent->mu);
if (!m->parent->simulate_channel_actions || m->parent->shutdown) {
gpr_mu_unlock(&m->parent->mu);
return;
}
m->parent->channel_effects->actions = actions;
sched_next_channel_action_locked(m);
gpr_mu_unlock(&m->parent->mu);
}

@ -1,58 +0,0 @@
//
//
// Copyright 2016 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_TEST_CORE_UTIL_PASSTHRU_ENDPOINT_H
#define GRPC_TEST_CORE_UTIL_PASSTHRU_ENDPOINT_H
#include <stdint.h>
#include <vector>
#include <grpc/support/atm.h>
#include <grpc/support/sync.h>
#include "src/core/lib/iomgr/endpoint.h"
// The struct is refcounted, always use grpc_passthru_endpoint_stats_create and
// grpc_passthru_endpoint_stats_destroy, rather then embedding it in your
// objects by value.
typedef struct {
gpr_refcount refs;
gpr_atm num_writes;
} grpc_passthru_endpoint_stats;
typedef struct {
uint64_t wait_ms;
uint64_t add_n_writable_bytes;
uint64_t add_n_readable_bytes;
} grpc_passthru_endpoint_channel_action;
void grpc_passthru_endpoint_create(grpc_endpoint** client,
grpc_endpoint** server,
grpc_passthru_endpoint_stats* stats,
bool simulate_channel_actions = false);
grpc_passthru_endpoint_stats* grpc_passthru_endpoint_stats_create();
void grpc_passthru_endpoint_stats_destroy(grpc_passthru_endpoint_stats* stats);
void start_scheduling_grpc_passthru_endpoint_channel_effects(
grpc_endpoint* ep,
const std::vector<grpc_passthru_endpoint_channel_action>& actions);
#endif // GRPC_TEST_CORE_UTIL_PASSTHRU_ENDPOINT_H

@ -13,8 +13,10 @@
// limitations under the License. // limitations under the License.
// //
#include <algorithm>
#include <memory> #include <memory>
#include <string> #include <string>
#include <type_traits>
#include <vector> #include <vector>
#include <gmock/gmock.h> #include <gmock/gmock.h>
@ -24,9 +26,11 @@
#include "src/core/client_channel/backup_poller.h" #include "src/core/client_channel/backup_poller.h"
#include "src/core/lib/config/config_vars.h" #include "src/core/lib/config/config_vars.h"
#include "src/proto/grpc/testing/xds/v3/listener.pb.h"
#include "test/core/util/resolve_localhost_ip46.h" #include "test/core/util/resolve_localhost_ip46.h"
#include "test/core/util/scoped_env_var.h" #include "test/core/util/scoped_env_var.h"
#include "test/cpp/end2end/xds/xds_end2end_test_lib.h" #include "test/cpp/end2end/xds/xds_end2end_test_lib.h"
#include "test/cpp/end2end/xds/xds_server.h"
namespace grpc { namespace grpc {
namespace testing { namespace testing {
@ -167,7 +171,21 @@ INSTANTIATE_TEST_SUITE_P(XdsTest, GlobalXdsClientTest,
XdsTestType::kBootstrapFromEnvVar)), XdsTestType::kBootstrapFromEnvVar)),
&XdsTestType::Name); &XdsTestType::Name);
TEST_P(GlobalXdsClientTest, MultipleChannelsShareXdsClient) { TEST_P(GlobalXdsClientTest, MultipleChannelsSameTargetShareXdsClient) {
CreateAndStartBackends(1);
EdsResourceArgs args({{"locality0", CreateEndpointsForBackends()}});
balancer_->ads_service()->SetEdsResource(BuildEdsResource(args));
WaitForAllBackends(DEBUG_LOCATION);
// Create second channel and tell it to connect to the same server.
auto channel2 = CreateChannel(/*failover_timeout_ms=*/0, kServerName);
channel2->GetState(/*try_to_connect=*/true);
ASSERT_TRUE(channel2->WaitForConnected(grpc_timeout_seconds_to_deadline(1)));
// Make sure there's only one client connected.
EXPECT_EQ(1UL, balancer_->ads_service()->clients().size());
}
TEST_P(GlobalXdsClientTest,
MultipleChannelsDifferentTargetDoNotShareXdsClient) {
CreateAndStartBackends(1); CreateAndStartBackends(1);
const char* kNewServerName = "new-server.example.com"; const char* kNewServerName = "new-server.example.com";
Listener listener = default_listener_; Listener listener = default_listener_;
@ -181,8 +199,8 @@ TEST_P(GlobalXdsClientTest, MultipleChannelsShareXdsClient) {
auto channel2 = CreateChannel(/*failover_timeout_ms=*/0, kNewServerName); auto channel2 = CreateChannel(/*failover_timeout_ms=*/0, kNewServerName);
channel2->GetState(/*try_to_connect=*/true); channel2->GetState(/*try_to_connect=*/true);
ASSERT_TRUE(channel2->WaitForConnected(grpc_timeout_seconds_to_deadline(1))); ASSERT_TRUE(channel2->WaitForConnected(grpc_timeout_seconds_to_deadline(1)));
// Make sure there's only one client connected. // Make sure there are two clients connected.
EXPECT_EQ(1UL, balancer_->ads_service()->clients().size()); EXPECT_EQ(2UL, balancer_->ads_service()->clients().size());
} }
TEST_P( TEST_P(
@ -219,64 +237,62 @@ TEST_P(
} }
// Tests that the NACK for multiple bad LDS resources includes both errors. // Tests that the NACK for multiple bad LDS resources includes both errors.
// This needs to be in GlobalXdsClientTest because the only way to request // This needs to use xDS server as this is the only scenario when XdsClient
// two LDS resources in the same XdsClient is for two channels to share // is shared.
// the same XdsClient.
TEST_P(GlobalXdsClientTest, MultipleBadLdsResources) { TEST_P(GlobalXdsClientTest, MultipleBadLdsResources) {
CreateAndStartBackends(1); CreateBackends(2, true);
constexpr char kServerName2[] = "server.other.com"; EdsResourceArgs args({{"locality0", CreateEndpointsForBackends(0, 2)}});
constexpr char kServerName3[] = "server.another.com";
auto listener = default_listener_;
listener.clear_api_listener();
balancer_->ads_service()->SetLdsResource(listener);
listener.set_name(kServerName2);
balancer_->ads_service()->SetLdsResource(listener);
listener = default_listener_;
listener.set_name(kServerName3);
SetListenerAndRouteConfiguration(balancer_.get(), listener,
default_route_config_);
EdsResourceArgs args({{"locality0", CreateEndpointsForBackends()}});
balancer_->ads_service()->SetEdsResource(BuildEdsResource(args)); balancer_->ads_service()->SetEdsResource(BuildEdsResource(args));
const auto response_state = WaitForLdsNack(DEBUG_LOCATION); auto listener = default_server_listener_;
listener.clear_address();
listener.set_name(GetServerListenerName(backends_[0]->port()));
balancer_->ads_service()->SetLdsResource(listener);
backends_[0]->Start();
auto response_state = WaitForLdsNack(DEBUG_LOCATION);
ASSERT_TRUE(response_state.has_value()) << "timed out waiting for NACK"; ASSERT_TRUE(response_state.has_value()) << "timed out waiting for NACK";
EXPECT_EQ(response_state->error_message, EXPECT_EQ(
"xDS response validation errors: [" response_state->error_message,
"resource index 0: server.example.com: " absl::StrFormat(
"INVALID_ARGUMENT: Listener has neither address nor ApiListener]"); "xDS response validation errors: ["
// Need to create a second channel to subscribe to a second LDS resource. "resource index 0: "
auto channel2 = CreateChannel(0, kServerName2); "grpc/server?xds.resource.listening_address=127.0.0.1:%lu: "
auto stub2 = grpc::testing::EchoTestService::NewStub(channel2); "INVALID_ARGUMENT: Listener has neither address nor ApiListener]",
{ backends_[0]->port()));
ClientContext context; listener = default_server_listener_;
EchoRequest request; listener.clear_address();
request.set_message(kRequestMessage); listener.set_name(GetServerListenerName(backends_[1]->port()));
EchoResponse response; balancer_->ads_service()->SetLdsResource(listener);
grpc::Status status = stub2->Echo(&context, request, &response); backends_[1]->Start();
EXPECT_FALSE(status.ok()); constexpr absl::string_view kMessageFormat =
// Wait for second NACK to be reported to xDS server. "xDS response validation errors: ["
const auto response_state = WaitForLdsNack(DEBUG_LOCATION); "resource index 0: "
ASSERT_TRUE(response_state.has_value()) << "timed out waiting for NACK"; "grpc/server?xds.resource.listening_address=127.0.0.1:%d: "
EXPECT_EQ( "INVALID_ARGUMENT: Listener has neither address nor "
response_state->error_message, "ApiListener; "
"xDS response validation errors: [" "resource index 1: "
"resource index 0: server.other.com: " "grpc/server?xds.resource.listening_address=127.0.0.1:%d: "
"INVALID_ARGUMENT: Listener has neither address nor ApiListener; " "INVALID_ARGUMENT: Listener has neither address nor "
"resource index 1: server.example.com: " "ApiListener"
"INVALID_ARGUMENT: Listener has neither address nor ApiListener]"); "]";
} const std::string expected_message1 = absl::StrFormat(
// Now start a new channel with a third server name, this one with a kMessageFormat, backends_[0]->port(), backends_[1]->port());
// valid resource. const std::string expected_message2 = absl::StrFormat(
auto channel3 = CreateChannel(0, kServerName3); kMessageFormat, backends_[1]->port(), backends_[0]->port());
auto stub3 = grpc::testing::EchoTestService::NewStub(channel3); response_state = WaitForNack(
{ DEBUG_LOCATION, [&]() -> absl::optional<AdsServiceImpl::ResponseState> {
ClientContext context; auto response = balancer_->ads_service()->lds_response_state();
EchoRequest request; if (response.has_value() &&
request.set_message(kRequestMessage); response->state == AdsServiceImpl::ResponseState::NACKED) {
EchoResponse response; if (response->error_message == expected_message1 ||
grpc::Status status = stub3->Echo(&context, request, &response); response->error_message == expected_message2) {
EXPECT_TRUE(status.ok()) << "code=" << status.error_code() return response;
<< " message=" << status.error_message(); }
} gpr_log(GPR_INFO, "non-matching NACK message: %s",
response->error_message.c_str());
}
return absl::nullopt;
});
EXPECT_TRUE(response_state.has_value()) << "timed out waiting for NACK";
} }
// Tests that we don't trigger does-not-exist callbacks for a resource // Tests that we don't trigger does-not-exist callbacks for a resource

@ -22,6 +22,7 @@
#include "absl/memory/memory.h" #include "absl/memory/memory.h"
#include "absl/strings/str_cat.h" #include "absl/strings/str_cat.h"
#include "absl/strings/strip.h"
#include <grpcpp/create_channel.h> #include <grpcpp/create_channel.h>
#include <grpcpp/security/credentials.h> #include <grpcpp/security/credentials.h>
@ -344,7 +345,7 @@ TEST_P(ClientStatusDiscoveryServiceTest, XdsConfigDumpVanilla) {
// Fetches the client config // Fetches the client config
auto csds_response = FetchCsdsResponse(); auto csds_response = FetchCsdsResponse();
gpr_log(GPR_INFO, "xDS config dump: %s", csds_response.DebugString().c_str()); gpr_log(GPR_INFO, "xDS config dump: %s", csds_response.DebugString().c_str());
EXPECT_EQ(1, csds_response.config_size()); ASSERT_EQ(1, csds_response.config_size());
const auto& client_config = csds_response.config(0); const auto& client_config = csds_response.config(0);
// Validate the Node information // Validate the Node information
EXPECT_THAT(client_config.node(), EXPECT_THAT(client_config.node(),
@ -615,6 +616,82 @@ TEST_P(ClientStatusDiscoveryServiceTest, XdsConfigDumpClusterRequested) {
ClientResourceStatus::REQUESTED, ::testing::_)))); ClientResourceStatus::REQUESTED, ::testing::_))));
} }
TEST_P(ClientStatusDiscoveryServiceTest, XdsConfigDumpMultiClient) {
Listener listener = default_listener_;
const char* kServer2Name = "server2.example.com";
listener.set_name(kServer2Name);
balancer_->ads_service()->SetLdsResource(listener);
SetListenerAndRouteConfiguration(balancer_.get(), listener,
default_route_config_);
CreateAndStartBackends(1);
const size_t kNumRpcs = 5;
EdsResourceArgs args({{"locality0", CreateEndpointsForBackends(0, 1)}});
balancer_->ads_service()->SetEdsResource(BuildEdsResource(args));
// Send several RPCs to ensure the xDS setup works
CheckRpcSendOk(DEBUG_LOCATION, kNumRpcs);
// Connect to a second server
auto channel2 = CreateChannel(0, kServer2Name);
channel2->GetState(/*try_to_connect=*/true);
ASSERT_TRUE(channel2->WaitForConnected(grpc_timeout_seconds_to_deadline(1)));
// Fetches the client config
auto csds_response = FetchCsdsResponse();
ASSERT_EQ(2, csds_response.config_size());
std::vector<std::string> scopes;
for (const auto& client_config : csds_response.config()) {
// Validate the Node information
EXPECT_THAT(client_config.node(),
EqNode("xds_end2end_test", ::testing::HasSubstr("C-core"),
::testing::HasSubstr(grpc_version_string()),
::testing::ElementsAre(
"envoy.lb.does_not_support_overprovisioning")));
scopes.emplace_back(client_config.client_scope());
absl::string_view server = client_config.client_scope();
// Listener matcher depends on whether RDS is enabled.
::testing::Matcher<google::protobuf::Any> api_listener_matcher;
if (GetParam().enable_rds_testing()) {
api_listener_matcher = IsRdsEnabledHCM();
} else {
api_listener_matcher =
EqNoRdsHCM(kDefaultRouteConfigurationName, kDefaultClusterName);
}
// Construct list of all matchers.
std::vector<::testing::Matcher<
envoy::service::status::v3::ClientConfig_GenericXdsConfig>>
matchers = {
// Listener
EqGenericXdsConfig(
kLdsTypeUrl, absl::StripPrefix(server, "xds:"), "3",
UnpackListener(EqListener(absl::StripPrefix(server, "xds:"),
api_listener_matcher)),
ClientResourceStatus::ACKED, ::testing::_),
// Cluster
EqGenericXdsConfig(kCdsTypeUrl, kDefaultClusterName, "1",
UnpackCluster(EqCluster(kDefaultClusterName)),
ClientResourceStatus::ACKED, ::testing::_),
// ClusterLoadAssignment
EqGenericXdsConfig(
kEdsTypeUrl, kDefaultEdsServiceName, "1",
UnpackClusterLoadAssignment(EqClusterLoadAssignment(
kDefaultEdsServiceName, backends_[0]->port(),
kDefaultLocalityWeight)),
ClientResourceStatus::ACKED, ::testing::_),
};
// If RDS is enabled, add matcher for RDS resource.
if (GetParam().enable_rds_testing()) {
matchers.push_back(EqGenericXdsConfig(
kRdsTypeUrl, kDefaultRouteConfigurationName, "2",
UnpackRouteConfiguration(EqRouteConfiguration(
kDefaultRouteConfigurationName, kDefaultClusterName)),
ClientResourceStatus::ACKED, ::testing::_));
}
// Validate the dumped xDS configs
EXPECT_THAT(client_config.generic_xds_configs(),
::testing::UnorderedElementsAreArray(matchers));
}
EXPECT_THAT(scopes, ::testing::UnorderedElementsAre(
"xds:server.example.com", "xds:server2.example.com"));
}
class CsdsShortAdsTimeoutTest : public ClientStatusDiscoveryServiceTest { class CsdsShortAdsTimeoutTest : public ClientStatusDiscoveryServiceTest {
protected: protected:
void SetUp() override { void SetUp() override {

@ -523,7 +523,7 @@ void XdsEnd2endTest::InitClient(XdsBootstrapBuilder builder,
// because it's not expecting the client to connect. It also // because it's not expecting the client to connect. It also
// ensures that each test can independently set the global channel // ensures that each test can independently set the global channel
// args for the xDS channel. // args for the xDS channel.
grpc_core::internal::UnsetGlobalXdsClientForTest(); grpc_core::internal::UnsetGlobalXdsClientsForTest();
} }
// Create channel and stub. // Create channel and stub.
ResetStub(); ResetStub();
@ -558,7 +558,14 @@ std::shared_ptr<Channel> XdsEnd2endTest::CreateChannel(
GRPC_ARG_TEST_ONLY_DO_NOT_USE_IN_PROD_XDS_CLIENT_CHANNEL_ARGS, GRPC_ARG_TEST_ONLY_DO_NOT_USE_IN_PROD_XDS_CLIENT_CHANNEL_ARGS,
&xds_channel_args_, &kChannelArgsArgVtable); &xds_channel_args_, &kChannelArgsArgVtable);
} }
std::string uri = absl::StrCat("xds://", xds_authority, "/", server_name); std::vector<absl::string_view> parts = {"xds:"};
if (xds_authority != nullptr && xds_authority[0] != '\0') {
parts.emplace_back("//");
parts.emplace_back(xds_authority);
parts.emplace_back("/");
}
parts.emplace_back(server_name);
std::string uri = absl::StrJoin(parts, "");
std::shared_ptr<ChannelCredentials> channel_creds = std::shared_ptr<ChannelCredentials> channel_creds =
GetParam().use_xds_credentials() GetParam().use_xds_credentials()
? XdsCredentials(CreateTlsFallbackCredentials()) ? XdsCredentials(CreateTlsFallbackCredentials())

@ -113,7 +113,7 @@ TEST_P(WrrTest, MetricsHaveLocalityLabel) {
grpc_core::GlobalInstrumentsRegistryTestPeer:: grpc_core::GlobalInstrumentsRegistryTestPeer::
FindDoubleHistogramHandleByName("grpc.lb.wrr.endpoint_weights") FindDoubleHistogramHandleByName("grpc.lb.wrr.endpoint_weights")
.value(); .value();
const std::string target = absl::StrCat("xds:///", kServerName); const std::string target = absl::StrCat("xds:", kServerName);
const absl::string_view kLabelValues[] = {/*target=*/target}; const absl::string_view kLabelValues[] = {/*target=*/target};
// Register stats plugin before initializing client. // Register stats plugin before initializing client.
auto stats_plugin = grpc_core::FakeStatsPluginBuilder() auto stats_plugin = grpc_core::FakeStatsPluginBuilder()
@ -137,10 +137,7 @@ TEST_P(WrrTest, MetricsHaveLocalityLabel) {
EdsResourceArgs args({{"locality0", CreateEndpointsForBackends(0, 1)}, EdsResourceArgs args({{"locality0", CreateEndpointsForBackends(0, 1)},
{"locality1", CreateEndpointsForBackends(1, 2)}}); {"locality1", CreateEndpointsForBackends(1, 2)}});
balancer_->ads_service()->SetEdsResource(BuildEdsResource(args)); balancer_->ads_service()->SetEdsResource(BuildEdsResource(args));
CheckRpcSendOk(DEBUG_LOCATION, 10); WaitForAllBackends(DEBUG_LOCATION);
// Both backends got some requests. The exact count doesn't matter.
EXPECT_GT(backends_[0]->backend_service()->request_count(), 0);
EXPECT_GT(backends_[1]->backend_service()->request_count(), 0);
// Make sure we have a metric value for each of the two localities. // Make sure we have a metric value for each of the two localities.
EXPECT_THAT( EXPECT_THAT(
stats_plugin->GetHistogramValue(kEndpointWeights, kLabelValues, stats_plugin->GetHistogramValue(kEndpointWeights, kLabelValues,

@ -52,34 +52,22 @@ static void StreamingPingPongArgs(benchmark::internal::Benchmark* b) {
} }
} }
BENCHMARK_TEMPLATE(BM_StreamingPingPong, InProcessCHTTP2, NoOpMutator,
NoOpMutator)
->Apply(StreamingPingPongArgs);
BENCHMARK_TEMPLATE(BM_StreamingPingPong, TCP, NoOpMutator, NoOpMutator) BENCHMARK_TEMPLATE(BM_StreamingPingPong, TCP, NoOpMutator, NoOpMutator)
->Apply(StreamingPingPongArgs); ->Apply(StreamingPingPongArgs);
BENCHMARK_TEMPLATE(BM_StreamingPingPong, InProcess, NoOpMutator, NoOpMutator) BENCHMARK_TEMPLATE(BM_StreamingPingPong, InProcess, NoOpMutator, NoOpMutator)
->Apply(StreamingPingPongArgs); ->Apply(StreamingPingPongArgs);
BENCHMARK_TEMPLATE(BM_StreamingPingPongMsgs, InProcessCHTTP2, NoOpMutator,
NoOpMutator)
->Range(0, kMaxMessageSize);
BENCHMARK_TEMPLATE(BM_StreamingPingPongMsgs, TCP, NoOpMutator, NoOpMutator) BENCHMARK_TEMPLATE(BM_StreamingPingPongMsgs, TCP, NoOpMutator, NoOpMutator)
->Range(0, kMaxMessageSize); ->Range(0, kMaxMessageSize);
BENCHMARK_TEMPLATE(BM_StreamingPingPongMsgs, InProcess, NoOpMutator, BENCHMARK_TEMPLATE(BM_StreamingPingPongMsgs, InProcess, NoOpMutator,
NoOpMutator) NoOpMutator)
->Range(0, kMaxMessageSize); ->Range(0, kMaxMessageSize);
BENCHMARK_TEMPLATE(BM_StreamingPingPong, MinInProcessCHTTP2, NoOpMutator,
NoOpMutator)
->Apply(StreamingPingPongArgs);
BENCHMARK_TEMPLATE(BM_StreamingPingPong, MinTCP, NoOpMutator, NoOpMutator) BENCHMARK_TEMPLATE(BM_StreamingPingPong, MinTCP, NoOpMutator, NoOpMutator)
->Apply(StreamingPingPongArgs); ->Apply(StreamingPingPongArgs);
BENCHMARK_TEMPLATE(BM_StreamingPingPong, MinInProcess, NoOpMutator, NoOpMutator) BENCHMARK_TEMPLATE(BM_StreamingPingPong, MinInProcess, NoOpMutator, NoOpMutator)
->Apply(StreamingPingPongArgs); ->Apply(StreamingPingPongArgs);
BENCHMARK_TEMPLATE(BM_StreamingPingPongMsgs, MinInProcessCHTTP2, NoOpMutator,
NoOpMutator)
->Range(0, kMaxMessageSize);
BENCHMARK_TEMPLATE(BM_StreamingPingPongMsgs, MinTCP, NoOpMutator, NoOpMutator) BENCHMARK_TEMPLATE(BM_StreamingPingPongMsgs, MinTCP, NoOpMutator, NoOpMutator)
->Range(0, kMaxMessageSize); ->Range(0, kMaxMessageSize);
BENCHMARK_TEMPLATE(BM_StreamingPingPongMsgs, MinInProcess, NoOpMutator, BENCHMARK_TEMPLATE(BM_StreamingPingPongMsgs, MinInProcess, NoOpMutator,
@ -106,12 +94,6 @@ static void StreamingPingPongWithCoalescingApiArgs(
} }
} }
BENCHMARK_TEMPLATE(BM_StreamingPingPongWithCoalescingApi, InProcessCHTTP2,
NoOpMutator, NoOpMutator)
->Apply(StreamingPingPongWithCoalescingApiArgs);
BENCHMARK_TEMPLATE(BM_StreamingPingPongWithCoalescingApi, MinInProcessCHTTP2,
NoOpMutator, NoOpMutator)
->Apply(StreamingPingPongWithCoalescingApiArgs);
BENCHMARK_TEMPLATE(BM_StreamingPingPongWithCoalescingApi, InProcess, BENCHMARK_TEMPLATE(BM_StreamingPingPongWithCoalescingApi, InProcess,
NoOpMutator, NoOpMutator) NoOpMutator, NoOpMutator)
->Apply(StreamingPingPongWithCoalescingApiArgs); ->Apply(StreamingPingPongWithCoalescingApiArgs);

@ -35,24 +35,18 @@ BENCHMARK_TEMPLATE(BM_PumpStreamClientToServer, UDS)
->Range(0, 128 * 1024 * 1024); ->Range(0, 128 * 1024 * 1024);
BENCHMARK_TEMPLATE(BM_PumpStreamClientToServer, InProcess) BENCHMARK_TEMPLATE(BM_PumpStreamClientToServer, InProcess)
->Range(0, 128 * 1024 * 1024); ->Range(0, 128 * 1024 * 1024);
BENCHMARK_TEMPLATE(BM_PumpStreamClientToServer, InProcessCHTTP2)
->Range(0, 128 * 1024 * 1024);
BENCHMARK_TEMPLATE(BM_PumpStreamServerToClient, TCP) BENCHMARK_TEMPLATE(BM_PumpStreamServerToClient, TCP)
->Range(0, 128 * 1024 * 1024); ->Range(0, 128 * 1024 * 1024);
BENCHMARK_TEMPLATE(BM_PumpStreamServerToClient, UDS) BENCHMARK_TEMPLATE(BM_PumpStreamServerToClient, UDS)
->Range(0, 128 * 1024 * 1024); ->Range(0, 128 * 1024 * 1024);
BENCHMARK_TEMPLATE(BM_PumpStreamServerToClient, InProcess) BENCHMARK_TEMPLATE(BM_PumpStreamServerToClient, InProcess)
->Range(0, 128 * 1024 * 1024); ->Range(0, 128 * 1024 * 1024);
BENCHMARK_TEMPLATE(BM_PumpStreamServerToClient, InProcessCHTTP2)
->Range(0, 128 * 1024 * 1024);
BENCHMARK_TEMPLATE(BM_PumpStreamClientToServer, MinTCP)->Arg(0); BENCHMARK_TEMPLATE(BM_PumpStreamClientToServer, MinTCP)->Arg(0);
BENCHMARK_TEMPLATE(BM_PumpStreamClientToServer, MinUDS)->Arg(0); BENCHMARK_TEMPLATE(BM_PumpStreamClientToServer, MinUDS)->Arg(0);
BENCHMARK_TEMPLATE(BM_PumpStreamClientToServer, MinInProcess)->Arg(0); BENCHMARK_TEMPLATE(BM_PumpStreamClientToServer, MinInProcess)->Arg(0);
BENCHMARK_TEMPLATE(BM_PumpStreamClientToServer, MinInProcessCHTTP2)->Arg(0);
BENCHMARK_TEMPLATE(BM_PumpStreamServerToClient, MinTCP)->Arg(0); BENCHMARK_TEMPLATE(BM_PumpStreamServerToClient, MinTCP)->Arg(0);
BENCHMARK_TEMPLATE(BM_PumpStreamServerToClient, MinUDS)->Arg(0); BENCHMARK_TEMPLATE(BM_PumpStreamServerToClient, MinUDS)->Arg(0);
BENCHMARK_TEMPLATE(BM_PumpStreamServerToClient, MinInProcess)->Arg(0); BENCHMARK_TEMPLATE(BM_PumpStreamServerToClient, MinInProcess)->Arg(0);
BENCHMARK_TEMPLATE(BM_PumpStreamServerToClient, MinInProcessCHTTP2)->Arg(0);
} // namespace testing } // namespace testing
} // namespace grpc } // namespace grpc

@ -56,61 +56,6 @@ BENCHMARK_TEMPLATE(BM_UnaryPingPong, SockPair, NoOpMutator, NoOpMutator)
->Args({0, 0}); ->Args({0, 0});
BENCHMARK_TEMPLATE(BM_UnaryPingPong, MinSockPair, NoOpMutator, NoOpMutator) BENCHMARK_TEMPLATE(BM_UnaryPingPong, MinSockPair, NoOpMutator, NoOpMutator)
->Args({0, 0}); ->Args({0, 0});
BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2, NoOpMutator, NoOpMutator)
->Apply(SweepSizesArgs);
BENCHMARK_TEMPLATE(BM_UnaryPingPong, MinInProcessCHTTP2, NoOpMutator,
NoOpMutator)
->Apply(SweepSizesArgs);
BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2,
Client_AddMetadata<RandomBinaryMetadata<10>, 1>, NoOpMutator)
->Args({0, 0});
BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2,
Client_AddMetadata<RandomBinaryMetadata<31>, 1>, NoOpMutator)
->Args({0, 0});
BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2,
Client_AddMetadata<RandomBinaryMetadata<100>, 1>,
NoOpMutator)
->Args({0, 0});
BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2,
Client_AddMetadata<RandomBinaryMetadata<10>, 2>, NoOpMutator)
->Args({0, 0});
BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2,
Client_AddMetadata<RandomBinaryMetadata<31>, 2>, NoOpMutator)
->Args({0, 0});
BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2,
Client_AddMetadata<RandomBinaryMetadata<100>, 2>,
NoOpMutator)
->Args({0, 0});
BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2, NoOpMutator,
Server_AddInitialMetadata<RandomBinaryMetadata<10>, 1>)
->Args({0, 0});
BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2, NoOpMutator,
Server_AddInitialMetadata<RandomBinaryMetadata<31>, 1>)
->Args({0, 0});
BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2, NoOpMutator,
Server_AddInitialMetadata<RandomBinaryMetadata<100>, 1>)
->Args({0, 0});
BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2,
Client_AddMetadata<RandomAsciiMetadata<10>, 1>, NoOpMutator)
->Args({0, 0});
BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2,
Client_AddMetadata<RandomAsciiMetadata<31>, 1>, NoOpMutator)
->Args({0, 0});
BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2,
Client_AddMetadata<RandomAsciiMetadata<100>, 1>, NoOpMutator)
->Args({0, 0});
BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2, NoOpMutator,
Server_AddInitialMetadata<RandomAsciiMetadata<10>, 1>)
->Args({0, 0});
BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2, NoOpMutator,
Server_AddInitialMetadata<RandomAsciiMetadata<31>, 1>)
->Args({0, 0});
BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2, NoOpMutator,
Server_AddInitialMetadata<RandomAsciiMetadata<100>, 1>)
->Args({0, 0});
BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2, NoOpMutator,
Server_AddInitialMetadata<RandomAsciiMetadata<10>, 100>)
->Args({0, 0});
BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcess, BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcess,
Client_AddMetadata<RandomBinaryMetadata<10>, 1>, NoOpMutator) Client_AddMetadata<RandomBinaryMetadata<10>, 1>, NoOpMutator)
->Args({0, 0}); ->Args({0, 0});

@ -40,7 +40,6 @@
#include "src/core/lib/surface/completion_queue.h" #include "src/core/lib/surface/completion_queue.h"
#include "src/core/lib/surface/server.h" #include "src/core/lib/surface/server.h"
#include "src/cpp/client/create_channel_internal.h" #include "src/cpp/client/create_channel_internal.h"
#include "test/core/util/passthru_endpoint.h"
#include "test/core/util/port.h" #include "test/core/util/port.h"
#include "test/core/util/test_config.h" #include "test/core/util/test_config.h"
#include "test/cpp/microbenchmarks/helpers.h" #include "test/cpp/microbenchmarks/helpers.h"
@ -254,45 +253,6 @@ class SockPair : public EndpointPairFixture {
fixture_configuration) {} fixture_configuration) {}
}; };
// Use InProcessCHTTP2 instead. This class (with stats as an explicit parameter)
// is here only to be able to initialize both the base class and stats_ with the
// same stats instance without accessing the stats_ fields before the object is
// properly initialized.
class InProcessCHTTP2WithExplicitStats : public EndpointPairFixture {
public:
InProcessCHTTP2WithExplicitStats(
Service* service, grpc_passthru_endpoint_stats* stats,
const FixtureConfiguration& fixture_configuration)
: EndpointPairFixture(service, MakeEndpoints(stats),
fixture_configuration),
stats_(stats) {}
~InProcessCHTTP2WithExplicitStats() override {
if (stats_ != nullptr) {
grpc_passthru_endpoint_stats_destroy(stats_);
}
}
private:
grpc_passthru_endpoint_stats* stats_;
static grpc_endpoint_pair MakeEndpoints(grpc_passthru_endpoint_stats* stats) {
grpc_endpoint_pair p;
grpc_passthru_endpoint_create(&p.client, &p.server, stats);
return p;
}
};
class InProcessCHTTP2 : public InProcessCHTTP2WithExplicitStats {
public:
explicit InProcessCHTTP2(Service* service,
const FixtureConfiguration& fixture_configuration =
FixtureConfiguration())
: InProcessCHTTP2WithExplicitStats(service,
grpc_passthru_endpoint_stats_create(),
fixture_configuration) {}
};
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Minimal stack fixtures // Minimal stack fixtures
@ -319,7 +279,6 @@ typedef MinStackize<TCP> MinTCP;
typedef MinStackize<UDS> MinUDS; typedef MinStackize<UDS> MinUDS;
typedef MinStackize<InProcess> MinInProcess; typedef MinStackize<InProcess> MinInProcess;
typedef MinStackize<SockPair> MinSockPair; typedef MinStackize<SockPair> MinSockPair;
typedef MinStackize<InProcessCHTTP2> MinInProcessCHTTP2;
} // namespace testing } // namespace testing
} // namespace grpc } // namespace grpc

Loading…
Cancel
Save