linux/net/netfilter/ipvs/ip_vs_wlc.c
<<
>>
Prefs
   1/*
   2 * IPVS:        Weighted Least-Connection Scheduling module
   3 *
   4 * Authors:     Wensong Zhang <wensong@linuxvirtualserver.org>
   5 *              Peter Kese <peter.kese@ijs.si>
   6 *
   7 *              This program is free software; you can redistribute it and/or
   8 *              modify it under the terms of the GNU General Public License
   9 *              as published by the Free Software Foundation; either version
  10 *              2 of the License, or (at your option) any later version.
  11 *
  12 * Changes:
  13 *     Wensong Zhang            :     changed the ip_vs_wlc_schedule to return dest
  14 *     Wensong Zhang            :     changed to use the inactconns in scheduling
  15 *     Wensong Zhang            :     changed some comestics things for debugging
  16 *     Wensong Zhang            :     changed for the d-linked destination list
  17 *     Wensong Zhang            :     added the ip_vs_wlc_update_svc
  18 *     Wensong Zhang            :     added any dest with weight=0 is quiesced
  19 *
  20 */
  21
  22#include <linux/module.h>
  23#include <linux/kernel.h>
  24
  25#include <net/ip_vs.h>
  26
  27
  28static inline unsigned int
  29ip_vs_wlc_dest_overhead(struct ip_vs_dest *dest)
  30{
  31        /*
  32         * We think the overhead of processing active connections is 256
  33         * times higher than that of inactive connections in average. (This
  34         * 256 times might not be accurate, we will change it later) We
  35         * use the following formula to estimate the overhead now:
  36         *                dest->activeconns*256 + dest->inactconns
  37         */
  38        return (atomic_read(&dest->activeconns) << 8) +
  39                atomic_read(&dest->inactconns);
  40}
  41
  42
  43/*
  44 *      Weighted Least Connection scheduling
  45 */
  46static struct ip_vs_dest *
  47ip_vs_wlc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
  48{
  49        struct ip_vs_dest *dest, *least;
  50        unsigned int loh, doh;
  51
  52        IP_VS_DBG(6, "ip_vs_wlc_schedule(): Scheduling...\n");
  53
  54        /*
  55         * We calculate the load of each dest server as follows:
  56         *                (dest overhead) / dest->weight
  57         *
  58         * Remember -- no floats in kernel mode!!!
  59         * The comparison of h1*w2 > h2*w1 is equivalent to that of
  60         *                h1/w1 > h2/w2
  61         * if every weight is larger than zero.
  62         *
  63         * The server with weight=0 is quiesced and will not receive any
  64         * new connections.
  65         */
  66
  67        list_for_each_entry(dest, &svc->destinations, n_list) {
  68                if (!(dest->flags & IP_VS_DEST_F_OVERLOAD) &&
  69                    atomic_read(&dest->weight) > 0) {
  70                        least = dest;
  71                        loh = ip_vs_wlc_dest_overhead(least);
  72                        goto nextstage;
  73                }
  74        }
  75        return NULL;
  76
  77        /*
  78         *    Find the destination with the least load.
  79         */
  80  nextstage:
  81        list_for_each_entry_continue(dest, &svc->destinations, n_list) {
  82                if (dest->flags & IP_VS_DEST_F_OVERLOAD)
  83                        continue;
  84                doh = ip_vs_wlc_dest_overhead(dest);
  85                if (loh * atomic_read(&dest->weight) >
  86                    doh * atomic_read(&least->weight)) {
  87                        least = dest;
  88                        loh = doh;
  89                }
  90        }
  91
  92        IP_VS_DBG_BUF(6, "WLC: server %s:%u "
  93                      "activeconns %d refcnt %d weight %d overhead %d\n",
  94                      IP_VS_DBG_ADDR(svc->af, &least->addr), ntohs(least->port),
  95                      atomic_read(&least->activeconns),
  96                      atomic_read(&least->refcnt),
  97                      atomic_read(&least->weight), loh);
  98
  99        return least;
 100}
 101
 102
 103static struct ip_vs_scheduler ip_vs_wlc_scheduler =
 104{
 105        .name =                 "wlc",
 106        .refcnt =               ATOMIC_INIT(0),
 107        .module =               THIS_MODULE,
 108        .n_list =               LIST_HEAD_INIT(ip_vs_wlc_scheduler.n_list),
 109#ifdef CONFIG_IP_VS_IPV6
 110        .supports_ipv6 =        1,
 111#endif
 112        .schedule =             ip_vs_wlc_schedule,
 113};
 114
 115
 116static int __init ip_vs_wlc_init(void)
 117{
 118        return register_ip_vs_scheduler(&ip_vs_wlc_scheduler);
 119}
 120
 121static void __exit ip_vs_wlc_cleanup(void)
 122{
 123        unregister_ip_vs_scheduler(&ip_vs_wlc_scheduler);
 124}
 125
 126module_init(ip_vs_wlc_init);
 127module_exit(ip_vs_wlc_cleanup);
 128MODULE_LICENSE("GPL");
 129