root/net/netfilter/ipvs/ip_vs_wlc.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ip_vs_wlc_schedule
  2. ip_vs_wlc_init
  3. ip_vs_wlc_cleanup

   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  */
  28 static struct ip_vs_dest *
  29 ip_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 
  88 static 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 
  98 static int __init ip_vs_wlc_init(void)
  99 {
 100         return register_ip_vs_scheduler(&ip_vs_wlc_scheduler);
 101 }
 102 
 103 static void __exit ip_vs_wlc_cleanup(void)
 104 {
 105         unregister_ip_vs_scheduler(&ip_vs_wlc_scheduler);
 106         synchronize_rcu();
 107 }
 108 
 109 module_init(ip_vs_wlc_init);
 110 module_exit(ip_vs_wlc_cleanup);
 111 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */