grpc 1.82.0 → 1.83.0.pre1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (153) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +8 -5
  3. data/etc/roots.pem +10400 -3855
  4. data/include/grpc/grpc_audit_logging.h +2 -2
  5. data/include/grpc/grpc_security_constants.h +2 -0
  6. data/include/grpc/impl/channel_arg_names.h +23 -0
  7. data/src/core/call/call_filters.h +19 -3
  8. data/src/core/call/call_spine.h +4 -4
  9. data/src/core/call/client_call.cc +1 -1
  10. data/src/core/call/metadata.cc +7 -2
  11. data/src/core/call/server_call.cc +13 -3
  12. data/src/core/call/server_call.h +5 -3
  13. data/src/core/client_channel/backup_poller.cc +2 -17
  14. data/src/core/client_channel/client_channel.cc +17 -14
  15. data/src/core/client_channel/client_channel.h +3 -1
  16. data/src/core/client_channel/client_channel_filter.cc +11 -13
  17. data/src/core/client_channel/client_channel_service_config.cc +5 -13
  18. data/src/core/client_channel/direct_channel.cc +5 -1
  19. data/src/core/client_channel/direct_channel.h +3 -1
  20. data/src/core/config/experiment_env_var.cc +30 -0
  21. data/src/core/config/experiment_env_var.h +26 -0
  22. data/src/core/credentials/call/regional_access_boundary_fetcher.cc +6 -6
  23. data/src/core/credentials/transport/ssl/ssl_security_connector.cc +14 -2
  24. data/src/core/credentials/transport/tls/grpc_tls_certificate_selector.cc +172 -0
  25. data/src/core/credentials/transport/tls/grpc_tls_certificate_selector.h +103 -0
  26. data/src/core/credentials/transport/tls/load_system_roots_fallback.cc +3 -2
  27. data/src/core/credentials/transport/tls/load_system_roots_supported.cc +10 -3
  28. data/src/core/credentials/transport/tls/tls_security_connector.cc +14 -2
  29. data/src/core/credentials/transport/xds/xds_credentials.cc +4 -12
  30. data/src/core/ext/filters/rbac/rbac_service_config_parser.cc +2 -1
  31. data/src/core/ext/transport/chttp2/server/chttp2_server.cc +19 -13
  32. data/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +11 -9
  33. data/src/core/ext/transport/chttp2/transport/flow_control.cc +2 -2
  34. data/src/core/ext/transport/chttp2/transport/flow_control.h +3 -2
  35. data/src/core/ext/transport/chttp2/transport/frame.cc +58 -1
  36. data/src/core/ext/transport/chttp2/transport/frame.h +13 -1
  37. data/src/core/ext/transport/chttp2/transport/frame_rst_stream.cc +2 -4
  38. data/src/core/ext/transport/chttp2/transport/frame_security.cc +10 -1
  39. data/src/core/ext/transport/chttp2/transport/frame_security.h +2 -1
  40. data/src/core/ext/transport/chttp2/transport/goaway.cc +11 -1
  41. data/src/core/ext/transport/chttp2/transport/goaway.h +17 -1
  42. data/src/core/ext/transport/chttp2/transport/hpack_parser.cc +9 -0
  43. data/src/core/ext/transport/chttp2/transport/http2_client_transport.cc +117 -276
  44. data/src/core/ext/transport/chttp2/transport/http2_client_transport.h +44 -17
  45. data/src/core/ext/transport/chttp2/transport/http2_server_transport.cc +382 -496
  46. data/src/core/ext/transport/chttp2/transport/http2_server_transport.h +75 -77
  47. data/src/core/ext/transport/chttp2/transport/http2_settings.cc +1 -1
  48. data/src/core/ext/transport/chttp2/transport/http2_settings.h +30 -11
  49. data/src/core/ext/transport/chttp2/transport/http2_settings_promises.h +24 -9
  50. data/src/core/ext/transport/chttp2/transport/http2_transport.cc +26 -0
  51. data/src/core/ext/transport/chttp2/transport/http2_transport.h +2 -0
  52. data/src/core/ext/transport/chttp2/transport/internal.h +4 -0
  53. data/src/core/ext/transport/chttp2/transport/parsing.cc +3 -2
  54. data/src/core/ext/transport/chttp2/transport/ping_promise.cc +1 -1
  55. data/src/core/ext/transport/chttp2/transport/ping_rate_policy.cc +4 -10
  56. data/src/core/ext/transport/chttp2/transport/read_context.h +62 -20
  57. data/src/core/ext/transport/chttp2/transport/security_frame.h +1 -0
  58. data/src/core/ext/transport/chttp2/transport/stream.h +271 -120
  59. data/src/core/ext/transport/chttp2/transport/stream_data_queue.h +77 -61
  60. data/src/core/handshaker/security/secure_endpoint.cc +0 -13
  61. data/src/core/lib/channel/promise_based_filter.cc +77 -3
  62. data/src/core/lib/channel/promise_based_filter.h +238 -184
  63. data/src/core/lib/event_engine/extensions/receive_coalescing_extension.h +0 -4
  64. data/src/core/lib/event_engine/extensions/tcp_trace.h +1 -1
  65. data/src/core/lib/event_engine/posix_engine/posix_engine.cc +2 -12
  66. data/src/core/lib/event_engine/shim.cc +2 -16
  67. data/src/core/lib/event_engine/shim.h +0 -4
  68. data/src/core/lib/experiments/experiments.cc +51 -102
  69. data/src/core/lib/experiments/experiments.h +37 -59
  70. data/src/core/lib/iomgr/error.cc +3 -73
  71. data/src/core/lib/iomgr/error.h +8 -6
  72. data/src/core/lib/iomgr/error_cfstream.cc +1 -2
  73. data/src/core/lib/iomgr/ev_epoll1_linux.cc +2 -6
  74. data/src/core/lib/iomgr/ev_poll_posix.cc +2 -6
  75. data/src/core/lib/iomgr/tcp_posix.cc +2 -6
  76. data/src/core/lib/security/authorization/audit_logging.cc +2 -2
  77. data/src/core/lib/security/authorization/audit_logging.h +3 -3
  78. data/src/core/lib/security/authorization/grpc_authorization_engine.cc +11 -13
  79. data/src/core/lib/security/authorization/grpc_authorization_engine.h +1 -1
  80. data/src/core/lib/security/authorization/matchers.cc +20 -20
  81. data/src/core/lib/security/authorization/matchers.h +15 -16
  82. data/src/core/lib/security/authorization/rbac_policy.h +1 -1
  83. data/src/core/lib/security/authorization/stdout_logger.cc +3 -3
  84. data/src/core/lib/security/authorization/stdout_logger.h +6 -5
  85. data/src/core/lib/surface/call.cc +0 -8
  86. data/src/core/lib/surface/call.h +2 -0
  87. data/src/core/lib/surface/channel.cc +21 -2
  88. data/src/core/lib/surface/channel.h +14 -6
  89. data/src/core/lib/surface/filter_stack_call.cc +10 -29
  90. data/src/core/lib/surface/legacy_channel.cc +7 -7
  91. data/src/core/lib/surface/legacy_channel.h +3 -1
  92. data/src/core/lib/surface/version.cc +2 -2
  93. data/src/core/lib/transport/bdp_estimator.cc +13 -13
  94. data/src/core/lib/transport/bdp_estimator.h +9 -5
  95. data/src/core/lib/transport/error_utils.cc +26 -138
  96. data/src/core/lib/transport/promise_endpoint.h +2 -4
  97. data/src/core/load_balancing/grpclb/grpclb.cc +2 -1
  98. data/src/core/load_balancing/pick_first/pick_first.cc +33 -2
  99. data/src/core/load_balancing/pick_first/pick_first.h +6 -0
  100. data/src/core/load_balancing/ring_hash/ring_hash.cc +3 -10
  101. data/src/core/load_balancing/rls/rls.cc +2 -1
  102. data/src/core/load_balancing/weighted_round_robin/weighted_round_robin.cc +2 -7
  103. data/src/core/load_balancing/xds/cds.cc +80 -56
  104. data/src/core/load_balancing/xds/cds.h +21 -0
  105. data/src/core/mitigation_engine/mitigation.h +53 -0
  106. data/src/core/mitigation_engine/mitigation_provider.h +62 -0
  107. data/src/core/resolver/dns/dns_resolver_plugin.cc +1 -6
  108. data/src/core/resolver/xds/xds_resolver.cc +14 -11
  109. data/src/core/server/server.h +1 -4
  110. data/src/core/server/server_config_selector.h +5 -4
  111. data/src/core/server/server_config_selector_filter.cc +67 -80
  112. data/src/core/server/xds_server_config_fetcher.cc +681 -692
  113. data/src/core/server/xds_server_config_fetcher_legacy.cc +15 -12
  114. data/src/core/telemetry/call_tracer.cc +49 -2
  115. data/src/core/telemetry/call_tracer.h +1 -0
  116. data/src/core/telemetry/tcp_tracer.h +38 -0
  117. data/src/core/tsi/alts/handshaker/alts_handshaker_client.cc +1 -1
  118. data/src/core/tsi/ssl_telemetry_utils.cc +343 -0
  119. data/src/core/tsi/ssl_telemetry_utils.h +74 -0
  120. data/src/core/tsi/ssl_transport_security.cc +577 -301
  121. data/src/core/tsi/ssl_transport_security.h +22 -6
  122. data/src/core/tsi/ssl_transport_security_utils.cc +2 -0
  123. data/src/core/tsi/transport_security.h +7 -0
  124. data/src/core/util/http_client/httpcli.cc +1 -4
  125. data/src/core/util/http_client/httpcli_security_connector.cc +2 -1
  126. data/src/core/util/status_helper.cc +71 -192
  127. data/src/core/util/status_helper.h +16 -21
  128. data/src/core/xds/grpc/file_watcher_certificate_provider_factory.cc +2 -11
  129. data/src/core/xds/grpc/xds_bootstrap_grpc.cc +2 -7
  130. data/src/core/xds/grpc/xds_cluster_parser.cc +5 -16
  131. data/src/core/xds/grpc/xds_common_types.cc +94 -38
  132. data/src/core/xds/grpc/xds_common_types.h +33 -18
  133. data/src/core/xds/grpc/xds_common_types_parser.cc +168 -100
  134. data/src/core/xds/grpc/xds_common_types_parser.h +18 -1
  135. data/src/core/xds/grpc/xds_endpoint_parser.cc +6 -17
  136. data/src/core/xds/grpc/xds_http_filter_registry.cc +2 -10
  137. data/src/core/xds/grpc/xds_http_rbac_filter.cc +3 -12
  138. data/src/core/xds/grpc/xds_metadata_parser.cc +0 -2
  139. data/src/core/xds/grpc/xds_route_config_parser.cc +7 -11
  140. data/src/core/xds/grpc/xds_routing.cc +113 -82
  141. data/src/core/xds/grpc/xds_routing.h +70 -20
  142. data/src/core/xds/grpc/xds_server_grpc.cc +22 -13
  143. data/src/core/xds/grpc/xds_server_grpc.h +16 -2
  144. data/src/core/xds/grpc/xds_server_grpc_interface.h +10 -0
  145. data/src/core/xds/grpc/xds_transport_grpc.cc +123 -18
  146. data/src/core/xds/grpc/xds_transport_grpc.h +28 -4
  147. data/src/core/xds/xds_client/lrs_client.cc +3 -7
  148. data/src/core/xds/xds_client/xds_bootstrap.cc +4 -16
  149. data/src/core/xds/xds_client/xds_client.cc +2 -15
  150. data/src/core/xds/xds_client/xds_transport.h +3 -0
  151. data/src/ruby/lib/grpc/version.rb +1 -1
  152. data/src/ruby/pb/src/proto/grpc/testing/messages_pb.rb +1 -1
  153. metadata +9 -1
@@ -63,159 +63,47 @@ void grpc_error_get_status(grpc_error_handle error,
63
63
  grpc_status_code* code, std::string* message,
64
64
  Http2ErrorCode* http_error,
65
65
  const char** error_string) {
66
- if (grpc_core::IsErrorFlattenEnabled()) {
67
- auto http_error_code = GetHttp2Error(error);
68
- if (code != nullptr) {
69
- // If the top-level status code is UNKNOWN and there is an HTTP2 error
70
- // code attribute set, convert from that. Otherwise, use the top-level
71
- // status code.
72
- if (error.code() == absl::StatusCode::kUnknown &&
73
- http_error_code.has_value()) {
74
- *code = grpc_http2_error_to_grpc_status(*http_error_code, deadline);
75
- } else {
76
- *code = static_cast<grpc_status_code>(error.code());
77
- }
78
- }
79
- if (message != nullptr) *message = std::string(error.message());
80
- if (error_string != nullptr && !error.ok()) {
81
- *error_string = gpr_strdup(grpc_core::StatusToString(error).c_str());
82
- }
83
- if (http_error != nullptr) {
84
- // If the HTTP2 error code attribute is present, use it. Otherwise,
85
- // if the status code is something other than UNKNOWN, convert from
86
- // that. Otherwise, set a default based on whether the status
87
- // code is OK.
88
- if (http_error_code.has_value()) {
89
- *http_error = *http_error_code;
90
- } else if (error.code() != absl::StatusCode::kUnknown) {
91
- *http_error = grpc_status_to_http2_error(
92
- static_cast<grpc_status_code>(error.code()));
93
- } else {
94
- *http_error = error.ok() ? Http2ErrorCode::kNoError
95
- : Http2ErrorCode::kInternalError;
96
- }
97
- }
98
- return;
99
- }
100
-
101
- // Fast path: We expect no error.
102
- if (GPR_LIKELY(error.ok())) {
103
- if (code != nullptr) *code = GRPC_STATUS_OK;
104
- if (message != nullptr) {
105
- // Normally, we call grpc_error_get_str(
106
- // error, grpc_core::StatusStrProperty::kGrpcMessage, message).
107
- // We can fastpath since we know that:
108
- // 1) Error is null
109
- // 2) which == grpc_core::StatusStrProperty::kGrpcMessage
110
- // 3) The resulting message is statically known.
111
- // 4) Said resulting message is "".
112
- // This means 3 movs, instead of 10s of instructions and a strlen.
113
- *message = "";
114
- }
115
- if (http_error != nullptr) {
116
- *http_error = Http2ErrorCode::kNoError;
66
+ auto http_error_code = GetHttp2Error(error);
67
+ if (code != nullptr) {
68
+ // If the top-level status code is UNKNOWN and there is an HTTP2 error
69
+ // code attribute set, convert from that. Otherwise, use the top-level
70
+ // status code.
71
+ if (error.code() == absl::StatusCode::kUnknown &&
72
+ http_error_code.has_value()) {
73
+ *code = grpc_http2_error_to_grpc_status(*http_error_code, deadline);
74
+ } else {
75
+ *code = static_cast<grpc_status_code>(error.code());
117
76
  }
118
- return;
119
77
  }
120
-
121
- // Start with the parent error and recurse through the tree of children
122
- // until we find the first one that has a status code.
123
- grpc_error_handle found_error = recursively_find_error_with_field(
124
- error, grpc_core::StatusIntProperty::kRpcStatus);
125
- if (found_error.ok()) {
126
- /// If no grpc-status exists, retry through the tree to find a http2 error
127
- /// code
128
- found_error = recursively_find_error_with_field(
129
- error, grpc_core::StatusIntProperty::kHttp2Error);
130
- }
131
-
132
- // If we found an error with a status code above, use that; otherwise,
133
- // fall back to using the parent error.
134
- if (found_error.ok()) found_error = error;
135
-
136
- grpc_status_code status = GRPC_STATUS_UNKNOWN;
137
- intptr_t integer;
138
- if (grpc_error_get_int(found_error, grpc_core::StatusIntProperty::kRpcStatus,
139
- &integer)) {
140
- status = static_cast<grpc_status_code>(integer);
141
- } else if (grpc_error_get_int(found_error,
142
- grpc_core::StatusIntProperty::kHttp2Error,
143
- &integer)) {
144
- status = grpc_http2_error_to_grpc_status(
145
- static_cast<Http2ErrorCode>(integer), deadline);
146
- } else {
147
- status = static_cast<grpc_status_code>(found_error.code());
148
- }
149
- if (code != nullptr) *code = status;
150
-
151
- if (error_string != nullptr && status != GRPC_STATUS_OK) {
78
+ if (message != nullptr) *message = std::string(error.message());
79
+ if (error_string != nullptr && !error.ok()) {
152
80
  *error_string = gpr_strdup(grpc_core::StatusToString(error).c_str());
153
81
  }
154
-
155
82
  if (http_error != nullptr) {
156
- if (grpc_error_get_int(
157
- found_error, grpc_core::StatusIntProperty::kHttp2Error, &integer)) {
158
- *http_error = static_cast<Http2ErrorCode>(integer);
159
- } else if (grpc_error_get_int(found_error,
160
- grpc_core::StatusIntProperty::kRpcStatus,
161
- &integer)) {
162
- *http_error =
163
- grpc_status_to_http2_error(static_cast<grpc_status_code>(integer));
83
+ // If the HTTP2 error code attribute is present, use it. Otherwise,
84
+ // if the status code is something other than UNKNOWN, convert from
85
+ // that. Otherwise, set a default based on whether the status
86
+ // code is OK.
87
+ if (http_error_code.has_value()) {
88
+ *http_error = *http_error_code;
89
+ } else if (error.code() != absl::StatusCode::kUnknown) {
90
+ *http_error = grpc_status_to_http2_error(
91
+ static_cast<grpc_status_code>(error.code()));
164
92
  } else {
165
- *http_error = found_error.ok() ? Http2ErrorCode::kNoError
166
- : Http2ErrorCode::kInternalError;
167
- }
168
- }
169
-
170
- // If the error has a status message, use it. Otherwise, fall back to
171
- // the error description.
172
- if (message != nullptr) {
173
- if (!grpc_error_get_str(
174
- found_error, grpc_core::StatusStrProperty::kGrpcMessage, message)) {
175
- *message = found_error.message().empty()
176
- ? grpc_core::StatusToString(error)
177
- : std::string(found_error.message());
93
+ *http_error = error.ok() ? Http2ErrorCode::kNoError
94
+ : Http2ErrorCode::kInternalError;
178
95
  }
179
96
  }
180
97
  }
181
98
 
182
99
  absl::Status grpc_error_to_absl_status(grpc_error_handle error) {
183
- if (grpc_core::IsErrorFlattenEnabled()) return error;
184
- grpc_status_code status;
185
- // TODO(yashykt): This should be updated once we decide on how to use the
186
- // absl::Status payload to capture all the contents of grpc_error.
187
- std::string message;
188
- grpc_error_get_status(error, grpc_core::Timestamp::InfFuture(), &status,
189
- &message, nullptr /* http_error */,
190
- nullptr /* error_string */);
191
- return absl::Status(static_cast<absl::StatusCode>(status), message);
100
+ return error;
192
101
  }
193
102
 
194
103
  grpc_error_handle absl_status_to_grpc_error(absl::Status status) {
195
- if (grpc_core::IsErrorFlattenEnabled()) return status;
196
- // Special error checks
197
- if (status.ok()) {
198
- return absl::OkStatus();
199
- }
200
- return grpc_error_set_int(GRPC_ERROR_CREATE(status.message()),
201
- grpc_core::StatusIntProperty::kRpcStatus,
202
- static_cast<grpc_status_code>(status.code()));
104
+ return status;
203
105
  }
204
106
 
205
107
  bool grpc_error_has_clear_grpc_status(grpc_error_handle error) {
206
- if (grpc_core::IsErrorFlattenEnabled()) {
207
- return error.code() != absl::StatusCode::kUnknown;
208
- }
209
- intptr_t unused;
210
- if (grpc_error_get_int(error, grpc_core::StatusIntProperty::kRpcStatus,
211
- &unused)) {
212
- return true;
213
- }
214
- std::vector<absl::Status> children = grpc_core::StatusGetChildren(error);
215
- for (const absl::Status& child : children) {
216
- if (grpc_error_has_clear_grpc_status(child)) {
217
- return true;
218
- }
219
- }
220
- return false;
108
+ return error.code() != absl::StatusCode::kUnknown;
221
109
  }
@@ -222,14 +222,12 @@ class PromiseEndpoint {
222
222
  });
223
223
  }
224
224
 
225
- // Enables RPC receive coalescing and alignment of memory holding received
226
- // RPCs.
227
- void EnforceRxMemoryAlignmentAndCoalescing() {
225
+ // Enables RPC receive coalescing and memory alignment for received RPCs.
226
+ void EnableRpcReceiveCoalescing() {
228
227
  auto* ext = grpc_event_engine::experimental::QueryExtension<
229
228
  grpc_event_engine::experimental::ReceiveCoalescingExtension>(
230
229
  endpoint_.get());
231
230
  if (ext != nullptr) {
232
- ext->EnforceRxMemoryAlignment();
233
231
  ext->EnableRpcReceiveCoalescing();
234
232
  }
235
233
  }
@@ -880,7 +880,8 @@ GrpcLb::BalancerCallState::BalancerCallState(
880
880
  /*parent_call=*/nullptr, GRPC_PROPAGATE_DEFAULTS,
881
881
  /*cq=*/nullptr, grpclb_policy_->interested_parties(),
882
882
  Slice::FromStaticString("/grpc.lb.v1.LoadBalancer/BalanceLoad"),
883
- /*authority=*/std::nullopt, deadline, /*registered_method=*/true);
883
+ /*authority=*/std::nullopt, deadline, /*registered_method=*/true,
884
+ /*arena_init_function=*/std::nullopt);
884
885
  // Init the LB call request payload.
885
886
  upb::Arena arena;
886
887
  grpc_slice request_payload_slice = GrpcLbRequestCreate(
@@ -23,6 +23,7 @@
23
23
  #include <inttypes.h>
24
24
  #include <string.h>
25
25
 
26
+ #include <cmath>
26
27
  #include <memory>
27
28
  #include <optional>
28
29
  #include <set>
@@ -32,6 +33,7 @@
32
33
  #include <vector>
33
34
 
34
35
  #include "src/core/config/core_configuration.h"
36
+ #include "src/core/config/experiment_env_var.h"
35
37
  #include "src/core/lib/address_utils/sockaddr_utils.h"
36
38
  #include "src/core/lib/channel/channel_args.h"
37
39
  #include "src/core/lib/debug/trace.h"
@@ -538,8 +540,33 @@ absl::Status PickFirst::UpdateLocked(UpdateArgs args) {
538
540
  // Shuffle the list if needed.
539
541
  auto config = static_cast<PickFirstConfig*>(args.config.get());
540
542
  if (config->shuffle_addresses()) {
541
- SharedBitGen g;
542
- absl::c_shuffle(endpoints, g);
543
+ if (PfWeightedShufflingEnabled()) {
544
+ struct WeightedEndpoint {
545
+ EndpointAddresses endpoint;
546
+ double key;
547
+ };
548
+ std::vector<WeightedEndpoint> weighted_endpoints;
549
+ weighted_endpoints.reserve(endpoints.size());
550
+ SharedBitGen g;
551
+ for (auto& endpoint : endpoints) {
552
+ double e = absl::Exponential<double>(g);
553
+ int weight_arg =
554
+ endpoint.args().GetInt(GRPC_ARG_ADDRESS_WEIGHT).value_or(1);
555
+ double weight = weight_arg <= 0 ? 1.0 : weight_arg;
556
+ double key = (weight == 1.0) ? e : (e / weight);
557
+ weighted_endpoints.push_back({std::move(endpoint), key});
558
+ }
559
+ std::sort(weighted_endpoints.begin(), weighted_endpoints.end(),
560
+ [](const WeightedEndpoint& a, const WeightedEndpoint& b) {
561
+ return a.key < b.key;
562
+ });
563
+ for (size_t i = 0; i < weighted_endpoints.size(); ++i) {
564
+ endpoints[i] = std::move(weighted_endpoints[i].endpoint);
565
+ }
566
+ } else {
567
+ SharedBitGen g;
568
+ absl::c_shuffle(endpoints, g);
569
+ }
543
570
  }
544
571
  // Flatten the list so that we have one address per endpoint.
545
572
  // While we're iterating, also determine the desired address family
@@ -1159,6 +1186,10 @@ class PickFirstFactory final : public LoadBalancingPolicyFactory {
1159
1186
 
1160
1187
  } // namespace
1161
1188
 
1189
+ bool PfWeightedShufflingEnabled() {
1190
+ return IsExperimentEnvVarEnabled("GRPC_EXPERIMENTAL_PF_WEIGHTED_SHUFFLING");
1191
+ }
1192
+
1162
1193
  void RegisterPickFirstLbPolicy(CoreConfiguration::Builder* builder) {
1163
1194
  builder->lb_policy_registry()->RegisterLoadBalancingPolicyFactory(
1164
1195
  std::make_unique<PickFirstFactory>());
@@ -33,4 +33,10 @@
33
33
  #define GRPC_ARG_INTERNAL_PICK_FIRST_OMIT_STATUS_MESSAGE_PREFIX \
34
34
  GRPC_ARG_NO_SUBCHANNEL_PREFIX "pick_first_omit_status_message_prefix"
35
35
 
36
+ namespace grpc_core {
37
+
38
+ bool PfWeightedShufflingEnabled();
39
+
40
+ } // namespace grpc_core
41
+
36
42
  #endif // GRPC_SRC_CORE_LOAD_BALANCING_PICK_FIRST_PICK_FIRST_H
@@ -34,6 +34,7 @@
34
34
 
35
35
  #include "src/core/client_channel/client_channel_internal.h"
36
36
  #include "src/core/config/core_configuration.h"
37
+ #include "src/core/config/experiment_env_var.h"
37
38
  #include "src/core/lib/address_utils/sockaddr_utils.h"
38
39
  #include "src/core/lib/channel/channel_args.h"
39
40
  #include "src/core/lib/debug/trace.h"
@@ -51,7 +52,6 @@
51
52
  #include "src/core/resolver/endpoint_addresses.h"
52
53
  #include "src/core/util/crash.h"
53
54
  #include "src/core/util/debug_location.h"
54
- #include "src/core/util/env.h"
55
55
  #include "src/core/util/grpc_check.h"
56
56
  #include "src/core/util/json/json.h"
57
57
  #include "src/core/util/orphanable.h"
@@ -81,19 +81,12 @@ namespace {
81
81
 
82
82
  constexpr absl::string_view kRingHash = "ring_hash_experimental";
83
83
 
84
- bool XdsRingHashSetRequestHashKeyEnabled() {
85
- auto value = GetEnv("GRPC_EXPERIMENTAL_RING_HASH_SET_REQUEST_HASH_KEY");
86
- if (!value.has_value()) return false;
87
- bool parsed_value;
88
- bool parse_succeeded = gpr_parse_bool_value(value->c_str(), &parsed_value);
89
- return parse_succeeded && parsed_value;
90
- }
91
-
92
84
  class RingHashJsonArgs final : public JsonArgs {
93
85
  public:
94
86
  bool IsEnabled(absl::string_view key) const override {
95
87
  if (key == "request_hash_header") {
96
- return XdsRingHashSetRequestHashKeyEnabled();
88
+ return IsExperimentEnvVarEnabled(
89
+ "GRPC_EXPERIMENTAL_RING_HASH_SET_REQUEST_HASH_KEY");
97
90
  }
98
91
  return true;
99
92
  }
@@ -1680,7 +1680,8 @@ void RlsLb::RlsRequest::StartCallLocked() {
1680
1680
  /*parent_call=*/nullptr, GRPC_PROPAGATE_DEFAULTS, /*cq=*/nullptr,
1681
1681
  lb_policy_->interested_parties(),
1682
1682
  Slice::FromStaticString(kRlsRequestPath), /*authority=*/std::nullopt,
1683
- deadline_, /*registered_method=*/true);
1683
+ deadline_, /*registered_method=*/true,
1684
+ /*arena_init_function=*/std::nullopt);
1684
1685
  grpc_op ops[6];
1685
1686
  memset(ops, 0, sizeof(ops));
1686
1687
  grpc_op* op = ops;
@@ -36,6 +36,7 @@
36
36
 
37
37
  #include "src/core/client_channel/client_channel_service_config.h"
38
38
  #include "src/core/config/core_configuration.h"
39
+ #include "src/core/config/experiment_env_var.h"
39
40
  #include "src/core/lib/channel/channel_args.h"
40
41
  #include "src/core/lib/debug/trace.h"
41
42
  #include "src/core/lib/experiments/experiments.h"
@@ -55,7 +56,6 @@
55
56
  #include "src/core/telemetry/stats.h"
56
57
  #include "src/core/telemetry/stats_data.h"
57
58
  #include "src/core/util/debug_location.h"
58
- #include "src/core/util/env.h"
59
59
  #include "src/core/util/grpc_check.h"
60
60
  #include "src/core/util/json/json.h"
61
61
  #include "src/core/util/json/json_args.h"
@@ -64,7 +64,6 @@
64
64
  #include "src/core/util/ref_counted.h"
65
65
  #include "src/core/util/ref_counted_ptr.h"
66
66
  #include "src/core/util/shared_bit_gen.h"
67
- #include "src/core/util/string.h"
68
67
  #include "src/core/util/sync.h"
69
68
  #include "src/core/util/time.h"
70
69
  #include "src/core/util/validation_errors.h"
@@ -82,11 +81,7 @@
82
81
  namespace grpc_core {
83
82
 
84
83
  bool WrrCustomMetricsEnabled() {
85
- auto value = GetEnv("GRPC_EXPERIMENTAL_WRR_CUSTOM_METRICS");
86
- if (!value.has_value()) return false;
87
- bool parsed_value;
88
- bool parse_succeeded = gpr_parse_bool_value(value->c_str(), &parsed_value);
89
- return parse_succeeded && parsed_value;
84
+ return IsExperimentEnvVarEnabled("GRPC_EXPERIMENTAL_WRR_CUSTOM_METRICS");
90
85
  }
91
86
 
92
87
  namespace {
@@ -19,7 +19,6 @@
19
19
  #include <grpc/grpc_security.h>
20
20
  #include <grpc/impl/connectivity_state.h>
21
21
  #include <grpc/support/json.h>
22
- #include <grpc/support/port_platform.h>
23
22
 
24
23
  #include <algorithm>
25
24
  #include <map>
@@ -34,6 +33,7 @@
34
33
 
35
34
  #include "src/core/client_channel/client_channel_internal.h"
36
35
  #include "src/core/config/core_configuration.h"
36
+ #include "src/core/config/experiment_env_var.h"
37
37
  #include "src/core/lib/channel/channel_args.h"
38
38
  #include "src/core/lib/debug/trace.h"
39
39
  #include "src/core/lib/iomgr/pollset_set.h"
@@ -43,10 +43,10 @@
43
43
  #include "src/core/load_balancing/lb_policy_factory.h"
44
44
  #include "src/core/load_balancing/lb_policy_registry.h"
45
45
  #include "src/core/load_balancing/outlier_detection/outlier_detection.h"
46
+ #include "src/core/load_balancing/pick_first/pick_first.h"
46
47
  #include "src/core/load_balancing/xds/xds_channel_args.h"
47
48
  #include "src/core/resolver/xds/xds_dependency_manager.h"
48
49
  #include "src/core/util/debug_location.h"
49
- #include "src/core/util/env.h"
50
50
  #include "src/core/util/grpc_check.h"
51
51
  #include "src/core/util/json/json.h"
52
52
  #include "src/core/util/json/json_args.h"
@@ -165,11 +165,8 @@ namespace {
165
165
 
166
166
  // TODO(roth): Remove this after the 1.63 release.
167
167
  bool XdsAggregateClusterBackwardCompatibilityEnabled() {
168
- auto value = GetEnv("GRPC_XDS_AGGREGATE_CLUSTER_BACKWARD_COMPAT");
169
- if (!value.has_value()) return false;
170
- bool parsed_value;
171
- bool parse_succeeded = gpr_parse_bool_value(value->c_str(), &parsed_value);
172
- return parse_succeeded && parsed_value;
168
+ return IsExperimentEnvVarEnabled(
169
+ "GRPC_XDS_AGGREGATE_CLUSTER_BACKWARD_COMPAT");
173
170
  }
174
171
 
175
172
  constexpr absl::string_view kCds = "cds_experimental";
@@ -317,54 +314,6 @@ std::string MakeChildPolicyName(absl::string_view cluster,
317
314
  "}");
318
315
  }
319
316
 
320
- class PriorityEndpointIterator final : public EndpointAddressesIterator {
321
- public:
322
- PriorityEndpointIterator(
323
- RefCountedStringValue cluster_name, bool use_http_connect,
324
- std::shared_ptr<const XdsEndpointResource> endpoints,
325
- std::vector<size_t /*child_number*/> priority_child_numbers)
326
- : cluster_name_(std::move(cluster_name)),
327
- use_http_connect_(use_http_connect),
328
- endpoints_(std::move(endpoints)),
329
- priority_child_numbers_(std::move(priority_child_numbers)) {}
330
-
331
- void ForEach(absl::FunctionRef<void(const EndpointAddresses&)> callback)
332
- const override {
333
- const auto& priority_list = GetUpdatePriorityList(endpoints_.get());
334
- for (size_t priority = 0; priority < priority_list.size(); ++priority) {
335
- const auto& priority_entry = priority_list[priority];
336
- std::string priority_child_name = MakeChildPolicyName(
337
- cluster_name_.as_string_view(), priority_child_numbers_[priority]);
338
- for (const auto& [locality_name, locality] : priority_entry.localities) {
339
- std::vector<RefCountedStringValue> hierarchical_path = {
340
- RefCountedStringValue(priority_child_name),
341
- locality_name->human_readable_string()};
342
- auto hierarchical_path_attr =
343
- MakeRefCounted<HierarchicalPathArg>(std::move(hierarchical_path));
344
- for (const auto& endpoint : locality.endpoints) {
345
- uint32_t endpoint_weight =
346
- locality.lb_weight *
347
- endpoint.args().GetInt(GRPC_ARG_ADDRESS_WEIGHT).value_or(1);
348
- ChannelArgs args =
349
- endpoint.args()
350
- .SetObject(hierarchical_path_attr)
351
- .Set(GRPC_ARG_ADDRESS_WEIGHT, endpoint_weight)
352
- .SetObject(locality_name->Ref())
353
- .Set(GRPC_ARG_XDS_LOCALITY_WEIGHT, locality.lb_weight);
354
- if (!use_http_connect_) args = args.Remove(GRPC_ARG_XDS_HTTP_PROXY);
355
- callback(EndpointAddresses(endpoint.addresses(), args));
356
- }
357
- }
358
- }
359
- }
360
-
361
- private:
362
- RefCountedStringValue cluster_name_;
363
- bool use_http_connect_;
364
- std::shared_ptr<const XdsEndpointResource> endpoints_;
365
- std::vector<size_t /*child_number*/> priority_child_numbers_;
366
- };
367
-
368
317
  absl::Status CdsLb::UpdateLocked(UpdateArgs args) {
369
318
  // Get new config.
370
319
  auto new_config = args.config.TakeAsSubclass<CdsLbConfig>();
@@ -491,7 +440,7 @@ absl::Status CdsLb::UpdateLocked(UpdateArgs args) {
491
440
  // Compute new child numbers.
492
441
  child_name_state_.Update(old_cluster_config, endpoint_config);
493
442
  // Populate addresses and resolution_note for child policy.
494
- update_args.addresses = std::make_shared<PriorityEndpointIterator>(
443
+ update_args.addresses = std::make_shared<CdsPriorityEndpointIterator>(
495
444
  cluster_name_, new_cluster_config->cluster->use_http_connect,
496
445
  endpoint_config.endpoints,
497
446
  child_name_state_.priority_child_numbers());
@@ -752,6 +701,81 @@ class CdsLbFactory final : public LoadBalancingPolicyFactory {
752
701
 
753
702
  } // namespace
754
703
 
704
+ CdsPriorityEndpointIterator::CdsPriorityEndpointIterator(
705
+ RefCountedStringValue cluster_name, bool use_http_connect,
706
+ std::shared_ptr<const XdsEndpointResource> endpoints,
707
+ std::vector<size_t /*child_number*/> priority_child_numbers)
708
+ : cluster_name_(std::move(cluster_name)),
709
+ use_http_connect_(use_http_connect),
710
+ endpoints_(std::move(endpoints)),
711
+ priority_child_numbers_(std::move(priority_child_numbers)) {}
712
+
713
+ void CdsPriorityEndpointIterator::ForEach(
714
+ absl::FunctionRef<void(const EndpointAddresses&)> callback) const {
715
+ const auto& priority_list = GetUpdatePriorityList(endpoints_.get());
716
+ bool weighted_shuffling_enabled = PfWeightedShufflingEnabled();
717
+ for (size_t priority = 0; priority < priority_list.size(); ++priority) {
718
+ const auto& priority_entry = priority_list[priority];
719
+ std::string priority_child_name = MakeChildPolicyName(
720
+ cluster_name_.as_string_view(), priority_child_numbers_[priority]);
721
+ uint64_t locality_weight_sum = 0;
722
+ if (weighted_shuffling_enabled) {
723
+ for (const auto& [_, locality] : priority_entry.localities) {
724
+ locality_weight_sum += locality.lb_weight;
725
+ }
726
+ // This should never happen because the resource parsing code will strip
727
+ // out any localities with weight 0. However, we check this defensively.
728
+ if (locality_weight_sum == 0) locality_weight_sum = 1;
729
+ }
730
+ for (const auto& [locality_name, locality] : priority_entry.localities) {
731
+ uint32_t normalized_locality_weight = 1;
732
+ uint64_t endpoint_weight_sum = 0;
733
+ if (weighted_shuffling_enabled) {
734
+ normalized_locality_weight =
735
+ (locality.lb_weight * (uint64_t(1) << 31)) / locality_weight_sum;
736
+ for (const auto& endpoint : locality.endpoints) {
737
+ int weight =
738
+ endpoint.args().GetInt(GRPC_ARG_ADDRESS_WEIGHT).value_or(1);
739
+ endpoint_weight_sum += weight <= 0 ? 1 : weight;
740
+ }
741
+ // This should never happen because the resource validation code will
742
+ // reject the resource if any endpoint has weight 0. However, we check
743
+ // this defensively.
744
+ if (endpoint_weight_sum == 0) endpoint_weight_sum = 1;
745
+ }
746
+ std::vector<RefCountedStringValue> hierarchical_path = {
747
+ RefCountedStringValue(priority_child_name),
748
+ locality_name->human_readable_string()};
749
+ auto hierarchical_path_attr =
750
+ MakeRefCounted<HierarchicalPathArg>(std::move(hierarchical_path));
751
+ for (const auto& endpoint : locality.endpoints) {
752
+ int weight_arg =
753
+ endpoint.args().GetInt(GRPC_ARG_ADDRESS_WEIGHT).value_or(1);
754
+ uint32_t raw_endpoint_weight = weight_arg <= 0 ? 1 : weight_arg;
755
+ uint32_t endpoint_weight;
756
+ if (weighted_shuffling_enabled) {
757
+ uint32_t normalized_endpoint_weight =
758
+ (raw_endpoint_weight * (uint64_t(1) << 31)) / endpoint_weight_sum;
759
+ endpoint_weight = (uint64_t(normalized_locality_weight) *
760
+ normalized_endpoint_weight) >>
761
+ 31;
762
+ if (endpoint_weight == 0) endpoint_weight = 1;
763
+ } else {
764
+ endpoint_weight = locality.lb_weight * raw_endpoint_weight;
765
+ }
766
+ ChannelArgs args =
767
+ endpoint.args()
768
+ .SetObject(hierarchical_path_attr)
769
+ .Set(GRPC_ARG_ADDRESS_WEIGHT, endpoint_weight)
770
+ .SetObject(locality_name->Ref())
771
+ .Set(GRPC_ARG_XDS_LOCALITY_WEIGHT, locality.lb_weight);
772
+ if (!use_http_connect_) args = args.Remove(GRPC_ARG_XDS_HTTP_PROXY);
773
+ callback(EndpointAddresses(endpoint.addresses(), args));
774
+ }
775
+ }
776
+ }
777
+ }
778
+
755
779
  void RegisterCdsLbPolicy(CoreConfiguration::Builder* builder) {
756
780
  builder->lb_policy_registry()->RegisterLoadBalancingPolicyFactory(
757
781
  std::make_unique<CdsLbFactory>());
@@ -17,9 +17,13 @@
17
17
  #ifndef GRPC_SRC_CORE_LOAD_BALANCING_XDS_CDS_H
18
18
  #define GRPC_SRC_CORE_LOAD_BALANCING_XDS_CDS_H
19
19
 
20
+ #include <memory>
20
21
  #include <vector>
21
22
 
23
+ #include "src/core/resolver/endpoint_addresses.h"
22
24
  #include "src/core/resolver/xds/xds_config.h"
25
+ #include "src/core/util/ref_counted_string.h"
26
+ #include "src/core/xds/grpc/xds_endpoint.h"
23
27
 
24
28
  namespace grpc_core {
25
29
 
@@ -53,6 +57,23 @@ class CdsChildNameState {
53
57
  size_t next_available_child_number_ = 0;
54
58
  };
55
59
 
60
+ class CdsPriorityEndpointIterator final : public EndpointAddressesIterator {
61
+ public:
62
+ CdsPriorityEndpointIterator(
63
+ RefCountedStringValue cluster_name, bool use_http_connect,
64
+ std::shared_ptr<const XdsEndpointResource> endpoints,
65
+ std::vector<size_t /*child_number*/> priority_child_numbers);
66
+
67
+ void ForEach(absl::FunctionRef<void(const EndpointAddresses&)> callback)
68
+ const override;
69
+
70
+ private:
71
+ RefCountedStringValue cluster_name_;
72
+ bool use_http_connect_;
73
+ std::shared_ptr<const XdsEndpointResource> endpoints_;
74
+ std::vector<size_t /*child_number*/> priority_child_numbers_;
75
+ };
76
+
56
77
  } // namespace grpc_core
57
78
 
58
79
  #endif // GRPC_SRC_CORE_LOAD_BALANCING_XDS_CDS_H
@@ -0,0 +1,53 @@
1
+ //
2
+ //
3
+ // Copyright 2026 gRPC authors.
4
+ //
5
+ // Licensed under the Apache License, Version 2.0 (the "License");
6
+ // you may not use this file except in compliance with the License.
7
+ // You may obtain a copy of the License at
8
+ //
9
+ // http://www.apache.org/licenses/LICENSE-2.0
10
+ //
11
+ // Unless required by applicable law or agreed to in writing, software
12
+ // distributed under the License is distributed on an "AS IS" BASIS,
13
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ // See the License for the specific language governing permissions and
15
+ // limitations under the License.
16
+ //
17
+ //
18
+
19
+ #ifndef GRPC_SRC_CORE_MITIGATION_ENGINE_MITIGATION_H
20
+ #define GRPC_SRC_CORE_MITIGATION_ENGINE_MITIGATION_H
21
+
22
+ #include <optional>
23
+
24
+ #include "src/core/call/metadata_batch.h"
25
+ #include "src/core/mitigation_engine/mitigation_engine.h"
26
+ #include "src/core/util/ref_counted.h"
27
+ #include "absl/strings/string_view.h"
28
+
29
+ namespace grpc_core {
30
+
31
+ // Mitigations represent read-only configuration rules.
32
+ class Mitigation : public RefCounted<Mitigation> {
33
+ public:
34
+ ~Mitigation() override = default;
35
+
36
+ virtual std::optional<MitigationEngine::Action>
37
+ EvaluateIncomingMetadataParsed(absl::string_view key,
38
+ absl::string_view value) const = 0;
39
+ virtual std::optional<MitigationEngine::Action>
40
+ EvaluateIncomingMetadataAllParsed(
41
+ const grpc_metadata_batch& metadata) const = 0;
42
+
43
+ Mitigation() = default;
44
+ // Not movable or copyable.
45
+ Mitigation(Mitigation&&) = delete;
46
+ Mitigation& operator=(Mitigation&&) = delete;
47
+ Mitigation(const Mitigation&) = delete;
48
+ Mitigation& operator=(const Mitigation&) = delete;
49
+ };
50
+
51
+ } // namespace grpc_core
52
+
53
+ #endif // GRPC_SRC_CORE_MITIGATION_ENGINE_MITIGATION_H