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                  struct ip_vs_iphdr *iph)
  31{
  32        struct ip_vs_dest *dest, *least = NULL;
  33        unsigned int loh = 0, doh;
  34
  35        IP_VS_DBG(6, "%s(): Scheduling...\n", __func__);
  36
  37        /*
  38         * Simply select the server with the least number of
  39         *        (activeconns<<5) + inactconns
  40         * Except whose weight is equal to zero.
  41         * If the weight is equal to zero, it means that the server is
  42         * quiesced, the existing connections to the server still get
  43         * served, but no new connection is assigned to the server.
  44         */
  45
  46        list_for_each_entry_rcu(dest, &svc->destinations, n_list) {
  47                if ((dest->flags & IP_VS_DEST_F_OVERLOAD) ||
  48                    atomic_read(&dest->weight) == 0)
  49                        continue;
  50                doh = ip_vs_dest_conn_overhead(dest);
  51                if (!least || doh < loh) {
  52                        least = dest;
  53                        loh = doh;
  54                }
  55        }
  56
  57        if (!least)
  58                ip_vs_scheduler_err(svc, "no destination available");
  59        else
  60                IP_VS_DBG_BUF(6, "LC: server %s:%u activeconns %d "
  61                              "inactconns %d\n",
  62                              IP_VS_DBG_ADDR(svc->af, &least->addr),
  63                              ntohs(least->port),
  64                              atomic_read(&least->activeconns),
  65                              atomic_read(&least->inactconns));
  66
  67        return least;
  68}
  69
  70
  71static struct ip_vs_scheduler ip_vs_lc_scheduler = {
  72        .name =                 "lc",
  73        .refcnt =               ATOMIC_INIT(0),
  74        .module =               THIS_MODULE,
  75        .n_list =               LIST_HEAD_INIT(ip_vs_lc_scheduler.n_list),
  76        .schedule =             ip_vs_lc_schedule,
  77};
  78
  79
  80static int __init ip_vs_lc_init(void)
  81{
  82        return register_ip_vs_scheduler(&ip_vs_lc_scheduler) ;
  83}
  84
  85static void __exit ip_vs_lc_cleanup(void)
  86{
  87        unregister_ip_vs_scheduler(&ip_vs_lc_scheduler);
  88        synchronize_rcu();
  89}
  90
  91module_init(ip_vs_lc_init);
  92module_exit(ip_vs_lc_cleanup);
  93MODULE_LICENSE("GPL");
  94