diff --git a/BUILD b/BUILD
index 945acd00260..d9a9cf1153f 100644
--- a/BUILD
+++ b/BUILD
@@ -4082,6 +4082,11 @@ grpc_upb_proto_library(
deps = ["@envoy_api//envoy/extensions/load_balancing_policies/client_side_weighted_round_robin/v3:pkg"],
)
+grpc_upb_proto_library(
+ name = "envoy_extensions_load_balancing_policies_pick_first_upb",
+ deps = ["@envoy_api//envoy/extensions/load_balancing_policies/pick_first/v3:pkg"],
+)
+
grpc_upb_proto_library(
name = "envoy_extensions_load_balancing_policies_ring_hash_upb",
deps = ["@envoy_api//envoy/extensions/load_balancing_policies/ring_hash/v3:pkg"],
diff --git a/CMakeLists.txt b/CMakeLists.txt
index cd5b2c15645..0de5cb0e45c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -723,6 +723,9 @@ protobuf_generate_grpc_cpp_with_import_path_correction(
protobuf_generate_grpc_cpp_with_import_path_correction(
src/proto/grpc/testing/xds/v3/percent.proto src/proto/grpc/testing/xds/v3/percent.proto
)
+protobuf_generate_grpc_cpp_with_import_path_correction(
+ src/proto/grpc/testing/xds/v3/pick_first.proto src/proto/grpc/testing/xds/v3/pick_first.proto
+)
protobuf_generate_grpc_cpp_with_import_path_correction(
src/proto/grpc/testing/xds/v3/protocol.proto src/proto/grpc/testing/xds/v3/protocol.proto
)
@@ -1438,6 +1441,9 @@ if(gRPC_BUILD_TESTS)
endif()
add_dependencies(buildtests_cxx xds_override_host_lb_config_parser_test)
add_dependencies(buildtests_cxx xds_override_host_test)
+ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+ add_dependencies(buildtests_cxx xds_pick_first_end2end_test)
+ endif()
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_dependencies(buildtests_cxx xds_ring_hash_end2end_test)
endif()
@@ -1855,6 +1861,7 @@ add_library(grpc
src/core/ext/upb-generated/envoy/extensions/http/stateful_session/cookie/v3/cookie.upb.c
src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/client_side_weighted_round_robin/v3/client_side_weighted_round_robin.upb.c
src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/common/v3/common.upb.c
+ src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/pick_first/v3/pick_first.upb.c
src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb.c
src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/wrr_locality/v3/wrr_locality.upb.c
src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/cert.upb.c
@@ -29400,6 +29407,10 @@ add_executable(xds_lb_policy_registry_test
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/percent.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/percent.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/percent.grpc.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/pick_first.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/pick_first.grpc.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/pick_first.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/pick_first.grpc.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/ring_hash.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/ring_hash.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/ring_hash.pb.h
@@ -30026,6 +30037,182 @@ target_link_libraries(xds_override_host_test
)
+endif()
+if(gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+
+ add_executable(xds_pick_first_end2end_test
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/address.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/address.grpc.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/address.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/address.grpc.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/ads.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/ads.grpc.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/ads.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/ads.grpc.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/aggregate_cluster.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/aggregate_cluster.grpc.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/aggregate_cluster.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/aggregate_cluster.grpc.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/base.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/base.grpc.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/base.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/base.grpc.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/cluster.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/cluster.grpc.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/cluster.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/cluster.grpc.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_source.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_source.grpc.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_source.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_source.grpc.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/discovery.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/discovery.grpc.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/discovery.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/discovery.grpc.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/endpoint.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/endpoint.grpc.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/endpoint.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/endpoint.grpc.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/expr.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/expr.grpc.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/expr.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/expr.grpc.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/extension.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/extension.grpc.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/extension.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/extension.grpc.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/health_check.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/health_check.grpc.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/health_check.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/health_check.grpc.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/http_connection_manager.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/http_connection_manager.grpc.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/http_connection_manager.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/http_connection_manager.grpc.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/http_filter_rbac.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/http_filter_rbac.grpc.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/http_filter_rbac.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/http_filter_rbac.grpc.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/listener.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/listener.grpc.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/listener.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/listener.grpc.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/load_report.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/load_report.grpc.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/load_report.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/load_report.grpc.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/lrs.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/lrs.grpc.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/lrs.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/lrs.grpc.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/metadata.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/metadata.grpc.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/metadata.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/metadata.grpc.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/orca_load_report.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/orca_load_report.grpc.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/orca_load_report.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/orca_load_report.grpc.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/outlier_detection.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/outlier_detection.grpc.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/outlier_detection.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/outlier_detection.grpc.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/path.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/path.grpc.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/path.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/path.grpc.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/percent.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/percent.grpc.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/percent.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/percent.grpc.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/pick_first.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/pick_first.grpc.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/pick_first.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/pick_first.grpc.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/protocol.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/protocol.grpc.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/protocol.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/protocol.grpc.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/range.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/range.grpc.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/range.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/range.grpc.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/rbac.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/rbac.grpc.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/rbac.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/rbac.grpc.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/regex.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/regex.grpc.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/regex.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/regex.grpc.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/route.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/route.grpc.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/route.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/route.grpc.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/router.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/router.grpc.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/router.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/router.grpc.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/string.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/string.grpc.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/string.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/string.grpc.pb.h
+ test/cpp/end2end/connection_attempt_injector.cc
+ test/cpp/end2end/test_service_impl.cc
+ test/cpp/end2end/xds/xds_end2end_test_lib.cc
+ test/cpp/end2end/xds/xds_pick_first_end2end_test.cc
+ test/cpp/end2end/xds/xds_server.cc
+ test/cpp/util/tls_test_utils.cc
+ third_party/googletest/googletest/src/gtest-all.cc
+ third_party/googletest/googlemock/src/gmock-all.cc
+ )
+ target_compile_features(xds_pick_first_end2end_test PUBLIC cxx_std_14)
+ target_include_directories(xds_pick_first_end2end_test
+ PRIVATE
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ ${CMAKE_CURRENT_SOURCE_DIR}/include
+ ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
+ ${_gRPC_RE2_INCLUDE_DIR}
+ ${_gRPC_SSL_INCLUDE_DIR}
+ ${_gRPC_UPB_GENERATED_DIR}
+ ${_gRPC_UPB_GRPC_GENERATED_DIR}
+ ${_gRPC_UPB_INCLUDE_DIR}
+ ${_gRPC_XXHASH_INCLUDE_DIR}
+ ${_gRPC_ZLIB_INCLUDE_DIR}
+ third_party/googletest/googletest/include
+ third_party/googletest/googletest
+ third_party/googletest/googlemock/include
+ third_party/googletest/googlemock
+ ${_gRPC_PROTO_GENS_DIR}
+ )
+
+ target_link_libraries(xds_pick_first_end2end_test
+ ${_gRPC_BASELIB_LIBRARIES}
+ ${_gRPC_PROTOBUF_LIBRARIES}
+ ${_gRPC_ZLIB_LIBRARIES}
+ ${_gRPC_ALLTARGETS_LIBRARIES}
+ grpc++_test_util
+ )
+
+
+endif()
endif()
if(gRPC_BUILD_TESTS)
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
diff --git a/Makefile b/Makefile
index 47eb7261e0e..5ef57c8da7f 100644
--- a/Makefile
+++ b/Makefile
@@ -1144,6 +1144,7 @@ LIBGRPC_SRC = \
src/core/ext/upb-generated/envoy/extensions/http/stateful_session/cookie/v3/cookie.upb.c \
src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/client_side_weighted_round_robin/v3/client_side_weighted_round_robin.upb.c \
src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/common/v3/common.upb.c \
+ src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/pick_first/v3/pick_first.upb.c \
src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb.c \
src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/wrr_locality/v3/wrr_locality.upb.c \
src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/cert.upb.c \
@@ -3139,6 +3140,7 @@ src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_mana
src/core/ext/upb-generated/envoy/extensions/http/stateful_session/cookie/v3/cookie.upb.c: $(OPENSSL_DEP)
src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/client_side_weighted_round_robin/v3/client_side_weighted_round_robin.upb.c: $(OPENSSL_DEP)
src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/common/v3/common.upb.c: $(OPENSSL_DEP)
+src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/pick_first/v3/pick_first.upb.c: $(OPENSSL_DEP)
src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb.c: $(OPENSSL_DEP)
src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/wrr_locality/v3/wrr_locality.upb.c: $(OPENSSL_DEP)
src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/cert.upb.c: $(OPENSSL_DEP)
diff --git a/Package.swift b/Package.swift
index 7e04d9f9be8..57119cccf05 100644
--- a/Package.swift
+++ b/Package.swift
@@ -463,6 +463,8 @@ let package = Package(
"src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/client_side_weighted_round_robin/v3/client_side_weighted_round_robin.upb.h",
"src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/common/v3/common.upb.c",
"src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/common/v3/common.upb.h",
+ "src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/pick_first/v3/pick_first.upb.c",
+ "src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/pick_first/v3/pick_first.upb.h",
"src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb.c",
"src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb.h",
"src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/wrr_locality/v3/wrr_locality.upb.c",
diff --git a/build_autogenerated.yaml b/build_autogenerated.yaml
index 8cc28a1ac60..e9066caf3fc 100644
--- a/build_autogenerated.yaml
+++ b/build_autogenerated.yaml
@@ -382,6 +382,7 @@ libs:
- src/core/ext/upb-generated/envoy/extensions/http/stateful_session/cookie/v3/cookie.upb.h
- src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/client_side_weighted_round_robin/v3/client_side_weighted_round_robin.upb.h
- src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/common/v3/common.upb.h
+ - src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/pick_first/v3/pick_first.upb.h
- src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb.h
- src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/wrr_locality/v3/wrr_locality.upb.h
- src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/cert.upb.h
@@ -1199,6 +1200,7 @@ libs:
- src/core/ext/upb-generated/envoy/extensions/http/stateful_session/cookie/v3/cookie.upb.c
- src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/client_side_weighted_round_robin/v3/client_side_weighted_round_robin.upb.c
- src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/common/v3/common.upb.c
+ - src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/pick_first/v3/pick_first.upb.c
- src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb.c
- src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/wrr_locality/v3/wrr_locality.upb.c
- src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/cert.upb.c
@@ -16673,6 +16675,7 @@ targets:
build: test
language: c++
headers:
+ - test/core/util/scoped_env_var.h
- test/cpp/util/cli_call.h
- test/cpp/util/cli_credentials.h
- test/cpp/util/config_grpc_cli.h
@@ -16691,6 +16694,7 @@ targets:
- src/proto/grpc/testing/xds/v3/health_check.proto
- src/proto/grpc/testing/xds/v3/outlier_detection.proto
- src/proto/grpc/testing/xds/v3/percent.proto
+ - src/proto/grpc/testing/xds/v3/pick_first.proto
- src/proto/grpc/testing/xds/v3/ring_hash.proto
- src/proto/grpc/testing/xds/v3/round_robin.proto
- src/proto/grpc/testing/xds/v3/typed_struct.proto
@@ -16887,6 +16891,64 @@ targets:
deps:
- grpc_test_util
uses_polling: false
+- name: xds_pick_first_end2end_test
+ gtest: true
+ build: test
+ language: c++
+ headers:
+ - test/core/util/scoped_env_var.h
+ - test/cpp/end2end/connection_attempt_injector.h
+ - test/cpp/end2end/counted_service.h
+ - test/cpp/end2end/test_service_impl.h
+ - test/cpp/end2end/xds/xds_end2end_test_lib.h
+ - test/cpp/end2end/xds/xds_server.h
+ - test/cpp/util/tls_test_utils.h
+ src:
+ - src/proto/grpc/testing/duplicate/echo_duplicate.proto
+ - src/proto/grpc/testing/echo.proto
+ - src/proto/grpc/testing/echo_messages.proto
+ - src/proto/grpc/testing/simple_messages.proto
+ - src/proto/grpc/testing/xds/v3/address.proto
+ - src/proto/grpc/testing/xds/v3/ads.proto
+ - src/proto/grpc/testing/xds/v3/aggregate_cluster.proto
+ - src/proto/grpc/testing/xds/v3/base.proto
+ - src/proto/grpc/testing/xds/v3/cluster.proto
+ - src/proto/grpc/testing/xds/v3/config_source.proto
+ - src/proto/grpc/testing/xds/v3/discovery.proto
+ - src/proto/grpc/testing/xds/v3/endpoint.proto
+ - src/proto/grpc/testing/xds/v3/expr.proto
+ - src/proto/grpc/testing/xds/v3/extension.proto
+ - src/proto/grpc/testing/xds/v3/health_check.proto
+ - src/proto/grpc/testing/xds/v3/http_connection_manager.proto
+ - src/proto/grpc/testing/xds/v3/http_filter_rbac.proto
+ - src/proto/grpc/testing/xds/v3/listener.proto
+ - src/proto/grpc/testing/xds/v3/load_report.proto
+ - src/proto/grpc/testing/xds/v3/lrs.proto
+ - src/proto/grpc/testing/xds/v3/metadata.proto
+ - src/proto/grpc/testing/xds/v3/orca_load_report.proto
+ - src/proto/grpc/testing/xds/v3/outlier_detection.proto
+ - src/proto/grpc/testing/xds/v3/path.proto
+ - src/proto/grpc/testing/xds/v3/percent.proto
+ - src/proto/grpc/testing/xds/v3/pick_first.proto
+ - src/proto/grpc/testing/xds/v3/protocol.proto
+ - src/proto/grpc/testing/xds/v3/range.proto
+ - src/proto/grpc/testing/xds/v3/rbac.proto
+ - src/proto/grpc/testing/xds/v3/regex.proto
+ - src/proto/grpc/testing/xds/v3/route.proto
+ - src/proto/grpc/testing/xds/v3/router.proto
+ - src/proto/grpc/testing/xds/v3/string.proto
+ - test/cpp/end2end/connection_attempt_injector.cc
+ - test/cpp/end2end/test_service_impl.cc
+ - test/cpp/end2end/xds/xds_end2end_test_lib.cc
+ - test/cpp/end2end/xds/xds_pick_first_end2end_test.cc
+ - test/cpp/end2end/xds/xds_server.cc
+ - test/cpp/util/tls_test_utils.cc
+ deps:
+ - grpc++_test_util
+ platforms:
+ - linux
+ - posix
+ - mac
- name: xds_ring_hash_end2end_test
gtest: true
build: test
diff --git a/config.m4 b/config.m4
index 2d937db5208..16f2e2436c8 100644
--- a/config.m4
+++ b/config.m4
@@ -223,6 +223,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/ext/upb-generated/envoy/extensions/http/stateful_session/cookie/v3/cookie.upb.c \
src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/client_side_weighted_round_robin/v3/client_side_weighted_round_robin.upb.c \
src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/common/v3/common.upb.c \
+ src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/pick_first/v3/pick_first.upb.c \
src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb.c \
src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/wrr_locality/v3/wrr_locality.upb.c \
src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/cert.upb.c \
@@ -1390,6 +1391,7 @@ if test "$PHP_GRPC" != "no"; then
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/extensions/http/stateful_session/cookie/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/client_side_weighted_round_robin/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/common/v3)
+ PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/pick_first/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/ring_hash/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/wrr_locality/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3)
diff --git a/config.w32 b/config.w32
index 4717a9f46ad..99906275018 100644
--- a/config.w32
+++ b/config.w32
@@ -188,6 +188,7 @@ if (PHP_GRPC != "no") {
"src\\core\\ext\\upb-generated\\envoy\\extensions\\http\\stateful_session\\cookie\\v3\\cookie.upb.c " +
"src\\core\\ext\\upb-generated\\envoy\\extensions\\load_balancing_policies\\client_side_weighted_round_robin\\v3\\client_side_weighted_round_robin.upb.c " +
"src\\core\\ext\\upb-generated\\envoy\\extensions\\load_balancing_policies\\common\\v3\\common.upb.c " +
+ "src\\core\\ext\\upb-generated\\envoy\\extensions\\load_balancing_policies\\pick_first\\v3\\pick_first.upb.c " +
"src\\core\\ext\\upb-generated\\envoy\\extensions\\load_balancing_policies\\ring_hash\\v3\\ring_hash.upb.c " +
"src\\core\\ext\\upb-generated\\envoy\\extensions\\load_balancing_policies\\wrr_locality\\v3\\wrr_locality.upb.c " +
"src\\core\\ext\\upb-generated\\envoy\\extensions\\transport_sockets\\tls\\v3\\cert.upb.c " +
@@ -1429,6 +1430,8 @@ if (PHP_GRPC != "no") {
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\extensions\\load_balancing_policies\\client_side_weighted_round_robin\\v3");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\extensions\\load_balancing_policies\\common");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\extensions\\load_balancing_policies\\common\\v3");
+ FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\extensions\\load_balancing_policies\\pick_first");
+ FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\extensions\\load_balancing_policies\\pick_first\\v3");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\extensions\\load_balancing_policies\\ring_hash");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\extensions\\load_balancing_policies\\ring_hash\\v3");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\extensions\\load_balancing_policies\\wrr_locality");
diff --git a/gRPC-C++.podspec b/gRPC-C++.podspec
index acb834679b5..76c9a646391 100644
--- a/gRPC-C++.podspec
+++ b/gRPC-C++.podspec
@@ -452,6 +452,7 @@ Pod::Spec.new do |s|
'src/core/ext/upb-generated/envoy/extensions/http/stateful_session/cookie/v3/cookie.upb.h',
'src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/client_side_weighted_round_robin/v3/client_side_weighted_round_robin.upb.h',
'src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/common/v3/common.upb.h',
+ 'src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/pick_first/v3/pick_first.upb.h',
'src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb.h',
'src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/wrr_locality/v3/wrr_locality.upb.h',
'src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/cert.upb.h',
@@ -1496,6 +1497,7 @@ Pod::Spec.new do |s|
'src/core/ext/upb-generated/envoy/extensions/http/stateful_session/cookie/v3/cookie.upb.h',
'src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/client_side_weighted_round_robin/v3/client_side_weighted_round_robin.upb.h',
'src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/common/v3/common.upb.h',
+ 'src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/pick_first/v3/pick_first.upb.h',
'src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb.h',
'src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/wrr_locality/v3/wrr_locality.upb.h',
'src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/cert.upb.h',
diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec
index f69b95d25d5..85eae1e27b1 100644
--- a/gRPC-Core.podspec
+++ b/gRPC-Core.podspec
@@ -564,6 +564,8 @@ Pod::Spec.new do |s|
'src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/client_side_weighted_round_robin/v3/client_side_weighted_round_robin.upb.h',
'src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/common/v3/common.upb.c',
'src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/common/v3/common.upb.h',
+ 'src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/pick_first/v3/pick_first.upb.c',
+ 'src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/pick_first/v3/pick_first.upb.h',
'src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb.c',
'src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb.h',
'src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/wrr_locality/v3/wrr_locality.upb.c',
@@ -2226,6 +2228,7 @@ Pod::Spec.new do |s|
'src/core/ext/upb-generated/envoy/extensions/http/stateful_session/cookie/v3/cookie.upb.h',
'src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/client_side_weighted_round_robin/v3/client_side_weighted_round_robin.upb.h',
'src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/common/v3/common.upb.h',
+ 'src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/pick_first/v3/pick_first.upb.h',
'src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb.h',
'src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/wrr_locality/v3/wrr_locality.upb.h',
'src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/cert.upb.h',
diff --git a/grpc.gemspec b/grpc.gemspec
index 4a5124ef2aa..da13cb4b1ae 100644
--- a/grpc.gemspec
+++ b/grpc.gemspec
@@ -469,6 +469,8 @@ Gem::Specification.new do |s|
s.files += %w( src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/client_side_weighted_round_robin/v3/client_side_weighted_round_robin.upb.h )
s.files += %w( src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/common/v3/common.upb.c )
s.files += %w( src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/common/v3/common.upb.h )
+ s.files += %w( src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/pick_first/v3/pick_first.upb.c )
+ s.files += %w( src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/pick_first/v3/pick_first.upb.h )
s.files += %w( src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb.c )
s.files += %w( src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb.h )
s.files += %w( src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/wrr_locality/v3/wrr_locality.upb.c )
diff --git a/grpc.gyp b/grpc.gyp
index 5024d063f55..71fed91a53b 100644
--- a/grpc.gyp
+++ b/grpc.gyp
@@ -448,6 +448,7 @@
'src/core/ext/upb-generated/envoy/extensions/http/stateful_session/cookie/v3/cookie.upb.c',
'src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/client_side_weighted_round_robin/v3/client_side_weighted_round_robin.upb.c',
'src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/common/v3/common.upb.c',
+ 'src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/pick_first/v3/pick_first.upb.c',
'src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb.c',
'src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/wrr_locality/v3/wrr_locality.upb.c',
'src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/cert.upb.c',
diff --git a/package.xml b/package.xml
index c9bace71f3e..1cc17f8a6cb 100644
--- a/package.xml
+++ b/package.xml
@@ -451,6 +451,8 @@
+
+
diff --git a/src/core/BUILD b/src/core/BUILD
index dc83c9e6dbb..3c1e8b6f798 100644
--- a/src/core/BUILD
+++ b/src/core/BUILD
@@ -4126,6 +4126,7 @@ grpc_cc_library(
"envoy_extensions_http_stateful_session_cookie_upb",
"envoy_extensions_http_stateful_session_cookie_upbdefs",
"envoy_extensions_load_balancing_policies_client_side_weighted_round_robin_upb",
+ "envoy_extensions_load_balancing_policies_pick_first_upb",
"envoy_extensions_load_balancing_policies_ring_hash_upb",
"envoy_extensions_load_balancing_policies_wrr_locality_upb",
"envoy_extensions_transport_sockets_tls_upb",
@@ -4144,6 +4145,7 @@ grpc_cc_library(
"grpc_audit_logging",
"grpc_fake_credentials",
"grpc_fault_injection_filter",
+ "grpc_lb_policy_pick_first",
"grpc_lb_xds_channel_args",
"grpc_matchers",
"grpc_outlier_detection_header",
@@ -5907,6 +5909,11 @@ grpc_upb_proto_library(
deps = ["@envoy_api//envoy/extensions/load_balancing_policies/wrr_locality/v3:pkg"],
)
+grpc_upb_proto_library(
+ name = "envoy_extensions_load_balancing_policies_pick_first_upb",
+ deps = ["@envoy_api//envoy/extensions/load_balancing_policies/pick_first/v3:pkg"],
+)
+
grpc_upb_proto_library(
name = "envoy_extensions_filters_network_http_connection_manager_upb",
deps = ["@envoy_api//envoy/extensions/filters/network/http_connection_manager/v3:pkg"],
diff --git a/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc b/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc
index 9d3a0d871db..3c6ccd585c5 100644
--- a/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc
+++ b/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc
@@ -63,14 +63,6 @@ namespace grpc_core {
TraceFlag grpc_lb_pick_first_trace(false, "pick_first");
-namespace {
-
-//
-// pick_first LB policy
-//
-
-constexpr absl::string_view kPickFirst = "pick_first";
-
// TODO(eostroukhov): Remove once this feature is no longer experimental.
bool ShufflePickFirstEnabled() {
auto value = GetEnv("GRPC_EXPERIMENTAL_PICKFIRST_LB_CONFIG");
@@ -80,6 +72,14 @@ bool ShufflePickFirstEnabled() {
return parse_succeeded && parsed_value;
}
+namespace {
+
+//
+// pick_first LB policy
+//
+
+constexpr absl::string_view kPickFirst = "pick_first";
+
class PickFirstConfig : public LoadBalancingPolicy::Config {
public:
absl::string_view name() const override { return kPickFirst; }
diff --git a/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.h b/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.h
index ff5e0e6f2a4..4525cef730c 100644
--- a/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.h
+++ b/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.h
@@ -33,4 +33,9 @@
#define GRPC_ARG_INTERNAL_PICK_FIRST_OMIT_STATUS_MESSAGE_PREFIX \
GRPC_ARG_NO_SUBCHANNEL_PREFIX "pick_first_omit_status_message_prefix"
+namespace grpc_core {
+// TODO(eostroukhov): Remove once this feature is no longer experimental.
+bool ShufflePickFirstEnabled();
+} // namespace grpc_core
+
#endif // GRPC_SRC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_PICK_FIRST_PICK_FIRST_H
diff --git a/src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/pick_first/v3/pick_first.upb.c b/src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/pick_first/v3/pick_first.upb.c
new file mode 100644
index 00000000000..ae154bee1ec
--- /dev/null
+++ b/src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/pick_first/v3/pick_first.upb.c
@@ -0,0 +1,47 @@
+/* This file was generated by upbc (the upb compiler) from the input
+ * file:
+ *
+ * envoy/extensions/load_balancing_policies/pick_first/v3/pick_first.proto
+ *
+ * Do not edit -- your changes will be discarded when the file is
+ * regenerated. */
+
+#include
+#include "upb/collections/array_internal.h"
+#include "upb/message/internal.h"
+#include "upb/mini_table/enum_internal.h"
+#include "envoy/extensions/load_balancing_policies/pick_first/v3/pick_first.upb.h"
+#include "udpa/annotations/status.upb.h"
+
+// Must be last.
+#include "upb/port/def.inc"
+
+static const upb_MiniTableField envoy_extensions_load_balancing_policies_pick_first_v3_PickFirst__fields[1] = {
+ {1, 0, 0, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
+};
+
+const upb_MiniTable envoy_extensions_load_balancing_policies_pick_first_v3_PickFirst_msg_init = {
+ NULL,
+ &envoy_extensions_load_balancing_policies_pick_first_v3_PickFirst__fields[0],
+ 8, 1, kUpb_ExtMode_NonExtendable, 1, UPB_FASTTABLE_MASK(8), 0,
+ UPB_FASTTABLE_INIT({
+ {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric},
+ {0x000000003f000008, &upb_psb1_1bt},
+ })
+};
+
+static const upb_MiniTable *messages_layout[1] = {
+ &envoy_extensions_load_balancing_policies_pick_first_v3_PickFirst_msg_init,
+};
+
+const upb_MiniTableFile envoy_extensions_load_balancing_policies_pick_first_v3_pick_first_proto_upb_file_layout = {
+ messages_layout,
+ NULL,
+ NULL,
+ 1,
+ 0,
+ 0,
+};
+
+#include "upb/port/undef.inc"
+
diff --git a/src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/pick_first/v3/pick_first.upb.h b/src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/pick_first/v3/pick_first.upb.h
new file mode 100644
index 00000000000..09e1db78c62
--- /dev/null
+++ b/src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/pick_first/v3/pick_first.upb.h
@@ -0,0 +1,93 @@
+/* This file was generated by upbc (the upb compiler) from the input
+ * file:
+ *
+ * envoy/extensions/load_balancing_policies/pick_first/v3/pick_first.proto
+ *
+ * Do not edit -- your changes will be discarded when the file is
+ * regenerated. */
+
+#ifndef ENVOY_EXTENSIONS_LOAD_BALANCING_POLICIES_PICK_FIRST_V3_PICK_FIRST_PROTO_UPB_H_
+#define ENVOY_EXTENSIONS_LOAD_BALANCING_POLICIES_PICK_FIRST_V3_PICK_FIRST_PROTO_UPB_H_
+
+#include "upb/collections/array_internal.h"
+#include "upb/collections/map_gencode_util.h"
+#include "upb/message/accessors.h"
+#include "upb/message/internal.h"
+#include "upb/mini_table/enum_internal.h"
+#include "upb/wire/decode.h"
+#include "upb/wire/decode_fast.h"
+#include "upb/wire/encode.h"
+
+// Must be last.
+#include "upb/port/def.inc"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct envoy_extensions_load_balancing_policies_pick_first_v3_PickFirst envoy_extensions_load_balancing_policies_pick_first_v3_PickFirst;
+extern const upb_MiniTable envoy_extensions_load_balancing_policies_pick_first_v3_PickFirst_msg_init;
+
+
+
+/* envoy.extensions.load_balancing_policies.pick_first.v3.PickFirst */
+
+UPB_INLINE envoy_extensions_load_balancing_policies_pick_first_v3_PickFirst* envoy_extensions_load_balancing_policies_pick_first_v3_PickFirst_new(upb_Arena* arena) {
+ return (envoy_extensions_load_balancing_policies_pick_first_v3_PickFirst*)_upb_Message_New(&envoy_extensions_load_balancing_policies_pick_first_v3_PickFirst_msg_init, arena);
+}
+UPB_INLINE envoy_extensions_load_balancing_policies_pick_first_v3_PickFirst* envoy_extensions_load_balancing_policies_pick_first_v3_PickFirst_parse(const char* buf, size_t size, upb_Arena* arena) {
+ envoy_extensions_load_balancing_policies_pick_first_v3_PickFirst* ret = envoy_extensions_load_balancing_policies_pick_first_v3_PickFirst_new(arena);
+ if (!ret) return NULL;
+ if (upb_Decode(buf, size, ret, &envoy_extensions_load_balancing_policies_pick_first_v3_PickFirst_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
+ return NULL;
+ }
+ return ret;
+}
+UPB_INLINE envoy_extensions_load_balancing_policies_pick_first_v3_PickFirst* envoy_extensions_load_balancing_policies_pick_first_v3_PickFirst_parse_ex(const char* buf, size_t size,
+ const upb_ExtensionRegistry* extreg,
+ int options, upb_Arena* arena) {
+ envoy_extensions_load_balancing_policies_pick_first_v3_PickFirst* ret = envoy_extensions_load_balancing_policies_pick_first_v3_PickFirst_new(arena);
+ if (!ret) return NULL;
+ if (upb_Decode(buf, size, ret, &envoy_extensions_load_balancing_policies_pick_first_v3_PickFirst_msg_init, extreg, options, arena) !=
+ kUpb_DecodeStatus_Ok) {
+ return NULL;
+ }
+ return ret;
+}
+UPB_INLINE char* envoy_extensions_load_balancing_policies_pick_first_v3_PickFirst_serialize(const envoy_extensions_load_balancing_policies_pick_first_v3_PickFirst* msg, upb_Arena* arena, size_t* len) {
+ char* ptr;
+ (void)upb_Encode(msg, &envoy_extensions_load_balancing_policies_pick_first_v3_PickFirst_msg_init, 0, arena, &ptr, len);
+ return ptr;
+}
+UPB_INLINE char* envoy_extensions_load_balancing_policies_pick_first_v3_PickFirst_serialize_ex(const envoy_extensions_load_balancing_policies_pick_first_v3_PickFirst* msg, int options,
+ upb_Arena* arena, size_t* len) {
+ char* ptr;
+ (void)upb_Encode(msg, &envoy_extensions_load_balancing_policies_pick_first_v3_PickFirst_msg_init, options, arena, &ptr, len);
+ return ptr;
+}
+UPB_INLINE void envoy_extensions_load_balancing_policies_pick_first_v3_PickFirst_clear_shuffle_address_list(envoy_extensions_load_balancing_policies_pick_first_v3_PickFirst* msg) {
+ const upb_MiniTableField field = {1, 0, 0, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+ _upb_Message_ClearNonExtensionField(msg, &field);
+}
+UPB_INLINE bool envoy_extensions_load_balancing_policies_pick_first_v3_PickFirst_shuffle_address_list(const envoy_extensions_load_balancing_policies_pick_first_v3_PickFirst* msg) {
+ bool default_val = false;
+ bool ret;
+ const upb_MiniTableField field = {1, 0, 0, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+ _upb_Message_GetNonExtensionField(msg, &field, &default_val, &ret);
+ return ret;
+}
+
+UPB_INLINE void envoy_extensions_load_balancing_policies_pick_first_v3_PickFirst_set_shuffle_address_list(envoy_extensions_load_balancing_policies_pick_first_v3_PickFirst *msg, bool value) {
+ const upb_MiniTableField field = {1, 0, 0, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+ _upb_Message_SetNonExtensionField(msg, &field, &value);
+}
+
+extern const upb_MiniTableFile envoy_extensions_load_balancing_policies_pick_first_v3_pick_first_proto_upb_file_layout;
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#include "upb/port/undef.inc"
+
+#endif /* ENVOY_EXTENSIONS_LOAD_BALANCING_POLICIES_PICK_FIRST_V3_PICK_FIRST_PROTO_UPB_H_ */
diff --git a/src/core/ext/xds/xds_lb_policy_registry.cc b/src/core/ext/xds/xds_lb_policy_registry.cc
index 3cdff1af930..9c97be9206c 100644
--- a/src/core/ext/xds/xds_lb_policy_registry.cc
+++ b/src/core/ext/xds/xds_lb_policy_registry.cc
@@ -29,12 +29,14 @@
#include "absl/types/variant.h"
#include "envoy/config/core/v3/extension.upb.h"
#include "envoy/extensions/load_balancing_policies/client_side_weighted_round_robin/v3/client_side_weighted_round_robin.upb.h"
+#include "envoy/extensions/load_balancing_policies/pick_first/v3/pick_first.upb.h"
#include "envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb.h"
#include "envoy/extensions/load_balancing_policies/wrr_locality/v3/wrr_locality.upb.h"
#include "google/protobuf/wrappers.upb.h"
#include
+#include "src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.h"
#include "src/core/ext/xds/xds_common_types.h"
#include "src/core/lib/config/core_configuration.h"
#include "src/core/lib/gprpp/time.h"
@@ -254,6 +256,38 @@ class WrrLocalityLbPolicyConfigFactory
}
};
+class PickFirstLbPolicyConfigFactory
+ : public XdsLbPolicyRegistry::ConfigFactory {
+ public:
+ Json::Object ConvertXdsLbPolicyConfig(
+ const XdsLbPolicyRegistry* /*registry*/,
+ const XdsResourceType::DecodeContext& context,
+ absl::string_view configuration, ValidationErrors* errors,
+ int /*recursion_depth*/) override {
+ const auto* resource =
+ envoy_extensions_load_balancing_policies_pick_first_v3_PickFirst_parse(
+ configuration.data(), configuration.size(), context.arena);
+ if (resource == nullptr) {
+ errors->AddError("can't decode PickFirst LB policy config");
+ return {};
+ }
+ bool shuffle_address_list =
+ envoy_extensions_load_balancing_policies_pick_first_v3_PickFirst_shuffle_address_list(
+ resource);
+ return Json::Object{
+ {"pick_first",
+ Json::FromObject({
+ {"shuffleAddressList", Json::FromBool(shuffle_address_list)},
+ })}};
+ }
+
+ absl::string_view type() override { return Type(); }
+
+ static absl::string_view Type() {
+ return "envoy.extensions.load_balancing_policies.pick_first.v3.PickFirst";
+ }
+};
+
} // namespace
//
@@ -273,6 +307,11 @@ XdsLbPolicyRegistry::XdsLbPolicyRegistry() {
policy_config_factories_.emplace(
WrrLocalityLbPolicyConfigFactory::Type(),
std::make_unique());
+ if (ShufflePickFirstEnabled()) {
+ policy_config_factories_.emplace(
+ PickFirstLbPolicyConfigFactory::Type(),
+ std::make_unique());
+ }
}
Json::Array XdsLbPolicyRegistry::ConvertXdsLbPolicyConfig(
diff --git a/src/proto/grpc/testing/xds/v3/BUILD b/src/proto/grpc/testing/xds/v3/BUILD
index 4d506b3ff28..9c02b2a9f6c 100644
--- a/src/proto/grpc/testing/xds/v3/BUILD
+++ b/src/proto/grpc/testing/xds/v3/BUILD
@@ -402,6 +402,14 @@ grpc_proto_library(
well_known_protos = True,
)
+grpc_proto_library(
+ name = "pick_first_proto",
+ srcs = [
+ "pick_first.proto",
+ ],
+ well_known_protos = True,
+)
+
grpc_proto_library(
name = "ring_hash_proto",
srcs = [
diff --git a/src/proto/grpc/testing/xds/v3/pick_first.proto b/src/proto/grpc/testing/xds/v3/pick_first.proto
new file mode 100644
index 00000000000..a5190ddf627
--- /dev/null
+++ b/src/proto/grpc/testing/xds/v3/pick_first.proto
@@ -0,0 +1,29 @@
+// Copyright 2023 The gRPC Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Local copy of Envoy xDS proto file, used for testing only.
+
+syntax = "proto3";
+
+package envoy.extensions.load_balancing_policies.pick_first.v3;
+
+// [#protodoc-title: Round Robin Load Balancing Policy]
+
+// This configuration allows the built-in PICK_FIRST LB policy to be configured
+// via the LB policy extension point.
+message PickFirst {
+ // If set to true, instructs the LB policy to shuffle the list of addresses
+ // received from the name resolver before attempting to connect to them.
+ bool shuffle_address_list = 1;
+}
diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py
index 7bff3f48602..5f82b11abe1 100644
--- a/src/python/grpcio/grpc_core_dependencies.py
+++ b/src/python/grpcio/grpc_core_dependencies.py
@@ -197,6 +197,7 @@ CORE_SOURCE_FILES = [
'src/core/ext/upb-generated/envoy/extensions/http/stateful_session/cookie/v3/cookie.upb.c',
'src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/client_side_weighted_round_robin/v3/client_side_weighted_round_robin.upb.c',
'src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/common/v3/common.upb.c',
+ 'src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/pick_first/v3/pick_first.upb.c',
'src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb.c',
'src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/wrr_locality/v3/wrr_locality.upb.c',
'src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/cert.upb.c',
diff --git a/test/core/xds/BUILD b/test/core/xds/BUILD
index 6750ed52dae..76ce4fc4a60 100644
--- a/test/core/xds/BUILD
+++ b/test/core/xds/BUILD
@@ -113,12 +113,14 @@ grpc_cc_test(
"//:grpc",
"//src/proto/grpc/testing/xds/v3:client_side_weighted_round_robin_proto",
"//src/proto/grpc/testing/xds/v3:cluster_proto",
+ "//src/proto/grpc/testing/xds/v3:pick_first_proto",
"//src/proto/grpc/testing/xds/v3:ring_hash_proto",
"//src/proto/grpc/testing/xds/v3:round_robin_proto",
"//src/proto/grpc/testing/xds/v3:typed_struct_proto",
"//src/proto/grpc/testing/xds/v3:udpa_typed_struct_proto",
"//src/proto/grpc/testing/xds/v3:wrr_locality_proto",
"//test/core/util:grpc_test_util",
+ "//test/core/util:scoped_env_var",
"//test/cpp/util:grpc_cli_utils",
],
)
diff --git a/test/core/xds/xds_lb_policy_registry_test.cc b/test/core/xds/xds_lb_policy_registry_test.cc
index c40c8254054..b193ad5a442 100644
--- a/test/core/xds/xds_lb_policy_registry_test.cc
+++ b/test/core/xds/xds_lb_policy_registry_test.cc
@@ -48,10 +48,12 @@
#include "src/proto/grpc/testing/xds/v3/client_side_weighted_round_robin.pb.h"
#include "src/proto/grpc/testing/xds/v3/cluster.pb.h"
#include "src/proto/grpc/testing/xds/v3/extension.pb.h"
+#include "src/proto/grpc/testing/xds/v3/pick_first.pb.h"
#include "src/proto/grpc/testing/xds/v3/ring_hash.pb.h"
#include "src/proto/grpc/testing/xds/v3/round_robin.pb.h"
#include "src/proto/grpc/testing/xds/v3/typed_struct.pb.h"
#include "src/proto/grpc/testing/xds/v3/wrr_locality.pb.h"
+#include "test/core/util/scoped_env_var.h"
#include "test/core/util/test_config.h"
namespace grpc_core {
@@ -62,6 +64,7 @@ using LoadBalancingPolicyProto =
::envoy::config::cluster::v3::LoadBalancingPolicy;
using ::envoy::extensions::load_balancing_policies::
client_side_weighted_round_robin::v3::ClientSideWeightedRoundRobin;
+using ::envoy::extensions::load_balancing_policies::pick_first::v3::PickFirst;
using ::envoy::extensions::load_balancing_policies::ring_hash::v3::RingHash;
using ::envoy::extensions::load_balancing_policies::round_robin::v3::RoundRobin;
using ::envoy::extensions::load_balancing_policies::wrr_locality::v3::
@@ -442,6 +445,56 @@ TEST(WrrLocality, UnsupportedChildPolicyTypeSkipped) {
"\"childPolicy\":[{\"round_robin\":{}}]}}");
}
+//
+// PickFirst
+//
+
+TEST(PickFirst, NoShuffle) {
+ ScopedExperimentalEnvVar env_var("GRPC_EXPERIMENTAL_PICKFIRST_LB_CONFIG");
+ LoadBalancingPolicyProto policy;
+ auto* lb_policy = policy.add_policies();
+ PickFirst pick_first;
+ pick_first.set_shuffle_address_list(false);
+ lb_policy->mutable_typed_extension_config()->mutable_typed_config()->PackFrom(
+ pick_first);
+ auto result = ConvertXdsPolicy(policy);
+ ASSERT_TRUE(result.ok()) << result.status();
+ EXPECT_EQ(*result, "{\"pick_first\":{\"shuffleAddressList\":false}}");
+}
+
+TEST(PickFirst, Shuffle) {
+ ScopedExperimentalEnvVar env_var("GRPC_EXPERIMENTAL_PICKFIRST_LB_CONFIG");
+ LoadBalancingPolicyProto policy;
+ auto* lb_policy = policy.add_policies();
+ PickFirst pick_first;
+ pick_first.set_shuffle_address_list(true);
+ lb_policy->mutable_typed_extension_config()->mutable_typed_config()->PackFrom(
+ pick_first);
+ auto result = ConvertXdsPolicy(policy);
+ ASSERT_TRUE(result.ok()) << result.status();
+ EXPECT_EQ(*result, "{\"pick_first\":{\"shuffleAddressList\":true}}");
+}
+
+TEST(PickFirst, ShuffleOmitted) {
+ ScopedExperimentalEnvVar env_var("GRPC_EXPERIMENTAL_PICKFIRST_LB_CONFIG");
+ LoadBalancingPolicyProto policy;
+ auto* lb_policy = policy.add_policies();
+ lb_policy->mutable_typed_extension_config()->mutable_typed_config()->PackFrom(
+ PickFirst());
+ auto result = ConvertXdsPolicy(policy);
+ ASSERT_TRUE(result.ok()) << result.status();
+ EXPECT_EQ(*result, "{\"pick_first\":{\"shuffleAddressList\":false}}");
+}
+
+TEST(PickFirst, EnvVarDisabled) {
+ LoadBalancingPolicyProto policy;
+ auto* lb_policy = policy.add_policies();
+ lb_policy->mutable_typed_extension_config()->mutable_typed_config()->PackFrom(
+ PickFirst());
+ auto result = ConvertXdsPolicy(policy);
+ ASSERT_FALSE(result.ok());
+}
+
//
// CustomPolicy
//
diff --git a/test/cpp/end2end/xds/BUILD b/test/cpp/end2end/xds/BUILD
index d31329f5e71..0341713b3b0 100644
--- a/test/cpp/end2end/xds/BUILD
+++ b/test/cpp/end2end/xds/BUILD
@@ -448,3 +448,30 @@ grpc_cc_test(
"//test/core/util:scoped_env_var",
],
)
+
+grpc_cc_test(
+ name = "xds_pick_first_end2end_test",
+ size = "large",
+ srcs = ["xds_pick_first_end2end_test.cc"],
+ external_deps = [
+ "gtest",
+ ],
+ linkstatic = True, # Fixes dyld error on MacOS
+ tags = [
+ "no_test_ios",
+ "no_windows",
+ "xds_end2end_test",
+ ], # TODO(jtattermusch): fix test on windows
+ deps = [
+ ":xds_end2end_test_lib",
+ "//:gpr",
+ "//:grpc",
+ "//:grpc++",
+ "//src/proto/grpc/testing/xds/v3:aggregate_cluster_proto",
+ "//src/proto/grpc/testing/xds/v3:pick_first_proto",
+ "//src/proto/grpc/testing/xds/v3:router_proto",
+ "//test/core/util:grpc_test_util",
+ "//test/core/util:scoped_env_var",
+ "//test/cpp/end2end:connection_attempt_injector",
+ ],
+)
diff --git a/test/cpp/end2end/xds/xds_pick_first_end2end_test.cc b/test/cpp/end2end/xds/xds_pick_first_end2end_test.cc
new file mode 100644
index 00000000000..4344c27a727
--- /dev/null
+++ b/test/cpp/end2end/xds/xds_pick_first_end2end_test.cc
@@ -0,0 +1,132 @@
+// Copyright 2017 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+#include "absl/strings/str_cat.h"
+
+#include
+#include
+
+#include "src/core/ext/filters/client_channel/backup_poller.h"
+#include "src/core/ext/filters/client_channel/lb_policy/xds/xds_channel_args.h"
+#include "src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h"
+#include "src/core/lib/address_utils/sockaddr_utils.h"
+#include "src/core/lib/config/config_vars.h"
+#include "src/core/lib/gprpp/env.h"
+#include "src/proto/grpc/testing/xds/v3/cluster.grpc.pb.h"
+#include "src/proto/grpc/testing/xds/v3/pick_first.pb.h"
+#include "test/core/util/scoped_env_var.h"
+#include "test/core/util/test_config.h"
+#include "test/cpp/end2end/connection_attempt_injector.h"
+#include "test/cpp/end2end/xds/xds_end2end_test_lib.h"
+
+namespace grpc {
+namespace testing {
+namespace {
+
+using ::envoy::extensions::load_balancing_policies::pick_first::v3::PickFirst;
+
+class PickFirstTest : public XdsEnd2endTest {
+ protected:
+ // Sends RPCs until one of them lands on a backend in the specified range, in
+ // which case it returns the index of that backend. Returns an error status if
+ // any of the RPCs fails.
+ absl::StatusOr WaitForAnyBackendHit(size_t start, size_t end) {
+ absl::StatusOr output;
+ SendRpcsUntil(DEBUG_LOCATION, [&](const RpcResult& result) -> bool {
+ if (!result.status.ok()) {
+ output = absl::Status(
+ static_cast(result.status.error_code()),
+ result.status.error_message());
+ return false;
+ }
+ for (size_t i = start; i < end; ++i) {
+ if (backends_[i]->backend_service()->request_count() > 0) {
+ backends_[i]->backend_service()->ResetCounters();
+ output = i;
+ return false;
+ }
+ }
+ return true;
+ });
+ return output;
+ }
+};
+
+// Run both with and without load reporting, just for test coverage.
+INSTANTIATE_TEST_SUITE_P(XdsTest, PickFirstTest,
+ ::testing::Values(XdsTestType()), &XdsTestType::Name);
+
+TEST_P(PickFirstTest, PickFirstConfigurationIsPropagated) {
+ grpc_core::testing::ScopedExperimentalEnvVar env_var(
+ "GRPC_EXPERIMENTAL_PICKFIRST_LB_CONFIG");
+ CreateAndStartBackends(6);
+ // Change cluster to use pick_first with shuffle option.
+ auto cluster = default_cluster_;
+ PickFirst pick_first;
+ pick_first.set_shuffle_address_list(true);
+ cluster.mutable_load_balancing_policy()
+ ->add_policies()
+ ->mutable_typed_extension_config()
+ ->mutable_typed_config()
+ ->PackFrom(pick_first);
+ balancer_->ads_service()->SetCdsResource(cluster);
+ size_t start_index = 0;
+ for (size_t i = 0; i < 100; ++i) {
+ // Update EDS resource. This will send a new address list update to the LB
+ // policy.
+ balancer_->ads_service()->SetEdsResource(BuildEdsResource(
+ EdsResourceArgs({{"locality0", CreateEndpointsForBackends(
+ start_index, start_index + 3)}})));
+ auto result = WaitForAnyBackendHit(start_index, start_index + 3);
+ ASSERT_TRUE(result.ok()) << result.status();
+ if (*result != start_index) return;
+ // Toggle between backends 0-2 and 3-5
+ start_index = 3 - start_index;
+ }
+ FAIL() << "did not choose a different backend";
+}
+} // namespace
+} // namespace testing
+} // namespace grpc
+
+int main(int argc, char** argv) {
+ grpc::testing::TestEnvironment env(&argc, argv);
+ ::testing::InitGoogleTest(&argc, argv);
+ // Make the backup poller poll very frequently in order to pick up
+ // updates from all the subchannels's FDs.
+ grpc_core::ConfigVars::Overrides overrides;
+ overrides.client_channel_backup_poll_interval_ms = 1;
+ grpc_core::ConfigVars::SetOverrides(overrides);
+#if TARGET_OS_IPHONE
+ // Workaround Apple CFStream bug
+ grpc_core::SetEnv("grpc_cfstream", "0");
+#endif
+ grpc_init();
+ grpc::testing::ConnectionAttemptInjector::Init();
+ const auto result = RUN_ALL_TESTS();
+ grpc_shutdown();
+ return result;
+}
diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal
index 246f6a7f140..3c6a5ab1e82 100644
--- a/tools/doxygen/Doxyfile.c++.internal
+++ b/tools/doxygen/Doxyfile.c++.internal
@@ -1465,6 +1465,8 @@ src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/client_side_
src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/client_side_weighted_round_robin/v3/client_side_weighted_round_robin.upb.h \
src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/common/v3/common.upb.c \
src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/common/v3/common.upb.h \
+src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/pick_first/v3/pick_first.upb.c \
+src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/pick_first/v3/pick_first.upb.h \
src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb.c \
src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb.h \
src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/wrr_locality/v3/wrr_locality.upb.c \
diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal
index 68cb19c969b..a185c6a0664 100644
--- a/tools/doxygen/Doxyfile.core.internal
+++ b/tools/doxygen/Doxyfile.core.internal
@@ -1241,6 +1241,8 @@ src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/client_side_
src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/client_side_weighted_round_robin/v3/client_side_weighted_round_robin.upb.h \
src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/common/v3/common.upb.c \
src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/common/v3/common.upb.h \
+src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/pick_first/v3/pick_first.upb.c \
+src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/pick_first/v3/pick_first.upb.h \
src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb.c \
src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb.h \
src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/wrr_locality/v3/wrr_locality.upb.c \
diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json
index a313470869c..47dc1ef856f 100644
--- a/tools/run_tests/generated/tests.json
+++ b/tools/run_tests/generated/tests.json
@@ -11317,6 +11317,28 @@
],
"uses_polling": false
},
+ {
+ "args": [],
+ "benchmark": false,
+ "ci_platforms": [
+ "linux",
+ "mac",
+ "posix"
+ ],
+ "cpu_cost": 1.0,
+ "exclude_configs": [],
+ "exclude_iomgrs": [],
+ "flaky": false,
+ "gtest": true,
+ "language": "c++",
+ "name": "xds_pick_first_end2end_test",
+ "platforms": [
+ "linux",
+ "mac",
+ "posix"
+ ],
+ "uses_polling": true
+ },
{
"args": [],
"benchmark": false,