xds_lb_policy_registry.cc
Go to the documentation of this file.
1 //
2 // Copyright 2022 gRPC authors.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 
18 
20 
21 #include <stddef.h>
22 
23 #include <string>
24 #include <type_traits>
25 #include <utility>
26 #include <vector>
27 
28 #include "absl/memory/memory.h"
29 #include "absl/status/status.h"
30 #include "absl/strings/str_cat.h"
31 #include "absl/strings/str_format.h"
39 #include "upb/json_encode.h"
40 #include "upb/upb.h"
41 #include "upb/upb.hpp"
43 
48 
49 namespace grpc_core {
50 
51 namespace {
52 
53 class RingHashLbPolicyConfigFactory
54  : public XdsLbPolicyRegistry::ConfigFactory {
55  public:
56  absl::StatusOr<Json::Object> ConvertXdsLbPolicyConfig(
57  const XdsEncodingContext& context, absl::string_view configuration,
58  int /* recursion_depth */) override {
59  const auto* resource =
61  configuration.data(), configuration.size(), context.arena);
62  if (resource == nullptr) {
64  "Can't decode RingHash loadbalancing policy");
65  }
67  resource) !=
70  "Invalid hash function provided for RingHash loadbalancing policy. "
71  "Only XX_HASH is supported.");
72  }
73  Json::Object json;
74  const auto* min_ring_size =
76  resource);
77  if (min_ring_size != nullptr) {
78  json.emplace("minRingSize",
79  google_protobuf_UInt64Value_value(min_ring_size));
80  }
81  const auto* max_ring_size =
83  resource);
84  if (max_ring_size != nullptr) {
85  json.emplace("maxRingSize",
86  google_protobuf_UInt64Value_value(max_ring_size));
87  }
88  return Json::Object{{"ring_hash_experimental", std::move(json)}};
89  }
90 
91  absl::string_view type() override { return Type(); }
92 
93  static absl::string_view Type() {
94  return "envoy.extensions.load_balancing_policies.ring_hash.v3.RingHash";
95  }
96 };
97 
98 class RoundRobinLbPolicyConfigFactory
99  : public XdsLbPolicyRegistry::ConfigFactory {
100  public:
101  absl::StatusOr<Json::Object> ConvertXdsLbPolicyConfig(
102  const XdsEncodingContext& /* context */,
103  absl::string_view /* configuration */,
104  int /* recursion_depth */) override {
105  return Json::Object{{"round_robin", Json::Object()}};
106  }
107 
108  absl::string_view type() override { return Type(); }
109 
110  static absl::string_view Type() {
111  return "envoy.extensions.load_balancing_policies.round_robin.v3.RoundRobin";
112  }
113 };
114 
115 class WrrLocalityLbPolicyConfigFactory
116  : public XdsLbPolicyRegistry::ConfigFactory {
117  public:
118  absl::StatusOr<Json::Object> ConvertXdsLbPolicyConfig(
119  const XdsEncodingContext& context, absl::string_view configuration,
120  int recursion_depth) override {
121  const auto* resource =
123  configuration.data(), configuration.size(), context.arena);
124  if (resource == nullptr) {
126  "Can't decode WrrLocality loadbalancing policy");
127  }
128  const auto* endpoint_picking_policy =
130  resource);
131  if (endpoint_picking_policy == nullptr) {
133  "WrrLocality: endpoint_picking_policy not found");
134  }
136  context, endpoint_picking_policy, recursion_depth + 1);
137  if (!child_policy.ok()) {
139  absl::StrCat("Error parsing WrrLocality load balancing policy: ",
140  child_policy.status().message()));
141  }
142  return Json::Object{
143  {"xds_wrr_locality_experimental",
144  Json::Object{{"child_policy", *std::move(child_policy)}}}};
145  }
146 
147  absl::string_view type() override { return Type(); }
148 
149  static absl::string_view Type() {
150  return "envoy.extensions.load_balancing_policies.wrr_locality.v3."
151  "WrrLocality";
152  }
153 };
154 
155 absl::StatusOr<Json> ParseStructToJson(const XdsEncodingContext& context,
156  const google_protobuf_Struct* resource) {
158  const auto* msg_def = google_protobuf_Struct_getmsgdef(context.symtab);
159  size_t json_size = upb_JsonEncode(resource, msg_def, context.symtab, 0,
160  nullptr, 0, status.ptr());
161  if (json_size == static_cast<size_t>(-1)) {
163  absl::StrCat("Error parsing google::Protobuf::Struct: ",
165  }
166  void* buf = upb_Arena_Malloc(context.arena, json_size + 1);
167  upb_JsonEncode(resource, msg_def, context.symtab, 0,
168  reinterpret_cast<char*>(buf), json_size + 1, status.ptr());
170  auto json = Json::Parse(reinterpret_cast<char*>(buf), &error);
171  if (!GRPC_ERROR_IS_NONE(error)) {
172  // This should not happen
173  auto ret_status = absl::InternalError(
174  absl::StrCat("Error parsing JSON form of google::Protobuf::Struct "
175  "produced by upb library: ",
178  return ret_status;
179  }
180  return json;
181 }
182 
183 } // namespace
184 
185 //
186 // XdsLbPolicyRegistry
187 //
188 
192  int recursion_depth) {
193  constexpr int kMaxRecursionDepth = 16;
194  if (recursion_depth >= kMaxRecursionDepth) {
196  absl::StrFormat("LoadBalancingPolicy configuration has a recursion "
197  "depth of more than %d.",
198  kMaxRecursionDepth));
199  }
200  size_t size = 0;
201  const auto* policies =
203  for (size_t i = 0; i < size; ++i) {
205  const auto* typed_extension_config =
207  policies[i]);
208  if (typed_extension_config == nullptr) {
210  "Error parsing LoadBalancingPolicy::Policy - Missing "
211  "typed_extension_config field");
212  }
213  const auto* typed_config =
215  typed_extension_config);
216  if (typed_config == nullptr) {
218  "Error parsing LoadBalancingPolicy::Policy - Missing "
219  "TypedExtensionConfig::typed_config field");
220  }
221  auto type = ExtractExtensionTypeName(context, typed_config);
222  if (!type.ok()) {
224  "Error parsing "
225  "LoadBalancingPolicy::Policy::TypedExtensionConfig::typed_config: ",
226  type.status().message()));
227  }
230  auto config_factory_it = Get()->policy_config_factories_.find(type->type);
231  if (config_factory_it != Get()->policy_config_factories_.end()) {
232  policy = config_factory_it->second->ConvertXdsLbPolicyConfig(
233  context, value, recursion_depth);
234  if (!policy.ok()) {
236  absl::StrCat("Error parsing "
237  "LoadBalancingPolicy::Policy::TypedExtensionConfig::"
238  "typed_config to JSON: ",
239  policy.status().message()));
240  }
241  } else if (type->typed_struct != nullptr) {
242  // Custom lb policy config
243  std::string custom_type = std::string(type->type);
245  custom_type.c_str(), nullptr)) {
246  // Skip unsupported custom lb policy.
247  continue;
248  }
249  // Convert typed struct to json.
250  auto value = xds_type_v3_TypedStruct_value(type->typed_struct);
251  if (value == nullptr) {
252  policy = Json::Object{{std::move(custom_type), Json() /* null */}};
253  } else {
254  auto parsed_value = ParseStructToJson(context, value);
255  if (!parsed_value.ok()) {
257  "Error parsing LoadBalancingPolicy: Custom Policy: ", custom_type,
258  ": ", parsed_value.status().message()));
259  }
260  policy =
261  Json::Object{{std::move(custom_type), *(std::move(parsed_value))}};
262  }
263  } else {
264  // Unsupported type. Skipping entry.
265  continue;
266  }
267  return Json::Array{std::move(policy.value())};
268  }
270  "No supported load balancing policy config found.");
271 }
272 
274  policy_config_factories_.emplace(
276  absl::make_unique<RingHashLbPolicyConfigFactory>());
277  policy_config_factories_.emplace(
279  absl::make_unique<RoundRobinLbPolicyConfigFactory>());
280  policy_config_factories_.emplace(
282  absl::make_unique<WrrLocalityLbPolicyConfigFactory>());
283 }
284 
286  // This is thread-safe since C++11
288  return instance;
289 }
290 
291 } // namespace grpc_core
grpc_core::Json::Array
std::vector< Json > Array
Definition: src/core/lib/json/json.h:55
absl::InvalidArgumentError
Status InvalidArgumentError(absl::string_view message)
Definition: third_party/abseil-cpp/absl/status/status.cc:351
Type
struct Type Type
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/protobuf.h:673
cleanup.Json
Json
Definition: cleanup.py:49
GRPC_ERROR_NONE
#define GRPC_ERROR_NONE
Definition: error.h:234
grpc_core::XdsLbPolicyRegistry
Definition: xds_lb_policy_registry.h:36
absl::StrCat
std::string StrCat(const AlphaNum &a, const AlphaNum &b)
Definition: abseil-cpp/absl/strings/str_cat.cc:98
absl::StrFormat
ABSL_MUST_USE_RESULT std::string StrFormat(const FormatSpec< Args... > &format, const Args &... args)
Definition: abseil-cpp/absl/strings/str_format.h:338
envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_maximum_ring_size
UPB_INLINE const struct google_protobuf_UInt64Value * envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_maximum_ring_size(const envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash *msg)
Definition: ring_hash.upb.h:91
envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_minimum_ring_size
UPB_INLINE const struct google_protobuf_UInt64Value * envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_minimum_ring_size(const envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash *msg)
Definition: ring_hash.upb.h:82
grpc_core::XdsEncodingContext
Definition: upb_utils.h:39
grpc_core
Definition: call_metric_recorder.h:31
ring_hash.upb.h
buf
voidpf void * buf
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:136
absl::string_view
Definition: abseil-cpp/absl/strings/string_view.h:167
testing::internal::string
::std::string string
Definition: bloaty/third_party/protobuf/third_party/googletest/googletest/include/gtest/internal/gtest-port.h:881
error
grpc_error_handle error
Definition: retry_filter.cc:499
envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_XX_HASH
@ envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_XX_HASH
Definition: ring_hash.upb.h:33
instance
RefCountedPtr< grpc_tls_certificate_provider > instance
Definition: xds_server_config_fetcher.cc:224
status
absl::Status status
Definition: rls.cc:251
struct.upb.h
upb_JsonEncode
size_t upb_JsonEncode(const upb_Message *msg, const upb_MessageDef *m, const upb_DefPool *ext_pool, int options, char *buf, size_t size, upb_Status *status)
Definition: json_encode.c:757
envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_parse
UPB_INLINE envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash * envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_parse(const char *buf, size_t size, upb_Arena *arena)
Definition: ring_hash.upb.h:44
absl::InternalError
Status InternalError(absl::string_view message)
Definition: third_party/abseil-cpp/absl/status/status.cc:347
xds_lb_policy_registry.h
upb_Status_ErrorMessage
const char * upb_Status_ErrorMessage(const upb_Status *status)
Definition: upb/upb/upb.c:52
json_encode.h
envoy_config_cluster_v3_LoadBalancingPolicy
struct envoy_config_cluster_v3_LoadBalancingPolicy envoy_config_cluster_v3_LoadBalancingPolicy
Definition: config/cluster/v3/cluster.upb.h:68
absl::move
constexpr absl::remove_reference_t< T > && move(T &&t) noexcept
Definition: abseil-cpp/absl/utility/utility.h:221
absl::string_view::size
constexpr size_type size() const noexcept
Definition: abseil-cpp/absl/strings/string_view.h:277
google_protobuf_UInt64Value_value
UPB_INLINE uint64_t google_protobuf_UInt64Value_value(const google_protobuf_UInt64Value *msg)
Definition: wrappers.upb.h:213
xds_common_types.h
upb.h
wrr_locality.upb.h
upb_Arena_Malloc
UPB_INLINE void * upb_Arena_Malloc(upb_Arena *a, size_t size)
Definition: upb/upb/upb.h:222
wrappers.upb.h
grpc_core::XdsLbPolicyRegistry::Get
static XdsLbPolicyRegistry * Get()
Definition: xds_lb_policy_registry.cc:285
google_protobuf_Struct
struct google_protobuf_Struct google_protobuf_Struct
Definition: google/protobuf/struct.upb.h:27
envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality_parse
UPB_INLINE envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality * envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality_parse(const char *buf, size_t size, upb_Arena *arena)
Definition: wrr_locality.upb.h:36
error.h
xds_type_v3_TypedStruct_value
UPB_INLINE const struct google_protobuf_Struct * xds_type_v3_TypedStruct_value(const xds_type_v3_TypedStruct *msg)
Definition: typed_struct.upb.h:74
typed_struct.upb.h
grpc_core::Json::Parse
static Json Parse(absl::string_view json_str, grpc_error_handle *error)
Definition: json_reader.cc:899
value
const char * value
Definition: hpack_parser_table.cc:165
grpc_core::Json::Object
std::map< std::string, Json > Object
Definition: src/core/lib/json/json.h:54
absl::StatusOr::ok
ABSL_MUST_USE_RESULT bool ok() const
Definition: abseil-cpp/absl/status/statusor.h:491
envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_hash_function
UPB_INLINE int32_t envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_hash_function(const envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash *msg)
Definition: ring_hash.upb.h:73
envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality_endpoint_picking_policy
UPB_INLINE const struct envoy_config_cluster_v3_LoadBalancingPolicy * envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality_endpoint_picking_policy(const envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality *msg)
Definition: wrr_locality.upb.h:68
envoy_config_cluster_v3_LoadBalancingPolicy_Policy_typed_extension_config
UPB_INLINE const struct envoy_config_core_v3_TypedExtensionConfig * envoy_config_cluster_v3_LoadBalancingPolicy_Policy_typed_extension_config(const envoy_config_cluster_v3_LoadBalancingPolicy_Policy *msg)
Definition: config/cluster/v3/cluster.upb.h:2765
google_protobuf_Struct_getmsgdef
const UPB_INLINE upb_MessageDef * google_protobuf_Struct_getmsgdef(upb_DefPool *s)
Definition: google/protobuf/struct.upbdefs.h:24
lb_policy_registry.h
upb.hpp
grpc_error_std_string
std::string grpc_error_std_string(grpc_error_handle error)
Definition: error.cc:944
grpc_core::XdsLbPolicyRegistry::policy_config_factories_
std::map< absl::string_view, std::unique_ptr< ConfigFactory > > policy_config_factories_
Definition: xds_lb_policy_registry.h:67
struct.upbdefs.h
GRPC_ERROR_UNREF
#define GRPC_ERROR_UNREF(err)
Definition: error.h:262
grpc_core::ExtractExtensionTypeName
absl::StatusOr< ExtractExtensionTypeNameResult > ExtractExtensionTypeName(const XdsEncodingContext &context, const google_protobuf_Any *any)
Definition: xds_common_types.cc:377
envoy_config_core_v3_TypedExtensionConfig_typed_config
UPB_INLINE const struct google_protobuf_Any * envoy_config_core_v3_TypedExtensionConfig_typed_config(const envoy_config_core_v3_TypedExtensionConfig *msg)
Definition: envoy/config/core/v3/extension.upb.h:74
context
grpc::ClientContext context
Definition: istio_echo_server_lib.cc:61
absl::StatusOr::value
const T & value() const &ABSL_ATTRIBUTE_LIFETIME_BOUND
Definition: abseil-cpp/absl/status/statusor.h:687
grpc_core::LoadBalancingPolicyRegistry::LoadBalancingPolicyExists
static bool LoadBalancingPolicyExists(const char *name, bool *requires_config)
Definition: lb_policy_registry.cc:109
any.upb.h
absl::StatusOr
Definition: abseil-cpp/absl/status/statusor.h:187
asyncio_get_stats.type
type
Definition: asyncio_get_stats.py:37
grpc_error
Definition: error_internal.h:42
upb_utils.h
size
voidpf void uLong size
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:136
upb::Status
Definition: upb.hpp:35
absl::string_view::data
constexpr const_pointer data() const noexcept
Definition: abseil-cpp/absl/strings/string_view.h:336
grpc_core::XdsLbPolicyRegistry::ConvertXdsLbPolicyConfig
static absl::StatusOr< Json::Array > ConvertXdsLbPolicyConfig(const XdsEncodingContext &context, const envoy_config_cluster_v3_LoadBalancingPolicy *lb_policy, int recursion_depth=0)
Definition: xds_lb_policy_registry.cc:189
envoy_config_cluster_v3_LoadBalancingPolicy_policies
const UPB_INLINE envoy_config_cluster_v3_LoadBalancingPolicy_Policy *const * envoy_config_cluster_v3_LoadBalancingPolicy_policies(const envoy_config_cluster_v3_LoadBalancingPolicy *msg, size_t *len)
Definition: config/cluster/v3/cluster.upb.h:2711
extension.upb.h
grpc_core::UpbStringToAbsl
absl::string_view UpbStringToAbsl(const upb_StringView &str)
Definition: upb_utils.h:56
grpc_core::XdsLbPolicyRegistry::XdsLbPolicyRegistry
XdsLbPolicyRegistry()
Definition: xds_lb_policy_registry.cc:273
i
uint64_t i
Definition: abseil-cpp/absl/container/btree_benchmark.cc:230
google_protobuf_Any_value
UPB_INLINE upb_StringView google_protobuf_Any_value(const google_protobuf_Any *msg)
Definition: any.upb.h:69
absl::StatusOr::status
const Status & status() const &
Definition: abseil-cpp/absl/status/statusor.h:678
GRPC_ERROR_IS_NONE
#define GRPC_ERROR_IS_NONE(err)
Definition: error.h:241
port_platform.h


grpc
Author(s):
autogenerated on Fri May 16 2025 03:00:59