Skip to content

Commit

Permalink
wlc mowed to from dataplane to controlplane
Browse files Browse the repository at this point in the history
  • Loading branch information
levon-a-akopian committed Jun 26, 2024
1 parent d508ad3 commit 62f51a9
Show file tree
Hide file tree
Showing 3 changed files with 157 additions and 48 deletions.
152 changes: 151 additions & 1 deletion controlplane/balancer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -886,6 +886,12 @@ void balancer_t::flush_reals(common::idp::updateGlobalBaseBalancer::request& bal
}
}

auto reals_wlc = reals_wlc_weight.find(key);
if (reals_wlc != reals_wlc_weight.end() && reals_wlc->second.has_value())
{
effective_weight = reals_wlc->second.value();
}

uint32_t real_unordered_id = 0;
{
std::lock_guard<std::mutex> guard(reals_unordered_mutex);
Expand Down Expand Up @@ -929,8 +935,152 @@ void balancer_t::reconfigure_wlc_thread()
{
while (!flagStop)
{
balancer_real_flush();
if (balancer_t::reconfigure_wlc())
{
balancer_real_flush();
}

std::this_thread::sleep_for(std::chrono::seconds(YANET_CONFIG_BALANCER_WLC_RECONFIGURE));
}
}

bool balancer_t::reconfigure_wlc()
{
bool wlc_weight_changed = false;

common::idp::updateGlobalBaseBalancer::request balancer;
const auto balancer_real_connections = dataplane.balancer_real_connections();

std::lock_guard<std::mutex> guard(reals_enabled_mutex);

for (const auto& [module_name, balancer] : generations_config.current().config_balancers)
{

for (const auto& [service_id,
virtual_ip,
proto,
virtual_port,
version,
scheduler,
scheduler_params,
forwarding_method,
flags,
ipv4_outer_source_network,
ipv6_outer_source_network,
reals] : balancer.services)
{
(void)flags;
(void)version;
(void)forwarding_method;
(void)ipv4_outer_source_network;
(void)ipv6_outer_source_network;

if (scheduler != ::balancer::scheduler::wlc)
{
continue;
}

if (service_id >= YANET_CONFIG_BALANCER_SERVICES_SIZE)
{
continue;
}

std::vector<std::tuple<balancer::real_key_global_t, uint32_t, uint32_t>> service_reals_usage_info;
uint32_t connection_sum = 0;
uint32_t weight_sum = 0;

for (const auto& [real_ip, real_port, weight] : reals)
{
balancer::real_key_global_t key = {module_name, {virtual_ip, proto, virtual_port}, {real_ip, real_port}};
uint32_t effective_weight = weight;
{
auto it = reals_enabled.find(key);
if (it != reals_enabled.end())
{
if (it->second.has_value())
{
effective_weight = it->second.value();
}
}
}

weight_sum += effective_weight;

// don`t count connections for disabled reals - it can make other reals "feel" underloaded
if (effective_weight == 0)
{
continue;
}

common::idp::balancer_real_connections::real_key_t real_connections_key = {balancer.balancer_id,
virtual_ip,
proto,
virtual_port.value(),
real_ip,
real_port.value()};
uint32_t connections = 0;
for (auto& [socket_id, real_connections] : balancer_real_connections)
{
(void)socket_id;

auto it = real_connections.find(real_connections_key);
if (it == real_connections.end())
{
continue;
}
connections += it->second;
}

connection_sum += connections;

service_reals_usage_info.emplace_back(key,
effective_weight,
connections);
}

for (auto [key,
effective_weight,
connections] : service_reals_usage_info)
{
uint32_t wlc_power = scheduler_params.wlc_power;
if (wlc_power < 1 || wlc_power > 100)
{
wlc_power = YANET_CONFIG_BALANCER_WLC_DEFAULT_POWER;
}

effective_weight = calculate_wlc_weight(effective_weight, connections, weight_sum, connection_sum, wlc_power);

if (reals_wlc_weight[key] != effective_weight)
{
reals_wlc_weight[key] = effective_weight;
real_updates.insert(key);
if (in_reload)
{
real_reload_updates.insert(key);
}
wlc_weight_changed = true;
}
}
}
}

return wlc_weight_changed;
}

uint32_t balancer_t::calculate_wlc_weight(uint32_t weight, uint32_t connections, uint32_t weight_sum, uint32_t connection_sum, uint32_t wlc_power)
{
if (weight == 0 || weight_sum == 0 || connection_sum < weight_sum)
{
return weight;
}

auto wlc_ratio = std::max(1.0, wlc_power * (1 - 1.0 * connections * weight_sum / connection_sum / weight));
auto wlc_weight = (uint32_t)(weight * wlc_ratio);

if (wlc_weight > YANET_CONFIG_BALANCER_REAL_WEIGHT_MAX)
{
wlc_weight = YANET_CONFIG_BALANCER_REAL_WEIGHT_MAX;
}

return wlc_weight;
}
6 changes: 6 additions & 0 deletions controlplane/balancer.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@ class balancer_t : public module_t, common::icp_proto::BalancerService

std::map<balancer::real_key_global_t, std::optional<uint32_t>> reals_enabled;

std::map<balancer::real_key_global_t, std::optional<uint32_t>> reals_wlc_weight;

// The set contains all reals touched after the last one flush operation
std::set<balancer::real_key_global_t> real_updates;

Expand All @@ -143,7 +145,11 @@ class balancer_t : public module_t, common::icp_proto::BalancerService
friend class telegraf_t;
counter_t<balancer::service_counter_key_t, (size_t)balancer::service_counter::size> service_counters;
counter_t<balancer::real_counter_key_t, (size_t)balancer::real_counter::size> real_counters;

void RealFind(google::protobuf::RpcController* controller, const common::icp_proto::BalancerRealFindRequest* request, common::icp_proto::BalancerRealFindResponse* response, google::protobuf::Closure* done) override;
void Real(google::protobuf::RpcController* controller, const ::common::icp_proto::BalancerRealRequest* request, ::common::icp_proto::Empty* response, ::google::protobuf::Closure* done) override;
void RealFlush(google::protobuf::RpcController* controller, const ::common::icp_proto::Empty* request, ::common::icp_proto::Empty* response, ::google::protobuf::Closure* done) override;

bool reconfigure_wlc();
uint32_t calculate_wlc_weight(uint32_t weight, uint32_t connections, uint32_t weight_sum, uint32_t connection_sum, uint32_t wlc_power);
};
47 changes: 0 additions & 47 deletions dataplane/globalbase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1610,16 +1610,6 @@ eResult generation::update_balancer_unordered_real(const common::idp::updateGlob
return eResult::success;
}

double wlc_ratio(uint32_t weight, uint32_t connections, uint32_t weight_sum, uint32_t connection_sum, uint32_t power)
{
if (weight == 0 || weight_sum == 0 || connection_sum < weight_sum)
{
return 1;
}
auto a = power * (1 - 1.0 * connections * weight_sum / connection_sum / weight);
return std::max(1.0, a);
}

inline uint64_t generation::count_real_connections(uint32_t counter_id)
{
uint64_t sessions_created = 0;
Expand Down Expand Up @@ -1653,27 +1643,6 @@ void generation::evaluate_service_ring()
for (uint32_t service_idx = 0; service_idx < balancer_services_count; ++service_idx)
{
balancer_service_t* service = balancer_services + balancer_active_services[service_idx];
uint64_t connection_sum = 0;
uint32_t weight_sum = 0;
if (service->scheduler == ::balancer::scheduler::wlc)
{
for (uint32_t real_idx = service->real_start;
real_idx < service->real_start + service->real_size;
++real_idx)
{
uint32_t real_id = balancer_service_reals[real_idx];
balancer_real_state_t* state = balancer_real_states + real_id;
// don`t count connections for disabled reals - it can make other reals "feel" underloaded
if (state->weight == 0)
{
continue;
}
weight_sum += state->weight;

const balancer_real_t& real = balancer_reals[real_id];
connection_sum += count_real_connections(real.counter_id);
}
}

balancer_service_range_t* range = ring->ranges + balancer_active_services[service_idx];

Expand All @@ -1683,7 +1652,6 @@ void generation::evaluate_service_ring()
++real_idx)
{
uint32_t real_id = balancer_service_reals[real_idx];
const balancer_real_t& real = balancer_reals[real_id];
balancer_real_state_t* state = balancer_real_states + real_id;

if (state->weight == 0)
Expand All @@ -1693,21 +1661,6 @@ void generation::evaluate_service_ring()

auto weight = state->weight;

if (service->scheduler == ::balancer::scheduler::wlc)
{
uint64_t real_connections = count_real_connections(real.counter_id);

weight = (int)(weight * wlc_ratio(state->weight, real_connections, weight_sum, connection_sum, service->wlc_power));
// todo check weight change
}

// clamp weight to a maximum possible value
if (weight > YANET_CONFIG_BALANCER_REAL_WEIGHT_MAX)
{
// TODO: think about accounting the clamping
weight = YANET_CONFIG_BALANCER_REAL_WEIGHT_MAX;
}

while (weight-- > 0)
{
ring->reals[weight_pos++] = real_id;
Expand Down

0 comments on commit 62f51a9

Please sign in to comment.