LCOV - code coverage report
Current view: top level - source/common/runtime - runtime_features.cc (source / functions) Hit Total Coverage
Test: coverage.dat Lines: 48 75 64.0 %
Date: 2024-01-05 06:35:25 Functions: 9 11 81.8 %

          Line data    Source code
       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_absolute_url_with_mixed_scheme);
      33             : RUNTIME_GUARD(envoy_reloadable_features_append_xfh_idempotent);
      34             : RUNTIME_GUARD(envoy_reloadable_features_avoid_zombie_streams);
      35             : RUNTIME_GUARD(envoy_reloadable_features_check_mep_on_first_eject);
      36             : RUNTIME_GUARD(envoy_reloadable_features_conn_pool_delete_when_idle);
      37             : RUNTIME_GUARD(envoy_reloadable_features_convert_legacy_lb_config);
      38             : RUNTIME_GUARD(envoy_reloadable_features_copy_response_code_to_downstream_stream_info);
      39             : RUNTIME_GUARD(envoy_reloadable_features_count_unused_mapped_pages_as_free);
      40             : RUNTIME_GUARD(envoy_reloadable_features_defer_processing_backedup_streams);
      41             : RUNTIME_GUARD(envoy_reloadable_features_detect_and_raise_rst_tcp_connection);
      42             : RUNTIME_GUARD(envoy_reloadable_features_dfp_mixed_scheme);
      43             : RUNTIME_GUARD(envoy_reloadable_features_dns_cache_set_first_resolve_complete);
      44             : RUNTIME_GUARD(envoy_reloadable_features_enable_aws_credentials_file);
      45             : RUNTIME_GUARD(envoy_reloadable_features_enable_compression_bomb_protection);
      46             : RUNTIME_GUARD(envoy_reloadable_features_enable_connect_udp_support);
      47             : RUNTIME_GUARD(envoy_reloadable_features_enable_intermediate_ca);
      48             : RUNTIME_GUARD(envoy_reloadable_features_enable_zone_routing_different_zone_counts);
      49             : RUNTIME_GUARD(envoy_reloadable_features_ext_authz_http_send_original_xff);
      50             : RUNTIME_GUARD(envoy_reloadable_features_grpc_http1_reverse_bridge_handle_empty_response);
      51             : RUNTIME_GUARD(envoy_reloadable_features_handle_uppercase_scheme);
      52             : RUNTIME_GUARD(envoy_reloadable_features_hmac_base64_encoding_only);
      53             : RUNTIME_GUARD(envoy_reloadable_features_http1_allow_codec_error_response_after_1xx_headers);
      54             : RUNTIME_GUARD(envoy_reloadable_features_http1_connection_close_header_in_redirect);
      55             : RUNTIME_GUARD(envoy_reloadable_features_http1_use_balsa_parser);
      56             : RUNTIME_GUARD(envoy_reloadable_features_http2_decode_metadata_with_quiche);
      57             : RUNTIME_GUARD(envoy_reloadable_features_http2_discard_host_header);
      58             : RUNTIME_GUARD(envoy_reloadable_features_http2_use_oghttp2);
      59             : RUNTIME_GUARD(envoy_reloadable_features_http2_validate_authority_with_quiche);
      60             : RUNTIME_GUARD(envoy_reloadable_features_http_allow_partial_urls_in_referer);
      61             : RUNTIME_GUARD(envoy_reloadable_features_http_filter_avoid_reentrant_local_reply);
      62             : // Delay deprecation and decommission until UHV is enabled.
      63             : RUNTIME_GUARD(envoy_reloadable_features_http_reject_path_with_fragment);
      64             : RUNTIME_GUARD(envoy_reloadable_features_immediate_response_use_filter_mutation_rule);
      65             : RUNTIME_GUARD(envoy_reloadable_features_initialize_upstream_filters);
      66             : RUNTIME_GUARD(envoy_reloadable_features_keep_endpoint_active_hc_status_on_locality_update);
      67             : RUNTIME_GUARD(envoy_reloadable_features_locality_routing_use_new_routing_logic);
      68             : RUNTIME_GUARD(envoy_reloadable_features_lowercase_scheme);
      69             : RUNTIME_GUARD(envoy_reloadable_features_no_downgrade_to_canonical_name);
      70             : RUNTIME_GUARD(envoy_reloadable_features_no_extension_lookup_by_name);
      71             : RUNTIME_GUARD(envoy_reloadable_features_no_full_scan_certs_on_sni_mismatch);
      72             : RUNTIME_GUARD(envoy_reloadable_features_normalize_host_for_preresolve_dfp_dns);
      73             : RUNTIME_GUARD(envoy_reloadable_features_oauth_make_token_cookie_httponly);
      74             : RUNTIME_GUARD(envoy_reloadable_features_oauth_use_standard_max_age_value);
      75             : RUNTIME_GUARD(envoy_reloadable_features_oauth_use_url_encoding);
      76             : RUNTIME_GUARD(envoy_reloadable_features_original_dst_rely_on_idle_timeout);
      77             : RUNTIME_GUARD(envoy_reloadable_features_overload_manager_error_unknown_action);
      78             : RUNTIME_GUARD(envoy_reloadable_features_proxy_status_upstream_request_timeout);
      79             : RUNTIME_GUARD(envoy_reloadable_features_quic_fix_filter_manager_uaf);
      80             : RUNTIME_GUARD(envoy_reloadable_features_sanitize_te);
      81             : RUNTIME_GUARD(envoy_reloadable_features_send_header_raw_value);
      82             : RUNTIME_GUARD(envoy_reloadable_features_skip_dns_lookup_for_proxied_requests);
      83             : RUNTIME_GUARD(envoy_reloadable_features_ssl_transport_failure_reason_format);
      84             : RUNTIME_GUARD(envoy_reloadable_features_stateful_session_encode_ttl_in_cookie);
      85             : RUNTIME_GUARD(envoy_reloadable_features_stop_decode_metadata_on_local_reply);
      86             : RUNTIME_GUARD(envoy_reloadable_features_test_feature_true);
      87             : RUNTIME_GUARD(envoy_reloadable_features_thrift_allow_negative_field_ids);
      88             : RUNTIME_GUARD(envoy_reloadable_features_thrift_connection_draining);
      89             : RUNTIME_GUARD(envoy_reloadable_features_token_passed_entirely);
      90             : RUNTIME_GUARD(envoy_reloadable_features_uhv_allow_malformed_url_encoding);
      91             : RUNTIME_GUARD(envoy_reloadable_features_upstream_allow_connect_with_2xx);
      92             : RUNTIME_GUARD(envoy_reloadable_features_upstream_wait_for_response_headers_before_disabling_read);
      93             : RUNTIME_GUARD(envoy_reloadable_features_use_cluster_cache_for_alt_protocols_filter);
      94             : RUNTIME_GUARD(envoy_reloadable_features_use_http3_header_normalisation);
      95             : RUNTIME_GUARD(envoy_reloadable_features_validate_connect);
      96             : RUNTIME_GUARD(envoy_reloadable_features_validate_grpc_header_before_log_grpc_status);
      97             : RUNTIME_GUARD(envoy_reloadable_features_validate_upstream_headers);
      98             : RUNTIME_GUARD(envoy_restart_features_send_goaway_for_premature_rst_streams);
      99             : RUNTIME_GUARD(envoy_restart_features_udp_read_normalize_addresses);
     100             : 
     101             : // Begin false flags. These should come with a TODO to flip true.
     102             : // Sentinel and test flag.
     103             : FALSE_RUNTIME_GUARD(envoy_reloadable_features_test_feature_false);
     104             : // TODO(paul-r-gall) Make this enabled by default after additional soak time.
     105             : FALSE_RUNTIME_GUARD(envoy_reloadable_features_streaming_shadow);
     106             : // TODO(adisuissa) reset to true to enable unified mux by default
     107             : FALSE_RUNTIME_GUARD(envoy_reloadable_features_unified_mux);
     108             : // Used to track if runtime is initialized.
     109             : FALSE_RUNTIME_GUARD(envoy_reloadable_features_runtime_initialized);
     110             : // TODO(mattklein123): Flip this to true and/or remove completely once verified by Envoy Mobile.
     111             : // TODO(mattklein123): Also unit test this if this sticks and this becomes the default for Apple &
     112             : // Android.
     113             : FALSE_RUNTIME_GUARD(envoy_reloadable_features_always_use_v6);
     114             : // TODO(pradeepcrao) reset this to true after 2 releases (1.27)
     115             : FALSE_RUNTIME_GUARD(envoy_reloadable_features_enable_include_histograms);
     116             : // TODO(wbpcode) complete remove this feature is no one use it.
     117             : FALSE_RUNTIME_GUARD(envoy_reloadable_features_refresh_rtt_after_request);
     118             : // TODO(danzh) false deprecate it once QUICHE has its own enable/disable flag.
     119             : FALSE_RUNTIME_GUARD(envoy_reloadable_features_quic_reject_all);
     120             : // TODO(steveWang) flip this to true after this is verified in prod.
     121             : FALSE_RUNTIME_GUARD(envoy_reloadable_features_quiche_use_mem_slice_releasor_api);
     122             : // TODO(suniltheta): Once the newly added http async technique is stabilized move it under
     123             : // RUNTIME_GUARD so that this option becomes default enabled. Once this option proves effective
     124             : // remove the feature flag and remove code path that relies on old technique to fetch credentials
     125             : // via libcurl and remove the bazel steps to pull and test the curl dependency.
     126             : FALSE_RUNTIME_GUARD(envoy_reloadable_features_use_http_client_to_fetch_aws_credentials);
     127             : // TODO(adisuissa): enable by default once this is tested in prod.
     128             : FALSE_RUNTIME_GUARD(envoy_restart_features_use_eds_cache_for_ads);
     129             : // TODO(#10646) change to true when UHV is sufficiently tested
     130             : // For more information about Universal Header Validation, please see
     131             : // https://github.com/envoyproxy/envoy/issues/10646
     132             : FALSE_RUNTIME_GUARD(envoy_reloadable_features_enable_universal_header_validator);
     133             : // TODO(pksohn): enable after fixing https://github.com/envoyproxy/envoy/issues/29930
     134             : FALSE_RUNTIME_GUARD(envoy_reloadable_features_quic_defer_logging_to_ack_listener);
     135             : // TODO(#31276): flip this to true after some test time.
     136             : FALSE_RUNTIME_GUARD(envoy_restart_features_use_fast_protobuf_hash);
     137             : 
     138             : // Block of non-boolean flags. Use of int flags is deprecated. Do not add more.
     139             : ABSL_FLAG(uint64_t, re2_max_program_size_error_level, 100, ""); // NOLINT
     140             : ABSL_FLAG(uint64_t, re2_max_program_size_warn_level,            // NOLINT
     141             :           std::numeric_limits<uint32_t>::max(), "");            // NOLINT
     142             : 
     143             : namespace Envoy {
     144             : namespace Runtime {
     145             : namespace {
     146             : 
     147        3402 : std::string swapPrefix(std::string name) {
     148        3402 :   return absl::StrReplaceAll(name, {{"envoy_", "envoy."}, {"features_", "features."}});
     149        3402 : }
     150             : 
     151             : } // namespace
     152             : 
     153             : // This is a singleton class to map Envoy style flag names to absl flags
     154             : class RuntimeFeatures {
     155             : public:
     156             :   RuntimeFeatures();
     157             : 
     158             :   // Get the command line flag corresponding to the Envoy style feature name, or
     159             :   // nullptr if it is not a registered flag.
     160       75916 :   absl::CommandLineFlag* getFlag(absl::string_view feature) const {
     161       75916 :     auto it = all_features_.find(feature);
     162       75916 :     if (it == all_features_.end()) {
     163         220 :       return nullptr;
     164         220 :     }
     165       75696 :     return it->second;
     166       75916 :   }
     167             : 
     168             : private:
     169             :   absl::flat_hash_map<std::string, absl::CommandLineFlag*> all_features_;
     170             : };
     171             : 
     172             : using RuntimeFeaturesDefaults = ConstSingleton<RuntimeFeatures>;
     173             : 
     174          42 : RuntimeFeatures::RuntimeFeatures() {
     175          42 :   absl::flat_hash_map<absl::string_view, absl::CommandLineFlag*> flags = absl::GetAllFlags();
     176        8107 :   for (auto& it : flags) {
     177        8107 :     absl::string_view name = it.second->Name();
     178        8107 :     if ((!absl::StartsWith(name, "envoy_reloadable_features_") &&
     179        8107 :          !absl::StartsWith(name, "envoy_restart_features_")) ||
     180        8107 :         !it.second->TryGet<bool>().has_value()) {
     181        4705 :       continue;
     182        4705 :     }
     183        3402 :     std::string envoy_name = swapPrefix(std::string(name));
     184        3402 :     all_features_.emplace(envoy_name, it.second);
     185        3402 :   }
     186          42 : }
     187             : 
     188         126 : bool hasRuntimePrefix(absl::string_view feature) {
     189             :   // Track Envoy reloadable and restart features, excluding synthetic QUIC flags
     190             :   // which are not tracked in the list below.
     191         126 :   return (absl::StartsWith(feature, "envoy.reloadable_features.") &&
     192         126 :           !absl::StartsWith(feature, "envoy.reloadable_features.FLAGS_envoy_quic")) ||
     193         126 :          absl::StartsWith(feature, "envoy.restart_features.");
     194         126 : }
     195             : 
     196         918 : bool isRuntimeFeature(absl::string_view feature) {
     197         918 :   return RuntimeFeaturesDefaults::get().getFlag(feature) != nullptr;
     198         918 : }
     199             : 
     200       72726 : bool runtimeFeatureEnabled(absl::string_view feature) {
     201       72726 :   absl::CommandLineFlag* flag = RuntimeFeaturesDefaults::get().getFlag(feature);
     202       72726 :   if (flag == nullptr) {
     203           0 :     IS_ENVOY_BUG(absl::StrCat("Unable to find runtime feature ", feature));
     204           0 :     return false;
     205           0 :   }
     206             :   // We validate in map creation that the flag is a boolean.
     207       72726 :   return flag->TryGet<bool>().value();
     208       72726 : }
     209             : 
     210           0 : uint64_t getInteger(absl::string_view feature, uint64_t default_value) {
     211             :   // DO NOT ADD MORE FLAGS HERE. This function deprecated.
     212           0 :   if (absl::StartsWith(feature, "re2.")) {
     213           0 :     if (feature == "re2.max_program_size.error_level") {
     214           0 :       return absl::GetFlag(FLAGS_re2_max_program_size_error_level);
     215           0 :     } else if (feature == "re2.max_program_size.warn_level") {
     216           0 :       return absl::GetFlag(FLAGS_re2_max_program_size_warn_level);
     217           0 :     }
     218           0 :   }
     219           0 :   IS_ENVOY_BUG(absl::StrCat("requested an unsupported integer ", feature));
     220           0 :   return default_value;
     221           0 : }
     222             : 
     223        1701 : void markRuntimeInitialized() {
     224        1701 :   maybeSetRuntimeGuard("envoy.reloadable_features.runtime_initialized", true);
     225        1701 : }
     226             : 
     227         237 : bool isRuntimeInitialized() {
     228         237 :   return runtimeFeatureEnabled("envoy.reloadable_features.runtime_initialized");
     229         237 : }
     230             : 
     231        2273 : void maybeSetRuntimeGuard(absl::string_view name, bool value) {
     232        2273 :   absl::CommandLineFlag* flag = RuntimeFeaturesDefaults::get().getFlag(name);
     233        2273 :   if (flag == nullptr) {
     234           0 :     IS_ENVOY_BUG(absl::StrCat("Unable to find runtime feature ", name));
     235           0 :     return;
     236           0 :   }
     237        2273 :   std::string err;
     238        2273 :   flag->ParseFrom(value ? "true" : "false", &err);
     239        2273 : }
     240             : 
     241           0 : void maybeSetDeprecatedInts(absl::string_view name, uint32_t value) {
     242           0 :   if (!absl::StartsWith(name, "envoy.") && !absl::StartsWith(name, "re2.")) {
     243           0 :     return;
     244           0 :   }
     245             : 
     246             :   // DO NOT ADD MORE FLAGS HERE. This function deprecated.
     247           0 :   else if (name == "re2.max_program_size.error_level") {
     248           0 :     absl::SetFlag(&FLAGS_re2_max_program_size_error_level, value);
     249           0 :   } else if (name == "re2.max_program_size.warn_level") {
     250           0 :     absl::SetFlag(&FLAGS_re2_max_program_size_warn_level, value);
     251           0 :   }
     252           0 : }
     253             : 
     254             : } // namespace Runtime
     255             : } // namespace Envoy

Generated by: LCOV version 1.15