linux/net/netfilter/ipvs/ip_vs_lc.c
<<
>>
Prefs
   1/*
   2 * IPVS:        Least-Connection Scheduling module
   3 *
   4 * Authors:     Wensong Zhang <wensong@linuxvirtualserver.org>
   5 *
   6 *              This program is free software; you can redistribute it and/or
   7 *              modify it under the terms of the GNU General Public License
   8 *              as published by the Free Software Foundation; either version
   9 *              2 of the License, or (at your option) any later version.
  10 *
  11 * Changes:
  12 *     Wensong Zhang            :     added the ip_vs_lc_update_svc
  13 *     Wensong Zhang            :     added any dest with weight=0 is quiesced
  14 *
  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 *      Least Connection scheduling
  27 */
  28static struct ip_vs_dest *
  29ip_vs_lc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
  30{
  31        struct ip_vs_dest *dest, *least = NULL;
  32        unsigned int loh = 0, doh;
  33
  34        IP_VS_DBG(6, "%s(): Scheduling...\n", __func__);
  35
  36        /*
  37         * Simply select the server with the least number of
  38         *        (activeconns<<5) + inactconns
  39         * Except whose weight is equal to zero.
  40         * If the weight is equal to zero, it means that the server is
  41         * quiesced, the existing connections to the server still get
  42         * served, but no new connection is assigned to the server.
  43         */
  44
  45        list_for_each_entry_rcu(dest, &svc->destinations, n_list) {
  46                if ((dest->flags & IP_VS_DEST_F_OVERLOAD) ||
  47                    atomic_read(&dest->weight) == 0)
  48                        continue;
  49                doh = ip_vs_dest_conn_overhead(dest);
  50                if (!least || doh < loh) {
  51                        least = dest;
  52                        loh = doh;
  53                }
  54        }
  55
  56        if (!least)
  57                ip_vs_scheduler_err(svc, "no destination available");
  58        else
  59                IP_VS_DBG_BUF(6, "LC: server %s:%u activeconns %d "
  60                              "inactconns %d\n",
  61                              IP_VS_DBG_ADDR(svc->af, &least->addr),
  62                              ntohs(least->port),
  63                              atomic_read(&least->activeconns),
  64                              atomic_read(&least->inactconns));
  65
  66        return least;
  67}
  68
  69
  70static struct ip_vs_scheduler ip_vs_lc_scheduler = {
  71        .name =                 "lc",
  72        .refcnt =               ATOMIC_INIT(0),
  73        .module =               THIS_MODULE,
  74        .n_list =               LIST_HEAD_INIT(ip_vs_lc_scheduler.n_list),
  75        .schedule =             ip_vs_lc_schedule,
  76};
  77
  78
  79static int __init ip_vs_lc_init(void)
  80{
  81        return register_ip_vs_scheduler(&ip_vs_lc_scheduler) ;
  82}
  83
  84static void __exit ip_vs_lc_cleanup(void)
  85{
  86        unregister_ip_vs_scheduler(&ip_vs_lc_scheduler);
  87        synchronize_rcu();
  88}
  89
  90module_init(ip_vs_lc_init);
  91module_exit(ip_vs_lc_cleanup);
  92MODULE_LICENSE("GPL");
  93