linux/net/netfilter/ipvs/ip_vs_wlc.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * IPVS:        Weighted Least-Connection Scheduling module
   4 *
   5 * Authors:     Wensong Zhang <wensong@linuxvirtualserver.org>
   6 *              Peter Kese <peter.kese@ijs.si>
   7 *
   8 * Changes:
   9 *     Wensong Zhang            :     changed the ip_vs_wlc_schedule to return dest
  10 *     Wensong Zhang            :     changed to use the inactconns in scheduling
  11 *     Wensong Zhang            :     changed some comestics things for debugging
  12 *     Wensong Zhang            :     changed for the d-linked destination list
  13 *     Wensong Zhang            :     added the ip_vs_wlc_update_svc
  14 *     Wensong Zhang            :     added any dest with weight=0 is quiesced
  15 */
  16
  17#define KMSG_COMPONENT "IPVS"
  18#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
  19
  20#include <linux/module.h>
  21#include <linux/kernel.h>
  22
  23#include <net/ip_vs.h>
  24
  25/*
  26 *      Weighted Least Connection scheduling
  27 */
  28static struct ip_vs_dest *
  29ip_vs_wlc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
  30                   struct ip_vs_iphdr *iph)
  31{
  32        struct ip_vs_dest *dest, *least;
  33        int loh, doh;
  34
  35        IP_VS_DBG(6, "ip_vs_wlc_schedule(): Scheduling...\n");
  36
  37        /*
  38         * We calculate the load of each dest server as follows:
  39         *                (dest overhead) / dest->weight
  40         *
  41         * Remember -- no floats in kernel mode!!!
  42         * The comparison of h1*w2 > h2*w1 is equivalent to that of
  43         *                h1/w1 > h2/w2
  44         * if every weight is larger than zero.
  45         *
  46         * The server with weight=0 is quiesced and will not receive any
  47         * new connections.
  48         */
  49
  50        list_for_each_entry_rcu(dest, &svc->destinations, n_list) {
  51                if (!(dest->flags & IP_VS_DEST_F_OVERLOAD) &&
  52                    atomic_read(&dest->weight) > 0) {
  53                        least = dest;
  54                        loh = ip_vs_dest_conn_overhead(least);
  55                        goto nextstage;
  56                }
  57        }
  58        ip_vs_scheduler_err(svc, "no destination available");
  59        return NULL;
  60
  61        /*
  62         *    Find the destination with the least load.
  63         */
  64  nextstage:
  65        list_for_each_entry_continue_rcu(dest, &svc->destinations, n_list) {
  66                if (dest->flags & IP_VS_DEST_F_OVERLOAD)
  67                        continue;
  68                doh = ip_vs_dest_conn_overhead(dest);
  69                if ((__s64)loh * atomic_read(&dest->weight) >
  70                    (__s64)doh * atomic_read(&least->weight)) {
  71                        least = dest;
  72                        loh = doh;
  73                }
  74        }
  75
  76        IP_VS_DBG_BUF(6, "WLC: server %s:%u "
  77                      "activeconns %d refcnt %d weight %d overhead %d\n",
  78                      IP_VS_DBG_ADDR(least->af, &least->addr),
  79                      ntohs(least->port),
  80                      atomic_read(&least->activeconns),
  81                      refcount_read(&least->refcnt),
  82                      atomic_read(&least->weight), loh);
  83
  84        return least;
  85}
  86
  87
  88static struct ip_vs_scheduler ip_vs_wlc_scheduler =
  89{
  90        .name =                 "wlc",
  91        .refcnt =               ATOMIC_INIT(0),
  92        .module =               THIS_MODULE,
  93        .n_list =               LIST_HEAD_INIT(ip_vs_wlc_scheduler.n_list),
  94        .schedule =             ip_vs_wlc_schedule,
  95};
  96
  97
  98static int __init ip_vs_wlc_init(void)
  99{
 100        return register_ip_vs_scheduler(&ip_vs_wlc_scheduler);
 101}
 102
 103static void __exit ip_vs_wlc_cleanup(void)
 104{
 105        unregister_ip_vs_scheduler(&ip_vs_wlc_scheduler);
 106        synchronize_rcu();
 107}
 108
 109module_init(ip_vs_wlc_init);
 110module_exit(ip_vs_wlc_cleanup);
 111MODULE_LICENSE("GPL");
 112