Coverage Report

Created: 2024-09-19 09:45

/proc/self/cwd/source/common/runtime/runtime_features.cc
Line
Count
Source (jump to first uncovered line)
1
#include "source/common/runtime/runtime_features.h"
2
3
#include "absl/flags/commandlineflag.h"
4
#include "absl/flags/flag.h"
5
#include "absl/strings/match.h"
6
#include "absl/strings/str_replace.h"
7
8
#define RUNTIME_GUARD(name) ABSL_FLAG(bool, name, true, "");        // NOLINT
9
#define FALSE_RUNTIME_GUARD(name) ABSL_FLAG(bool, name, false, ""); // NOLINT
10
11
// Add additional features here to enable the new code paths by default.
12
//
13
// Per documentation in CONTRIBUTING.md is expected that new high risk code paths be guarded
14
// by runtime feature guards. If you add a guard of the form
15
// RUNTIME_GUARD(envoy_reloadable_features_my_feature_name)
16
// here you can guard code checking against "envoy.reloadable_features.my_feature_name".
17
// Please note the swap of envoy_reloadable_features_ to envoy.reloadable_features.!
18
//
19
// if (Runtime::runtimeFeatureEnabled("envoy.reloadable_features.my_feature_name")) {
20
//   [new code path]
21
// else {
22
//   [old_code_path]
23
// }
24
//
25
// Runtime features are true by default, so the new code path is exercised.
26
// To make a runtime feature false by default, use FALSE_RUNTIME_GUARD, and add
27
// a TODO to change it to true.
28
//
29
// If issues are found that require a runtime feature to be disabled, it should be reported
30
// ASAP by filing a bug on github. Overriding non-buggy code is strongly discouraged to avoid the
31
// problem of the bugs being found after the old code path has been removed.
32
RUNTIME_GUARD(envoy_reloadable_features_allow_alt_svc_for_ips);
33
RUNTIME_GUARD(envoy_reloadable_features_boolean_to_string_fix);
34
RUNTIME_GUARD(envoy_reloadable_features_check_switch_protocol_websocket_handshake);
35
RUNTIME_GUARD(envoy_reloadable_features_conn_pool_delete_when_idle);
36
RUNTIME_GUARD(envoy_reloadable_features_consistent_header_validation);
37
RUNTIME_GUARD(envoy_reloadable_features_defer_processing_backedup_streams);
38
RUNTIME_GUARD(envoy_reloadable_features_dfp_mixed_scheme);
39
RUNTIME_GUARD(envoy_reloadable_features_disallow_quic_client_udp_mmsg);
40
RUNTIME_GUARD(envoy_reloadable_features_dns_details);
41
RUNTIME_GUARD(envoy_reloadable_features_dns_nodata_noname_is_success);
42
RUNTIME_GUARD(envoy_reloadable_features_dns_reresolve_on_eai_again);
43
RUNTIME_GUARD(envoy_reloadable_features_edf_lb_host_scheduler_init_fix);
44
RUNTIME_GUARD(envoy_reloadable_features_edf_lb_locality_scheduler_init_fix);
45
RUNTIME_GUARD(envoy_reloadable_features_enable_compression_bomb_protection);
46
RUNTIME_GUARD(envoy_reloadable_features_enable_include_histograms);
47
RUNTIME_GUARD(envoy_reloadable_features_exclude_host_in_eds_status_draining);
48
RUNTIME_GUARD(envoy_reloadable_features_ext_proc_timeout_error);
49
RUNTIME_GUARD(envoy_reloadable_features_extend_h3_accept_untrusted);
50
RUNTIME_GUARD(envoy_reloadable_features_gcp_authn_use_fixed_url);
51
RUNTIME_GUARD(envoy_reloadable_features_getaddrinfo_num_retries);
52
RUNTIME_GUARD(envoy_reloadable_features_grpc_side_stream_flow_control);
53
RUNTIME_GUARD(envoy_reloadable_features_http1_balsa_delay_reset);
54
RUNTIME_GUARD(envoy_reloadable_features_http1_balsa_disallow_lone_cr_in_chunk_extension);
55
// Ignore the automated "remove this flag" issue: we should keep this for 1 year.
56
RUNTIME_GUARD(envoy_reloadable_features_http1_use_balsa_parser);
57
RUNTIME_GUARD(envoy_reloadable_features_http2_discard_host_header);
58
// Ignore the automated "remove this flag" issue: we should keep this for 1 year.
59
RUNTIME_GUARD(envoy_reloadable_features_http2_use_oghttp2);
60
RUNTIME_GUARD(envoy_reloadable_features_http2_use_visitor_for_data);
61
RUNTIME_GUARD(envoy_reloadable_features_http3_happy_eyeballs);
62
RUNTIME_GUARD(envoy_reloadable_features_http3_remove_empty_trailers);
63
RUNTIME_GUARD(envoy_reloadable_features_http_filter_avoid_reentrant_local_reply);
64
// Delay deprecation and decommission until UHV is enabled.
65
RUNTIME_GUARD(envoy_reloadable_features_http_reject_path_with_fragment);
66
RUNTIME_GUARD(envoy_reloadable_features_http_route_connect_proxy_by_default);
67
RUNTIME_GUARD(envoy_reloadable_features_internal_authority_header_validator);
68
RUNTIME_GUARD(envoy_reloadable_features_jwt_authn_remove_jwt_from_query_params);
69
RUNTIME_GUARD(envoy_reloadable_features_jwt_authn_validate_uri);
70
RUNTIME_GUARD(envoy_reloadable_features_lua_flow_control_while_http_call);
71
RUNTIME_GUARD(envoy_reloadable_features_mmdb_files_reload_enabled);
72
RUNTIME_GUARD(envoy_reloadable_features_no_extension_lookup_by_name);
73
RUNTIME_GUARD(envoy_reloadable_features_no_timer_based_rate_limit_token_bucket);
74
RUNTIME_GUARD(envoy_reloadable_features_original_dst_rely_on_idle_timeout);
75
RUNTIME_GUARD(envoy_reloadable_features_prefer_ipv6_dns_on_macos);
76
RUNTIME_GUARD(envoy_reloadable_features_proxy_104);
77
RUNTIME_GUARD(envoy_reloadable_features_proxy_ssl_port);
78
RUNTIME_GUARD(envoy_reloadable_features_proxy_status_mapping_more_core_response_flags);
79
RUNTIME_GUARD(envoy_reloadable_features_quic_connect_client_udp_sockets);
80
RUNTIME_GUARD(envoy_reloadable_features_quic_receive_ecn);
81
// Ignore the automated "remove this flag" issue: we should keep this for 1 year. Confirm with
82
// @danzh2010 or @RyanTheOptimist before removing.
83
RUNTIME_GUARD(envoy_reloadable_features_quic_send_server_preferred_address_to_all_clients);
84
RUNTIME_GUARD(envoy_reloadable_features_quic_support_certificate_compression);
85
RUNTIME_GUARD(envoy_reloadable_features_quic_upstream_reads_fixed_number_packets);
86
RUNTIME_GUARD(envoy_reloadable_features_quic_upstream_socket_use_address_cache_for_read);
87
RUNTIME_GUARD(envoy_reloadable_features_reject_invalid_yaml);
88
RUNTIME_GUARD(envoy_reloadable_features_report_stream_reset_error_code);
89
RUNTIME_GUARD(envoy_reloadable_features_sanitize_http2_headers_without_nghttp2);
90
RUNTIME_GUARD(envoy_reloadable_features_sanitize_te);
91
RUNTIME_GUARD(envoy_reloadable_features_send_local_reply_when_no_buffer_and_upstream_request);
92
RUNTIME_GUARD(envoy_reloadable_features_skip_dns_lookup_for_proxied_requests);
93
RUNTIME_GUARD(envoy_reloadable_features_strict_duration_validation);
94
RUNTIME_GUARD(envoy_reloadable_features_tcp_tunneling_send_downstream_fin_on_upstream_trailers);
95
RUNTIME_GUARD(envoy_reloadable_features_test_feature_true);
96
RUNTIME_GUARD(envoy_reloadable_features_udp_socket_apply_aggregated_read_limit);
97
RUNTIME_GUARD(envoy_reloadable_features_uhv_allow_malformed_url_encoding);
98
RUNTIME_GUARD(envoy_reloadable_features_upstream_remote_address_use_connection);
99
RUNTIME_GUARD(envoy_reloadable_features_use_config_in_happy_eyeballs);
100
RUNTIME_GUARD(envoy_reloadable_features_use_filter_manager_state_for_downstream_end_stream);
101
RUNTIME_GUARD(envoy_reloadable_features_use_http_client_to_fetch_aws_credentials);
102
RUNTIME_GUARD(envoy_reloadable_features_use_route_host_mutation_for_auto_sni_san);
103
RUNTIME_GUARD(envoy_reloadable_features_use_typed_metadata_in_proxy_protocol_listener);
104
RUNTIME_GUARD(envoy_reloadable_features_validate_connect);
105
RUNTIME_GUARD(envoy_reloadable_features_validate_grpc_header_before_log_grpc_status);
106
RUNTIME_GUARD(envoy_reloadable_features_validate_upstream_headers);
107
RUNTIME_GUARD(envoy_reloadable_features_xdstp_path_avoid_colon_encoding);
108
RUNTIME_GUARD(envoy_restart_features_allow_client_socket_creation_failure);
109
RUNTIME_GUARD(envoy_restart_features_allow_slot_destroy_on_worker_threads);
110
RUNTIME_GUARD(envoy_restart_features_fix_dispatcher_approximate_now);
111
RUNTIME_GUARD(envoy_restart_features_quic_handle_certs_with_shared_tls_code);
112
RUNTIME_GUARD(envoy_restart_features_use_eds_cache_for_ads);
113
RUNTIME_GUARD(envoy_restart_features_use_fast_protobuf_hash);
114
115
// Begin false flags. Most of them should come with a TODO to flip true.
116
117
// Execution context is optional and must be enabled explicitly.
118
// See https://github.com/envoyproxy/envoy/issues/32012.
119
FALSE_RUNTIME_GUARD(envoy_restart_features_enable_execution_context);
120
// Sentinel and test flag.
121
FALSE_RUNTIME_GUARD(envoy_reloadable_features_test_feature_false);
122
// TODO(paul-r-gall) Make this enabled by default after additional soak time.
123
FALSE_RUNTIME_GUARD(envoy_reloadable_features_streaming_shadow);
124
// TODO(adisuissa) reset to true to enable unified mux by default
125
FALSE_RUNTIME_GUARD(envoy_reloadable_features_unified_mux);
126
// Used to track if runtime is initialized.
127
FALSE_RUNTIME_GUARD(envoy_reloadable_features_runtime_initialized);
128
// TODO(mattklein123): Flip this to true and/or remove completely once verified by Envoy Mobile.
129
// TODO(mattklein123): Also unit test this if this sticks and this becomes the default for Apple &
130
// Android.
131
FALSE_RUNTIME_GUARD(envoy_reloadable_features_always_use_v6);
132
// TODO(vikaschoudhary16) flip this to true only after all the
133
// TcpProxy::Filter::HttpStreamDecoderFilterCallbacks are implemented or commented as unnecessary
134
FALSE_RUNTIME_GUARD(envoy_restart_features_upstream_http_filters_with_tcp_proxy);
135
// TODO(danzh) false deprecate it once QUICHE has its own enable/disable flag.
136
FALSE_RUNTIME_GUARD(envoy_reloadable_features_quic_reject_all);
137
// TODO(#10646) change to true when UHV is sufficiently tested
138
// For more information about Universal Header Validation, please see
139
// https://github.com/envoyproxy/envoy/issues/10646
140
FALSE_RUNTIME_GUARD(envoy_reloadable_features_enable_universal_header_validator);
141
// TODO(pksohn): enable after canarying fix for https://github.com/envoyproxy/envoy/issues/29930
142
FALSE_RUNTIME_GUARD(envoy_reloadable_features_quic_defer_logging_to_ack_listener);
143
// TODO(#33474) removed it once GRO packet dropping is fixed.
144
FALSE_RUNTIME_GUARD(envoy_reloadable_features_prefer_quic_client_udp_gro);
145
// TODO(alyssar) evaluate and either make this a config knob or remove.
146
FALSE_RUNTIME_GUARD(envoy_reloadable_features_reresolve_null_addresses);
147
// TODO(alyssar) evaluate and either make this a config knob or remove.
148
FALSE_RUNTIME_GUARD(envoy_reloadable_features_reresolve_if_no_connections);
149
// TODO(adisuissa): flip to true after this is out of alpha mode.
150
FALSE_RUNTIME_GUARD(envoy_restart_features_xds_failover_support);
151
// TODO(fredyw): evaluate and either make this a config knob or remove.
152
FALSE_RUNTIME_GUARD(envoy_reloadable_features_dns_cache_set_ip_version_to_remove);
153
// TODO(alyssawilk): evaluate and make this a config knob or remove.
154
FALSE_RUNTIME_GUARD(envoy_reloadable_features_reset_brokenness_on_nework_change);
155
156
// A flag to set the maximum TLS version for google_grpc client to TLS1.2, when needed for
157
// compliance restrictions.
158
FALSE_RUNTIME_GUARD(envoy_reloadable_features_google_grpc_disable_tls_13);
159
160
// TODO(yanavlasov): Flip to true after prod testing.
161
// Controls whether a stream stays open when HTTP/2 or HTTP/3 upstream half closes
162
// before downstream.
163
FALSE_RUNTIME_GUARD(envoy_reloadable_features_allow_multiplexed_upstream_half_close);
164
165
// Block of non-boolean flags. Use of int flags is deprecated. Do not add more.
166
ABSL_FLAG(uint64_t, re2_max_program_size_error_level, 100, ""); // NOLINT
167
ABSL_FLAG(uint64_t, re2_max_program_size_warn_level,            // NOLINT
168
          std::numeric_limits<uint32_t>::max(), "");            // NOLINT
169
170
namespace Envoy {
171
namespace Runtime {
172
namespace {
173
174
4.84k
std::string swapPrefix(std::string name) {
175
4.84k
  return absl::StrReplaceAll(name, {{"envoy_", "envoy."}, {"features_", "features."}});
176
4.84k
}
177
178
} // namespace
179
180
// This is a singleton class to map Envoy style flag names to absl flags
181
class RuntimeFeatures {
182
public:
183
  RuntimeFeatures();
184
185
  // Get the command line flag corresponding to the Envoy style feature name, or
186
  // nullptr if it is not a registered flag.
187
4.91M
  absl::CommandLineFlag* getFlag(absl::string_view feature) const {
188
4.91M
    auto it = all_features_.find(feature);
189
4.91M
    if (it == all_features_.end()) {
190
94.0k
      return nullptr;
191
94.0k
    }
192
4.82M
    return it->second;
193
4.91M
  }
194
195
private:
196
  absl::flat_hash_map<std::string, absl::CommandLineFlag*> all_features_;
197
};
198
199
using RuntimeFeaturesDefaults = ConstSingleton<RuntimeFeatures>;
200
201
51
RuntimeFeatures::RuntimeFeatures() {
202
51
  absl::flat_hash_map<absl::string_view, absl::CommandLineFlag*> flags = absl::GetAllFlags();
203
10.4k
  for (auto& it : flags) {
204
10.4k
    absl::string_view name = it.second->Name();
205
10.4k
    if ((!absl::StartsWith(name, "envoy_reloadable_features_") &&
206
10.4k
         !absl::StartsWith(name, "envoy_restart_features_")) ||
207
10.4k
        !it.second->TryGet<bool>().has_value()) {
208
5.62k
      continue;
209
5.62k
    }
210
4.84k
    std::string envoy_name = swapPrefix(std::string(name));
211
4.84k
    all_features_.emplace(envoy_name, it.second);
212
4.84k
  }
213
51
}
214
215
8.23k
bool hasRuntimePrefix(absl::string_view feature) {
216
  // Track Envoy reloadable and restart features, excluding synthetic QUIC flags
217
  // which are not tracked in the list below.
218
8.23k
  return (absl::StartsWith(feature, "envoy.reloadable_features.") &&
219
8.23k
          !absl::StartsWith(feature, "envoy.reloadable_features.FLAGS_envoy_quic")) ||
220
8.23k
         absl::StartsWith(feature, "envoy.restart_features.");
221
8.23k
}
222
223
137k
bool isRuntimeFeature(absl::string_view feature) {
224
137k
  return RuntimeFeaturesDefaults::get().getFlag(feature) != nullptr;
225
137k
}
226
227
4.63M
bool runtimeFeatureEnabled(absl::string_view feature) {
228
4.63M
  absl::CommandLineFlag* flag = RuntimeFeaturesDefaults::get().getFlag(feature);
229
4.63M
  if (flag == nullptr) {
230
0
    IS_ENVOY_BUG(absl::StrCat("Unable to find runtime feature ", feature));
231
0
    return false;
232
0
  }
233
  // We validate in map creation that the flag is a boolean.
234
4.63M
  return flag->TryGet<bool>().value();
235
4.63M
}
236
237
17.5k
uint64_t getInteger(absl::string_view feature, uint64_t default_value) {
238
  // DO NOT ADD MORE FLAGS HERE. This function deprecated.
239
17.5k
  if (absl::StartsWith(feature, "re2.")) {
240
17.5k
    if (feature == "re2.max_program_size.error_level") {
241
8.77k
      return absl::GetFlag(FLAGS_re2_max_program_size_error_level);
242
8.77k
    } else if (feature == "re2.max_program_size.warn_level") {
243
8.77k
      return absl::GetFlag(FLAGS_re2_max_program_size_warn_level);
244
8.77k
    }
245
17.5k
  }
246
0
  IS_ENVOY_BUG(absl::StrCat("requested an unsupported integer ", feature));
247
0
  return default_value;
248
0
}
249
250
97.5k
void markRuntimeInitialized() {
251
97.5k
  maybeSetRuntimeGuard("envoy.reloadable_features.runtime_initialized", true);
252
97.5k
}
253
254
37.6k
bool isRuntimeInitialized() {
255
37.6k
  return runtimeFeatureEnabled("envoy.reloadable_features.runtime_initialized");
256
37.6k
}
257
258
139k
void maybeSetRuntimeGuard(absl::string_view name, bool value) {
259
139k
  absl::CommandLineFlag* flag = RuntimeFeaturesDefaults::get().getFlag(name);
260
139k
  if (flag == nullptr) {
261
0
    IS_ENVOY_BUG(absl::StrCat("Unable to find runtime feature ", name));
262
0
    return;
263
0
  }
264
139k
  std::string err;
265
139k
  flag->ParseFrom(value ? "true" : "false", &err);
266
139k
}
267
268
4.08k
void maybeSetDeprecatedInts(absl::string_view name, uint32_t value) {
269
4.08k
  if (!absl::StartsWith(name, "envoy.") && !absl::StartsWith(name, "re2.")) {
270
3.80k
    return;
271
3.80k
  }
272
273
  // DO NOT ADD MORE FLAGS HERE. This function deprecated.
274
285
  else if (name == "re2.max_program_size.error_level") {
275
0
    absl::SetFlag(&FLAGS_re2_max_program_size_error_level, value);
276
285
  } else if (name == "re2.max_program_size.warn_level") {
277
0
    absl::SetFlag(&FLAGS_re2_max_program_size_warn_level, value);
278
0
  }
279
4.08k
}
280
281
} // namespace Runtime
282
} // namespace Envoy