linux/net/netfilter/ipvs/ip_vs_fo.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * IPVS:        Weighted Fail Over module
   4 *
   5 * Authors:     Kenny Mathis <kmathis@chokepoint.net>
   6 *
   7 * Changes:
   8 *     Kenny Mathis            :     added initial functionality based on weight
   9 */
  10
  11#define KMSG_COMPONENT "IPVS"
  12#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
  13
  14#include <linux/module.h>
  15#include <linux/kernel.h>
  16
  17#include <net/ip_vs.h>
  18
  19/* Weighted Fail Over Module */
  20static struct ip_vs_dest *
  21ip_vs_fo_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
  22                  struct ip_vs_iphdr *iph)
  23{
  24        struct ip_vs_dest *dest, *hweight = NULL;
  25        int hw = 0; /* Track highest weight */
  26
  27        IP_VS_DBG(6, "ip_vs_fo_schedule(): Scheduling...\n");
  28
  29        /* Basic failover functionality
  30         * Find virtual server with highest weight and send it traffic
  31         */
  32        list_for_each_entry_rcu(dest, &svc->destinations, n_list) {
  33                if (!(dest->flags & IP_VS_DEST_F_OVERLOAD) &&
  34                    atomic_read(&dest->weight) > hw) {
  35                        hweight = dest;
  36                        hw = atomic_read(&dest->weight);
  37                }
  38        }
  39
  40        if (hweight) {
  41                IP_VS_DBG_BUF(6, "FO: server %s:%u activeconns %d weight %d\n",
  42                              IP_VS_DBG_ADDR(hweight->af, &hweight->addr),
  43                              ntohs(hweight->port),
  44                              atomic_read(&hweight->activeconns),
  45                              atomic_read(&hweight->weight));
  46                return hweight;
  47        }
  48
  49        ip_vs_scheduler_err(svc, "no destination available");
  50        return NULL;
  51}
  52
  53static struct ip_vs_scheduler ip_vs_fo_scheduler = {
  54        .name =                 "fo",
  55        .refcnt =               ATOMIC_INIT(0),
  56        .module =               THIS_MODULE,
  57        .n_list =               LIST_HEAD_INIT(ip_vs_fo_scheduler.n_list),
  58        .schedule =             ip_vs_fo_schedule,
  59};
  60
  61static int __init ip_vs_fo_init(void)
  62{
  63        return register_ip_vs_scheduler(&ip_vs_fo_scheduler);
  64}
  65
  66static void __exit ip_vs_fo_cleanup(void)
  67{
  68        unregister_ip_vs_scheduler(&ip_vs_fo_scheduler);
  69        synchronize_rcu();
  70}
  71
  72module_init(ip_vs_fo_init);
  73module_exit(ip_vs_fo_cleanup);
  74MODULE_LICENSE("GPL");
  75