Imported Upstream version 1.27.0
[platform/upstream/grpc.git] / src / core / ext / filters / client_channel / xds / xds_api.h
1 /*
2  *
3  * Copyright 2018 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_CORE_EXT_FILTERS_CLIENT_CHANNEL_XDS_XDS_API_H
20 #define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_XDS_XDS_API_H
21
22 #include <grpc/support/port_platform.h>
23
24 #include <stdint.h>
25
26 #include <set>
27
28 #include <grpc/slice_buffer.h>
29
30 #include "src/core/ext/filters/client_channel/server_address.h"
31 #include "src/core/ext/filters/client_channel/xds/xds_bootstrap.h"
32 #include "src/core/ext/filters/client_channel/xds/xds_client_stats.h"
33 #include "src/core/lib/gprpp/optional.h"
34
35 namespace grpc_core {
36
37 constexpr char kCdsTypeUrl[] = "type.googleapis.com/envoy.api.v2.Cluster";
38 constexpr char kEdsTypeUrl[] =
39     "type.googleapis.com/envoy.api.v2.ClusterLoadAssignment";
40
41 // The version state for each specific ADS resource type.
42 struct VersionState {
43   // The version of the latest response that is accepted and used.
44   std::string version_info;
45   // The nonce of the latest response.
46   std::string nonce;
47   // The error message to be included in a NACK with the nonce. Consumed when a
48   // nonce is NACK'ed for the first time.
49   grpc_error* error = GRPC_ERROR_NONE;
50
51   ~VersionState() { GRPC_ERROR_UNREF(error); }
52 };
53
54 struct CdsUpdate {
55   // The name to use in the EDS request.
56   // If empty, the cluster name will be used.
57   std::string eds_service_name;
58   // The LRS server to use for load reporting.
59   // If not set, load reporting will be disabled.
60   // If set to the empty string, will use the same server we obtained the CDS
61   // data from.
62   Optional<std::string> lrs_load_reporting_server_name;
63 };
64
65 using CdsUpdateMap = std::map<std::string /*cluster_name*/, CdsUpdate>;
66
67 class XdsPriorityListUpdate {
68  public:
69   struct LocalityMap {
70     struct Locality {
71       bool operator==(const Locality& other) const {
72         return *name == *other.name && serverlist == other.serverlist &&
73                lb_weight == other.lb_weight && priority == other.priority;
74       }
75
76       // This comparator only compares the locality names.
77       struct Less {
78         bool operator()(const Locality& lhs, const Locality& rhs) const {
79           return XdsLocalityName::Less()(lhs.name, rhs.name);
80         }
81       };
82
83       RefCountedPtr<XdsLocalityName> name;
84       ServerAddressList serverlist;
85       uint32_t lb_weight;
86       uint32_t priority;
87     };
88
89     bool Contains(const RefCountedPtr<XdsLocalityName>& name) const {
90       return localities.find(name) != localities.end();
91     }
92
93     size_t size() const { return localities.size(); }
94
95     std::map<RefCountedPtr<XdsLocalityName>, Locality, XdsLocalityName::Less>
96         localities;
97   };
98
99   bool operator==(const XdsPriorityListUpdate& other) const;
100   bool operator!=(const XdsPriorityListUpdate& other) const {
101     return !(*this == other);
102   }
103
104   void Add(LocalityMap::Locality locality);
105
106   const LocalityMap* Find(uint32_t priority) const;
107
108   bool Contains(uint32_t priority) const {
109     return priority < priorities_.size();
110   }
111   bool Contains(const RefCountedPtr<XdsLocalityName>& name);
112
113   bool empty() const { return priorities_.empty(); }
114   size_t size() const { return priorities_.size(); }
115
116   // Callers should make sure the priority list is non-empty.
117   uint32_t LowestPriority() const {
118     return static_cast<uint32_t>(priorities_.size()) - 1;
119   }
120
121  private:
122   InlinedVector<LocalityMap, 2> priorities_;
123 };
124
125 // There are two phases of accessing this class's content:
126 // 1. to initialize in the control plane combiner;
127 // 2. to use in the data plane combiner.
128 // So no additional synchronization is needed.
129 class XdsDropConfig : public RefCounted<XdsDropConfig> {
130  public:
131   struct DropCategory {
132     bool operator==(const DropCategory& other) const {
133       return name == other.name && parts_per_million == other.parts_per_million;
134     }
135
136     std::string name;
137     const uint32_t parts_per_million;
138   };
139
140   using DropCategoryList = InlinedVector<DropCategory, 2>;
141
142   void AddCategory(std::string name, uint32_t parts_per_million) {
143     drop_category_list_.emplace_back(
144         DropCategory{std::move(name), parts_per_million});
145   }
146
147   // The only method invoked from the data plane combiner.
148   bool ShouldDrop(const std::string** category_name) const;
149
150   const DropCategoryList& drop_category_list() const {
151     return drop_category_list_;
152   }
153
154   bool operator==(const XdsDropConfig& other) const {
155     return drop_category_list_ == other.drop_category_list_;
156   }
157   bool operator!=(const XdsDropConfig& other) const {
158     return !(*this == other);
159   }
160
161  private:
162   DropCategoryList drop_category_list_;
163 };
164
165 struct EdsUpdate {
166   XdsPriorityListUpdate priority_list_update;
167   RefCountedPtr<XdsDropConfig> drop_config;
168   bool drop_all = false;
169 };
170
171 using EdsUpdateMap = std::map<std::string /*eds_service_name*/, EdsUpdate>;
172
173 // Creates a request to nack an unsupported resource type.
174 // Takes ownership of \a error.
175 grpc_slice XdsUnsupportedTypeNackRequestCreateAndEncode(
176     const std::string& type_url, const std::string& nonce, grpc_error* error);
177
178 // Creates a CDS request querying \a cluster_names.
179 // Takes ownership of \a error.
180 grpc_slice XdsCdsRequestCreateAndEncode(
181     const std::set<StringView>& cluster_names, const XdsBootstrap::Node* node,
182     const char* build_version, const std::string& version,
183     const std::string& nonce, grpc_error* error);
184
185 // Creates an EDS request querying \a eds_service_names.
186 // Takes ownership of \a error.
187 grpc_slice XdsEdsRequestCreateAndEncode(
188     const std::set<StringView>& eds_service_names,
189     const XdsBootstrap::Node* node, const char* build_version,
190     const std::string& version, const std::string& nonce, grpc_error* error);
191
192 // Parses the ADS response and outputs the validated update for either CDS or
193 // EDS. If the response can't be parsed at the top level, \a type_url will point
194 // to an empty string; otherwise, it will point to the received data.
195 grpc_error* XdsAdsResponseDecodeAndParse(
196     const grpc_slice& encoded_response,
197     const std::set<StringView>& expected_eds_service_names,
198     CdsUpdateMap* cds_update_map, EdsUpdateMap* eds_update_map,
199     std::string* version, std::string* nonce, std::string* type_url);
200
201 // Creates an LRS request querying \a server_name.
202 grpc_slice XdsLrsRequestCreateAndEncode(const std::string& server_name,
203                                         const XdsBootstrap::Node* node,
204                                         const char* build_version);
205
206 // Creates an LRS request sending client-side load reports. If all the counters
207 // are zero, returns empty slice.
208 grpc_slice XdsLrsRequestCreateAndEncode(
209     std::map<StringView /*cluster_name*/, std::set<XdsClientStats*>>
210         client_stats_map);
211
212 // Parses the LRS response and returns \a
213 // load_reporting_interval for client-side load reporting. If there is any
214 // error, the output config is invalid.
215 grpc_error* XdsLrsResponseDecodeAndParse(const grpc_slice& encoded_response,
216                                          std::set<std::string>* cluster_names,
217                                          grpc_millis* load_reporting_interval);
218
219 }  // namespace grpc_core
220
221 #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_XDS_XDS_API_H */