1 // 2 // Copyright 2018 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 17 #ifndef GRPC_SRC_CORE_EXT_XDS_XDS_ENDPOINT_H 18 #define GRPC_SRC_CORE_EXT_XDS_XDS_ENDPOINT_H 19 20 #include <grpc/support/port_platform.h> 21 22 #include <stdint.h> 23 24 #include <algorithm> 25 #include <map> 26 #include <string> 27 #include <utility> 28 #include <vector> 29 30 #include "absl/base/thread_annotations.h" 31 #include "absl/random/random.h" 32 #include "absl/strings/string_view.h" 33 #include "envoy/config/endpoint/v3/endpoint.upbdefs.h" 34 #include "upb/reflection/def.h" 35 36 #include "src/core/ext/xds/xds_client.h" 37 #include "src/core/ext/xds/xds_client_stats.h" 38 #include "src/core/ext/xds/xds_resource_type.h" 39 #include "src/core/ext/xds/xds_resource_type_impl.h" 40 #include "src/core/lib/gprpp/ref_counted.h" 41 #include "src/core/lib/gprpp/ref_counted_ptr.h" 42 #include "src/core/lib/gprpp/sync.h" 43 #include "src/core/resolver/endpoint_addresses.h" 44 45 namespace grpc_core { 46 47 struct XdsEndpointResource : public XdsResourceType::ResourceData { 48 struct Priority { 49 struct Locality { 50 RefCountedPtr<XdsLocalityName> name; 51 uint32_t lb_weight; 52 EndpointAddressesList endpoints; 53 54 bool operator==(const Locality& other) const { 55 return *name == *other.name && lb_weight == other.lb_weight && 56 endpoints == other.endpoints; 57 } 58 bool operator!=(const Locality& other) const { return !(*this == other); } 59 std::string ToString() const; 60 }; 61 62 std::map<XdsLocalityName*, Locality, XdsLocalityName::Less> localities; 63 64 bool operator==(const Priority& other) const; 65 bool operator!=(const Priority& other) const { return !(*this == other); } 66 std::string ToString() const; 67 }; 68 using PriorityList = std::vector<Priority>; 69 70 // There are two phases of accessing this class's content: 71 // 1. to initialize in the control plane combiner; 72 // 2. to use in the data plane combiner. 73 // So no additional synchronization is needed. 74 class DropConfig final : public RefCounted<DropConfig> { 75 public: 76 struct DropCategory { 77 bool operator==(const DropCategory& other) const { 78 return name == other.name && 79 parts_per_million == other.parts_per_million; 80 } 81 82 std::string name; 83 const uint32_t parts_per_million; 84 }; 85 86 using DropCategoryList = std::vector<DropCategory>; 87 AddCategoryXdsEndpointResource88 void AddCategory(std::string name, uint32_t parts_per_million) { 89 drop_category_list_.emplace_back( 90 DropCategory{std::move(name), parts_per_million}); 91 if (parts_per_million == 1000000) drop_all_ = true; 92 } 93 94 // The only method invoked from outside the WorkSerializer (used in 95 // the data plane). 96 bool ShouldDrop(const std::string** category_name); 97 drop_category_listXdsEndpointResource98 const DropCategoryList& drop_category_list() const { 99 return drop_category_list_; 100 } 101 drop_allXdsEndpointResource102 bool drop_all() const { return drop_all_; } 103 104 bool operator==(const DropConfig& other) const { 105 return drop_category_list_ == other.drop_category_list_; 106 } 107 bool operator!=(const DropConfig& other) const { return !(*this == other); } 108 109 std::string ToString() const; 110 111 private: 112 DropCategoryList drop_category_list_; 113 bool drop_all_ = false; 114 115 // TODO(roth): Consider using a separate thread-local BitGen for each CPU 116 // to avoid the need for this mutex. 117 Mutex mu_; 118 absl::BitGen bit_gen_ ABSL_GUARDED_BY(&mu_); 119 }; 120 121 PriorityList priorities; 122 RefCountedPtr<DropConfig> drop_config; 123 124 bool operator==(const XdsEndpointResource& other) const { 125 if (priorities != other.priorities) return false; 126 if (drop_config == nullptr) return other.drop_config == nullptr; 127 if (other.drop_config == nullptr) return false; 128 return *drop_config == *other.drop_config; 129 } 130 std::string ToString() const; 131 }; 132 133 class XdsEndpointResourceType final 134 : public XdsResourceTypeImpl<XdsEndpointResourceType, XdsEndpointResource> { 135 public: type_url()136 absl::string_view type_url() const override { 137 return "envoy.config.endpoint.v3.ClusterLoadAssignment"; 138 } 139 140 DecodeResult Decode(const XdsResourceType::DecodeContext& context, 141 absl::string_view serialized_resource) const override; 142 InitUpbSymtab(XdsClient *,upb_DefPool * symtab)143 void InitUpbSymtab(XdsClient*, upb_DefPool* symtab) const override { 144 envoy_config_endpoint_v3_ClusterLoadAssignment_getmsgdef(symtab); 145 } 146 }; 147 148 } // namespace grpc_core 149 150 #endif // GRPC_SRC_CORE_EXT_XDS_XDS_ENDPOINT_H 151