Skip to content

Commit bdb8b53

Browse files
committed
policy: More robust removeInitManager
Replace the nullptr init manager with a dedicated parked_init_manager_, and inspect it for unintended use so that we can log warnings as needed. This compiles without relying on undefined behavior, and still provides a signal if targets are added after initialization has completed. Signed-off-by: Jarno Rajahalme <jarno@isovalent.com>
1 parent 9b05687 commit bdb8b53

2 files changed

Lines changed: 44 additions & 9 deletions

File tree

cilium/network_policy.cc

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <utility>
1616
#include <vector>
1717

18+
#include "envoy/admin/v3/init_dump.pb.h"
1819
#include "envoy/common/exception.h"
1920
#include "envoy/common/matchers.h"
2021
#include "envoy/common/optref.h"
@@ -1876,11 +1877,13 @@ NetworkPolicyMapImpl::NetworkPolicyMapImpl(Server::Configuration::FactoryContext
18761877
std::make_shared<Server::Configuration::TransportSocketFactoryContextImpl>(
18771878
context_, *npds_stats_scope_,
18781879
context_.messageValidationContext().dynamicValidationVisitor())),
1880+
parked_init_manager_(std::make_unique<Init::ManagerImpl>("Cilium NetworkPolicyMap parked")),
18791881
npds_config_(npds_config),
18801882
stats_{ALL_CILIUM_POLICY_STATS(POOL_COUNTER(*policy_stats_scope_),
18811883
POOL_HISTOGRAM(*policy_stats_scope_))} {
18821884
// Use listener init manager for subscription initialization
18831885
context.initManager().add(init_target_);
1886+
transport_factory_context_->setInitManager(*parked_init_manager_);
18841887

18851888
// Allocate an initial policy map so that the map pointer is never a nullptr
18861889
store(new RawPolicyMap());
@@ -1921,15 +1924,42 @@ bool NetworkPolicyMapImpl::isNewStream() {
19211924

19221925
// removeInitManager must be called at the end of each policy update
19231926
void NetworkPolicyMapImpl::removeInitManager() {
1924-
// Remove the local init manager from the transport factory context
1925-
#ifdef __clang__
1926-
#pragma clang diagnostic push
1927-
#pragma clang diagnostic ignored "-Wnull-dereference"
1928-
#endif
1929-
transport_factory_context_->setInitManager(*static_cast<Init::Manager*>(nullptr));
1930-
#ifdef __clang__
1931-
#pragma clang diagnostic pop
1932-
#endif
1927+
RELEASE_ASSERT(parked_init_manager_ != nullptr, "parked init manager must exist");
1928+
1929+
const bool parked_wrong_state =
1930+
parked_init_manager_->state() != Init::Manager::State::Uninitialized;
1931+
if (parked_wrong_state) {
1932+
ENVOY_LOG(warn,
1933+
"Cilium NetworkPolicyMap parked init manager unexpectedly reached state {}; "
1934+
"replacing it before re-installing",
1935+
static_cast<int>(parked_init_manager_->state()));
1936+
}
1937+
1938+
envoy::admin::v3::UnreadyTargetsDumps parked_dumps;
1939+
parked_init_manager_->dumpUnreadyTargets(parked_dumps);
1940+
bool parked_has_targets = false;
1941+
for (const auto& parked_dump : parked_dumps.unready_targets_dumps()) {
1942+
if (!parked_dump.target_names().empty()) {
1943+
parked_has_targets = true;
1944+
ENVOY_LOG(
1945+
warn,
1946+
"Cilium NetworkPolicyMap parked init manager unexpectedly accumulated targets [{}]{}; "
1947+
"replacing it before re-installing",
1948+
fmt::join(parked_dump.target_names(), ", "),
1949+
parked_wrong_state
1950+
? fmt::format(" in state {}", static_cast<int>(parked_init_manager_->state()))
1951+
: "");
1952+
}
1953+
}
1954+
1955+
// replace parked init manager if it got to a bad state
1956+
if (parked_wrong_state || parked_has_targets) {
1957+
parked_init_manager_ = std::make_unique<Init::ManagerImpl>("Cilium NetworkPolicyMap parked");
1958+
}
1959+
1960+
// Restore the parked init manager after a policy-version-specific init manager has been
1961+
// installed for the duration of the update.
1962+
transport_factory_context_->setInitManager(*parked_init_manager_);
19331963
}
19341964

19351965
// onConfigUpdate parses the new network policy resources, allocates a new policy map and atomically

cilium/network_policy.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include "source/common/common/logger.h"
3434
#include "source/common/common/macros.h"
3535
#include "source/common/common/thread.h"
36+
#include "source/common/init/manager_impl.h"
3637
#include "source/common/init/target_impl.h"
3738
#include "source/common/protobuf/message_validator_impl.h"
3839
#include "source/common/protobuf/protobuf.h"
@@ -328,6 +329,10 @@ class NetworkPolicyMapImpl : public Envoy::Config::SubscriptionCallbacks,
328329
Init::TargetImpl init_target_;
329330
std::shared_ptr<Server::Configuration::TransportSocketFactoryContextImpl>
330331
transport_factory_context_;
332+
// Between policy updates, keep a dormant init manager installed so unexpected late init-target
333+
// registrations do not hit the listener's already-initialized manager. If it accumulates targets
334+
// while parked, log and rotate it out before making it active again.
335+
std::unique_ptr<Init::ManagerImpl> parked_init_manager_;
331336

332337
std::unique_ptr<Envoy::Config::Subscription> subscription_;
333338
envoy::config::core::v3::ConfigSource npds_config_;

0 commit comments

Comments
 (0)