linux/net/netfilter/ipvs/ip_vs_rr.c
<<
>>
Prefs
   1/*
   2 * IPVS:        Round-Robin 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 * Fixes/Changes:
  13 *     Wensong Zhang            :     changed the ip_vs_rr_schedule to return dest
  14 *     Julian Anastasov         :     fixed the NULL pointer access bug in debugging
  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_rr_update_svc
  18 *     Wensong Zhang            :     added any dest with weight=0 is quiesced
  19 *
  20 */
  21
  22#define KMSG_COMPONENT "IPVS"
  23#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
  24
  25#include <linux/module.h>
  26#include <linux/kernel.h>
  27
  28#include <net/ip_vs.h>
  29
  30
  31static int ip_vs_rr_init_svc(struct ip_vs_service *svc)
  32{
  33        svc->sched_data = &svc->destinations;
  34        return 0;
  35}
  36
  37
  38static int ip_vs_rr_update_svc(struct ip_vs_service *svc)
  39{
  40        svc->sched_data = &svc->destinations;
  41        return 0;
  42}
  43
  44
  45/*
  46 * Round-Robin Scheduling
  47 */
  48static struct ip_vs_dest *
  49ip_vs_rr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
  50{
  51        struct list_head *p, *q;
  52        struct ip_vs_dest *dest;
  53
  54        IP_VS_DBG(6, "%s(): Scheduling...\n", __func__);
  55
  56        write_lock(&svc->sched_lock);
  57        p = (struct list_head *)svc->sched_data;
  58        p = p->next;
  59        q = p;
  60        do {
  61                /* skip list head */
  62                if (q == &svc->destinations) {
  63                        q = q->next;
  64                        continue;
  65                }
  66
  67                dest = list_entry(q, struct ip_vs_dest, n_list);
  68                if (!(dest->flags & IP_VS_DEST_F_OVERLOAD) &&
  69                    atomic_read(&dest->weight) > 0)
  70                        /* HIT */
  71                        goto out;
  72                q = q->next;
  73        } while (q != p);
  74        write_unlock(&svc->sched_lock);
  75        IP_VS_ERR_RL("RR: no destination available\n");
  76        return NULL;
  77
  78  out:
  79        svc->sched_data = q;
  80        write_unlock(&svc->sched_lock);
  81        IP_VS_DBG_BUF(6, "RR: server %s:%u "
  82                      "activeconns %d refcnt %d weight %d\n",
  83                      IP_VS_DBG_ADDR(svc->af, &dest->addr), ntohs(dest->port),
  84                      atomic_read(&dest->activeconns),
  85                      atomic_read(&dest->refcnt), atomic_read(&dest->weight));
  86
  87        return dest;
  88}
  89
  90
  91static struct ip_vs_scheduler ip_vs_rr_scheduler = {
  92        .name =                 "rr",                   /* name */
  93        .refcnt =               ATOMIC_INIT(0),
  94        .module =               THIS_MODULE,
  95        .n_list =               LIST_HEAD_INIT(ip_vs_rr_scheduler.n_list),
  96        .init_service =         ip_vs_rr_init_svc,
  97        .update_service =       ip_vs_rr_update_svc,
  98        .schedule =             ip_vs_rr_schedule,
  99};
 100
 101static int __init ip_vs_rr_init(void)
 102{
 103        return register_ip_vs_scheduler(&ip_vs_rr_scheduler);
 104}
 105
 106static void __exit ip_vs_rr_cleanup(void)
 107{
 108        unregister_ip_vs_scheduler(&ip_vs_rr_scheduler);
 109}
 110
 111module_init(ip_vs_rr_init);
 112module_exit(ip_vs_rr_cleanup);
 113MODULE_LICENSE("GPL");
 114