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_ROUTE_CONFIG_H 18 #define GRPC_SRC_CORE_EXT_XDS_XDS_ROUTE_CONFIG_H 19 20 #include <grpc/support/port_platform.h> 21 22 #include <stdint.h> 23 24 #include <algorithm> 25 #include <map> 26 #include <memory> 27 #include <string> 28 #include <vector> 29 30 #include "absl/strings/string_view.h" 31 #include "absl/types/optional.h" 32 #include "absl/types/variant.h" 33 #include "envoy/config/route/v3/route.upb.h" 34 #include "envoy/config/route/v3/route.upbdefs.h" 35 #include "re2/re2.h" 36 #include "upb/reflection/def.h" 37 38 #include "src/core/ext/xds/xds_bootstrap_grpc.h" 39 #include "src/core/ext/xds/xds_client.h" 40 #include "src/core/ext/xds/xds_cluster_specifier_plugin.h" 41 #include "src/core/ext/xds/xds_http_filters.h" 42 #include "src/core/ext/xds/xds_resource_type.h" 43 #include "src/core/ext/xds/xds_resource_type_impl.h" 44 #include "src/core/lib/channel/status_util.h" 45 #include "src/core/lib/gprpp/time.h" 46 #include "src/core/lib/gprpp/validation_errors.h" 47 #include "src/core/lib/matchers/matchers.h" 48 49 namespace grpc_core { 50 51 struct XdsRouteConfigResource : public XdsResourceType::ResourceData { 52 using TypedPerFilterConfig = 53 std::map<std::string, XdsHttpFilterImpl::FilterConfig>; 54 55 using ClusterSpecifierPluginMap = 56 std::map<std::string /*cluster_specifier_plugin_name*/, 57 std::string /*LB policy config*/>; 58 59 struct RetryPolicy { 60 internal::StatusCodeSet retry_on; 61 uint32_t num_retries; 62 63 struct RetryBackOff { 64 Duration base_interval; 65 Duration max_interval; 66 67 bool operator==(const RetryBackOff& other) const { 68 return base_interval == other.base_interval && 69 max_interval == other.max_interval; 70 } 71 std::string ToString() const; 72 }; 73 RetryBackOff retry_back_off; 74 75 bool operator==(const RetryPolicy& other) const { 76 return (retry_on == other.retry_on && num_retries == other.num_retries && 77 retry_back_off == other.retry_back_off); 78 } 79 std::string ToString() const; 80 }; 81 82 struct Route { 83 // Matchers for this route. 84 struct Matchers { 85 StringMatcher path_matcher; 86 std::vector<HeaderMatcher> header_matchers; 87 absl::optional<uint32_t> fraction_per_million; 88 89 bool operator==(const Matchers& other) const { 90 return path_matcher == other.path_matcher && 91 header_matchers == other.header_matchers && 92 fraction_per_million == other.fraction_per_million; 93 } 94 std::string ToString() const; 95 }; 96 97 Matchers matchers; 98 99 struct UnknownAction { 100 bool operator==(const UnknownAction& /* other */) const { return true; } 101 }; 102 103 struct RouteAction { 104 struct HashPolicy { 105 struct Header { 106 std::string header_name; 107 std::unique_ptr<RE2> regex; 108 std::string regex_substitution; 109 110 Header() = default; 111 112 // Copyable. 113 Header(const Header& other); 114 Header& operator=(const Header& other); 115 116 // Movable. 117 Header(Header&& other) noexcept; 118 Header& operator=(Header&& other) noexcept; 119 120 bool operator==(const Header& other) const; 121 std::string ToString() const; 122 }; 123 124 struct ChannelId { 125 bool operator==(const ChannelId&) const { return true; } 126 }; 127 128 absl::variant<Header, ChannelId> policy; 129 bool terminal = false; 130 131 bool operator==(const HashPolicy& other) const { 132 return policy == other.policy && terminal == other.terminal; 133 } 134 std::string ToString() const; 135 }; 136 137 struct ClusterName { 138 std::string cluster_name; 139 140 bool operator==(const ClusterName& other) const { 141 return cluster_name == other.cluster_name; 142 } 143 }; 144 145 struct ClusterWeight { 146 std::string name; 147 uint32_t weight; 148 TypedPerFilterConfig typed_per_filter_config; 149 150 bool operator==(const ClusterWeight& other) const { 151 return name == other.name && weight == other.weight && 152 typed_per_filter_config == other.typed_per_filter_config; 153 } 154 std::string ToString() const; 155 }; 156 157 struct ClusterSpecifierPluginName { 158 std::string cluster_specifier_plugin_name; 159 160 bool operator==(const ClusterSpecifierPluginName& other) const { 161 return cluster_specifier_plugin_name == 162 other.cluster_specifier_plugin_name; 163 } 164 }; 165 166 std::vector<HashPolicy> hash_policies; 167 absl::optional<RetryPolicy> retry_policy; 168 169 // Action for this route. 170 absl::variant<ClusterName, std::vector<ClusterWeight>, 171 ClusterSpecifierPluginName> 172 action; 173 // Storing the timeout duration from route action: 174 // RouteAction.max_stream_duration.grpc_timeout_header_max or 175 // RouteAction.max_stream_duration.max_stream_duration if the former is 176 // not set. 177 absl::optional<Duration> max_stream_duration; 178 179 bool operator==(const RouteAction& other) const { 180 return hash_policies == other.hash_policies && 181 retry_policy == other.retry_policy && action == other.action && 182 max_stream_duration == other.max_stream_duration; 183 } 184 std::string ToString() const; 185 }; 186 187 struct NonForwardingAction { 188 bool operator==(const NonForwardingAction& /* other */) const { 189 return true; 190 } 191 }; 192 193 absl::variant<UnknownAction, RouteAction, NonForwardingAction> action; 194 TypedPerFilterConfig typed_per_filter_config; 195 196 bool operator==(const Route& other) const { 197 return matchers == other.matchers && action == other.action && 198 typed_per_filter_config == other.typed_per_filter_config; 199 } 200 std::string ToString() const; 201 }; 202 203 struct VirtualHost { 204 std::vector<std::string> domains; 205 std::vector<Route> routes; 206 TypedPerFilterConfig typed_per_filter_config; 207 208 bool operator==(const VirtualHost& other) const { 209 return domains == other.domains && routes == other.routes && 210 typed_per_filter_config == other.typed_per_filter_config; 211 } 212 }; 213 214 std::vector<VirtualHost> virtual_hosts; 215 ClusterSpecifierPluginMap cluster_specifier_plugin_map; 216 217 bool operator==(const XdsRouteConfigResource& other) const { 218 return virtual_hosts == other.virtual_hosts && 219 cluster_specifier_plugin_map == other.cluster_specifier_plugin_map; 220 } 221 std::string ToString() const; 222 223 static XdsRouteConfigResource Parse( 224 const XdsResourceType::DecodeContext& context, 225 const envoy_config_route_v3_RouteConfiguration* route_config, 226 ValidationErrors* errors); 227 }; 228 229 class XdsRouteConfigResourceType 230 : public XdsResourceTypeImpl<XdsRouteConfigResourceType, 231 XdsRouteConfigResource> { 232 public: type_url()233 absl::string_view type_url() const override { 234 return "envoy.config.route.v3.RouteConfiguration"; 235 } 236 237 DecodeResult Decode(const XdsResourceType::DecodeContext& context, 238 absl::string_view serialized_resource) const override; 239 InitUpbSymtab(XdsClient * xds_client,upb_DefPool * symtab)240 void InitUpbSymtab(XdsClient* xds_client, 241 upb_DefPool* symtab) const override { 242 envoy_config_route_v3_RouteConfiguration_getmsgdef(symtab); 243 const auto& cluster_specifier_plugin_registry = 244 static_cast<const GrpcXdsBootstrap&>(xds_client->bootstrap()) 245 .cluster_specifier_plugin_registry(); 246 cluster_specifier_plugin_registry.PopulateSymtab(symtab); 247 } 248 }; 249 250 } // namespace grpc_core 251 252 #endif // GRPC_SRC_CORE_EXT_XDS_XDS_ROUTE_CONFIG_H 253