linux/net/netfilter/ipvs/ip_vs_lc.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * IPVS:        Least-Connection Scheduling module
   4 *
   5 * Authors:     Wensong Zhang <wensong@linuxvirtualserver.org>
   6 *
   7 * Changes:
   8 *     Wensong Zhang            :     added the ip_vs_lc_update_svc
   9 *     Wensong Zhang            :     added any dest with weight=0 is quiesced
  10 */
  11
  12#define KMSG_COMPONENT "IPVS"
  13#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
  14
  15#include <linux/module.h>
  16#include <linux/kernel.h>
  17
  18#include <net/ip_vs.h>
  19
  20/*
  21 *      Least Connection scheduling
  22 */
  23static struct ip_vs_dest *
  24ip_vs_lc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
  25                  struct ip_vs_iphdr *iph)
  26{
  27        struct ip_vs_dest *dest, *least = NULL;
  28        unsigned int loh = 0, doh;
  29
  30        IP_VS_DBG(6, "%s(): Scheduling...\n", __func__);
  31
  32        /*
  33         * Simply select the server with the least number of
  34         *        (activeconns<<5) + inactconns
  35         * Except whose weight is equal to zero.
  36         * If the weight is equal to zero, it means that the server is
  37         * quiesced, the existing connections to the server still get
  38         * served, but no new connection is assigned to the server.
  39         */
  40
  41        list_for_each_entry_rcu(dest, &svc->destinations, n_list) {
  42                if ((dest->flags & IP_VS_DEST_F_OVERLOAD) ||
  43                    atomic_read(&dest->weight) == 0)
  44                        continue;
  45                doh = ip_vs_dest_conn_overhead(dest);
  46                if (!least || doh < loh) {
  47                        least = dest;
  48                        loh = doh;
  49                }
  50        }
  51
  52        if (!least)
  53                ip_vs_scheduler_err(svc, "no destination available");
  54        else
  55                IP_VS_DBG_BUF(6, "LC: server %s:%u activeconns %d "
  56                              "inactconns %d\n",
  57                              IP_VS_DBG_ADDR(least->af, &least->addr),
  58                              ntohs(least->port),
  59                              atomic_read(&least->activeconns),
  60                              atomic_read(&least->inactconns));
  61
  62        return least;
  63}
  64
  65
  66static struct ip_vs_scheduler ip_vs_lc_scheduler = {
  67        .name =                 "lc",
  68        .refcnt =               ATOMIC_INIT(0),
  69        .module =               THIS_MODULE,
  70        .n_list =               LIST_HEAD_INIT(ip_vs_lc_scheduler.n_list),
  71        .schedule =             ip_vs_lc_schedule,
  72};
  73
  74
  75static int __init ip_vs_lc_init(void)
  76{
  77        return register_ip_vs_scheduler(&ip_vs_lc_scheduler) ;
  78}
  79
  80static void __exit ip_vs_lc_cleanup(void)
  81{
  82        unregister_ip_vs_scheduler(&ip_vs_lc_scheduler);
  83        synchronize_rcu();
  84}
  85
  86module_init(ip_vs_lc_init);
  87module_exit(ip_vs_lc_cleanup);
  88MODULE_LICENSE("GPL");
  89