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_API_H 18 #define GRPC_SRC_CORE_EXT_XDS_XDS_API_H 19 20 #include <grpc/support/port_platform.h> 21 22 #include <stddef.h> 23 24 #include <map> 25 #include <set> 26 #include <string> 27 #include <utility> 28 #include <vector> 29 30 #include "absl/status/status.h" 31 #include "absl/strings/string_view.h" 32 #include "envoy/admin/v3/config_dump_shared.upb.h" 33 #include "upb/mem/arena.h" 34 #include "upb/reflection/def.hpp" 35 36 #include "src/core/ext/xds/xds_bootstrap.h" 37 #include "src/core/ext/xds/xds_client_stats.h" 38 #include "src/core/lib/debug/trace.h" 39 #include "src/core/lib/gprpp/ref_counted_ptr.h" 40 #include "src/core/lib/gprpp/time.h" 41 42 namespace grpc_core { 43 44 class XdsClient; 45 46 // TODO(roth): When we have time, split this into multiple pieces: 47 // - ADS request/response handling 48 // - LRS request/response handling 49 // - CSDS response generation 50 class XdsApi { 51 public: 52 // Interface defined by caller and passed to ParseAdsResponse(). 53 class AdsResponseParserInterface { 54 public: 55 struct AdsResponseFields { 56 std::string type_url; 57 std::string version; 58 std::string nonce; 59 size_t num_resources; 60 }; 61 62 virtual ~AdsResponseParserInterface() = default; 63 64 // Called when the top-level ADS fields are parsed. 65 // If this returns non-OK, parsing will stop, and the individual 66 // resources will not be processed. 67 virtual absl::Status ProcessAdsResponseFields(AdsResponseFields fields) = 0; 68 69 // Called to parse each individual resource in the ADS response. 70 // Note that resource_name is non-empty only when the resource was 71 // wrapped in a Resource wrapper proto. 72 virtual void ParseResource(upb_Arena* arena, size_t idx, 73 absl::string_view type_url, 74 absl::string_view resource_name, 75 absl::string_view serialized_resource) = 0; 76 77 // Called when a resource is wrapped in a Resource wrapper proto but 78 // we fail to parse the Resource wrapper. 79 virtual void ResourceWrapperParsingFailed(size_t idx, 80 absl::string_view message) = 0; 81 }; 82 83 struct ClusterLoadReport { 84 XdsClusterDropStats::Snapshot dropped_requests; 85 std::map<RefCountedPtr<XdsLocalityName>, XdsClusterLocalityStats::Snapshot, 86 XdsLocalityName::Less> 87 locality_stats; 88 Duration load_report_interval; 89 }; 90 using ClusterLoadReportMap = std::map< 91 std::pair<std::string /*cluster_name*/, std::string /*eds_service_name*/>, 92 ClusterLoadReport>; 93 94 // The metadata of the xDS resource; used by the xDS config dump. 95 struct ResourceMetadata { 96 // Resource status from the view of a xDS client, which tells the 97 // synchronization status between the xDS client and the xDS server. 98 enum ClientResourceStatus { 99 // Client requested this resource but hasn't received any update from 100 // management server. The client will not fail requests, but will queue 101 // them 102 // until update arrives or the client times out waiting for the resource. 103 REQUESTED = 1, 104 // This resource has been requested by the client but has either not been 105 // delivered by the server or was previously delivered by the server and 106 // then subsequently removed from resources provided by the server. 107 DOES_NOT_EXIST, 108 // Client received this resource and replied with ACK. 109 ACKED, 110 // Client received this resource and replied with NACK. 111 NACKED 112 }; 113 114 // The client status of this resource. 115 ClientResourceStatus client_status = REQUESTED; 116 // The serialized bytes of the last successfully updated raw xDS resource. 117 std::string serialized_proto; 118 // The timestamp when the resource was last successfully updated. 119 Timestamp update_time; 120 // The last successfully updated version of the resource. 121 std::string version; 122 // The rejected version string of the last failed update attempt. 123 std::string failed_version; 124 // Details about the last failed update attempt. 125 std::string failed_details; 126 // Timestamp of the last failed update attempt. 127 Timestamp failed_update_time; 128 }; 129 using ResourceMetadataMap = 130 std::map<std::string /*resource_name*/, const ResourceMetadata*>; 131 using ResourceTypeMetadataMap = 132 std::map<absl::string_view /*type_url*/, ResourceMetadataMap>; 133 static_assert(static_cast<ResourceMetadata::ClientResourceStatus>( 134 envoy_admin_v3_REQUESTED) == 135 ResourceMetadata::ClientResourceStatus::REQUESTED, 136 ""); 137 static_assert(static_cast<ResourceMetadata::ClientResourceStatus>( 138 envoy_admin_v3_DOES_NOT_EXIST) == 139 ResourceMetadata::ClientResourceStatus::DOES_NOT_EXIST, 140 ""); 141 static_assert(static_cast<ResourceMetadata::ClientResourceStatus>( 142 envoy_admin_v3_ACKED) == 143 ResourceMetadata::ClientResourceStatus::ACKED, 144 ""); 145 static_assert(static_cast<ResourceMetadata::ClientResourceStatus>( 146 envoy_admin_v3_NACKED) == 147 ResourceMetadata::ClientResourceStatus::NACKED, 148 ""); 149 150 XdsApi(XdsClient* client, TraceFlag* tracer, const XdsBootstrap::Node* node, 151 upb::SymbolTable* symtab, std::string user_agent_name, 152 std::string user_agent_version); 153 154 // Creates an ADS request. 155 std::string CreateAdsRequest(absl::string_view type_url, 156 absl::string_view version, 157 absl::string_view nonce, 158 const std::vector<std::string>& resource_names, 159 absl::Status status, bool populate_node); 160 161 // Returns non-OK when failing to deserialize response message. 162 // Otherwise, all events are reported to the parser. 163 absl::Status ParseAdsResponse(absl::string_view encoded_response, 164 AdsResponseParserInterface* parser); 165 166 // Creates an initial LRS request. 167 std::string CreateLrsInitialRequest(); 168 169 // Creates an LRS request sending a client-side load report. 170 std::string CreateLrsRequest(ClusterLoadReportMap cluster_load_report_map); 171 172 // Parses the LRS response and populates send_all_clusters, 173 // cluster_names, and load_reporting_interval. 174 absl::Status ParseLrsResponse(absl::string_view encoded_response, 175 bool* send_all_clusters, 176 std::set<std::string>* cluster_names, 177 Duration* load_reporting_interval); 178 179 // Assemble the client config proto message and return the serialized result. 180 std::string AssembleClientConfig( 181 const ResourceTypeMetadataMap& resource_type_metadata_map); 182 183 private: 184 XdsClient* client_; 185 TraceFlag* tracer_; 186 const XdsBootstrap::Node* node_; // Do not own. 187 upb::SymbolTable* symtab_; // Do not own. 188 const std::string user_agent_name_; 189 const std::string user_agent_version_; 190 }; 191 192 } // namespace grpc_core 193 194 #endif // GRPC_SRC_CORE_EXT_XDS_XDS_API_H 195