LVS
lvs-users
Google
 
Web LinuxVirtualServer.org

Re: [PATCH-2.5] spelling fixes

To: "LinuxVirtualServer.org users mailing list." <lvs-users@xxxxxxxxxxxxxxxxxxxxxx>
Subject: Re: [PATCH-2.5] spelling fixes
From: Roberto Nibali <ratz@xxxxxx>
Date: Mon, 07 Jul 2003 11:46:49 +0200
Hello Wensong,

If the backport to ipvs 1.0.x for 2.4.x is very well tested, we will include it in the next release of ipvs 1.0.x. We usually don't change ipvs 1.0.x too much, because 1.0.x is the stable branch.

I will fix the remaining issues if any and test it in our lab. Currently I'm cut off again from working on LVS as I need to do some customer work.

[threshold limitation problem]

Maybe there are two solutions to it.

I have another one for 2.2.x :)

1) add the flags member into the struct ip_vs_dest_entry, so that the status flags of real server can be exported to user-space programs.

For easy grepping/parsing, yes, but I'd like to have something more atomic.

2) add the failover server into each virtual service entry. When there
   is no server available, send the request to the failover server.
   The failover server can be run at the director machine, or the
   remote machine.

This is good. A RIP or a group of RIPs which act like a cold standby pool for session overload. The schedulers would not select a member of the pool (flagged with IP_VS_OVERFLOW_SERVER or something similar) unless all members of a VIP will have the IP_VS_DEST_F_OVERLOAD flag set. Then schedulers will start using the IP_VS_OVERFLOW_SERVER pool.

My 3) would be something like that, I've done a proof-of-concept scheduler for 2.2.x (customer requirements) called hprio which only takes the servers with highest weight. As my "per RS threshold limitation" implementation will quiesce overloaded servers (2.2.x kernels) you can simply add an overload pool with weights := weights_of_RIPs - 1.

I ripped the code from your rr and wrr schedulers, I hope you don't mind :) It's for 2.2.x and it works pretty well (let it run over the weekend and it didn't crash). Attached is the hprio scheduler.

Now I have following snapshot for example:

Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn u_thresh l_thresh
TCP  172.27.100.100:80 hprio
-> 172.27.232.12:80 Route 2 0 40 55 40 -> 127.0.0.1:80 Local 1 0 19 0 0 -> 172.27.232.4:80 Route 0 0 55 55 40

172.27.232.{4,12} are RIPs with weight 2, 127.0.0.1 is the session overflow page with weight 1, it will only be selected when it remains to be the highest weight (both other RIPs are quiesced).

Caveats:
--------
o only done for wrr/rr scheduler
o since the ipvsadm userspace notification on service addition is not in 2.2.x,
  I have to scan for the highest weight for every dest lookup.
o it will be all different for 2.4.x and 2.5.x :)

Best regards,
Roberto Nibali, ratz
--
echo '[q]sa[ln0=aln256%Pln256/snlbx]sb3135071790101768542287578439snlbxq' | dc
/*
 * IPVS:        Weighted Round-Robin High Priority Scheduling module
 *
 * Version:     0.0.2, 2003/07/03
 *
 * Authors:     Roberto Nibali <ratz@xxxxxx>
 *
 *              This program is free software; you can redistribute it and/or
 *              modify it under the terms of the GNU General Public License
 *              as published by the Free Software Foundation; either version
 *              2 of the License, or (at your option) any later version.
 *
 *              The code base is mostly shamelessly ripped from Wensong's rr
 *              and wrr schedulers. I hope he doesn't mind ;).
 *
 * Algorithm:
 *              It's based on the rr scheduler but it only takes the highest
 *              weight and then discards all other servers which have not
 *              the highest weight.
 *
 *              This can be used to simulate an atomic session LIP for peak
 *              loads where the user space application doesn't have the chance
 *              to react atomically.
 *
 * Changes:
 *      0.0.2
 *              - Removed wrr related code for list traversal: would crash the
 *                whole kernel
 *
 */

#include <linux/config.h>
#include <linux/module.h>
#ifdef CONFIG_KMOD
#include <linux/kmod.h>
#endif
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <net/ip_masq.h>
#ifdef CONFIG_IP_MASQUERADE_MOD
#include <net/ip_masq_mod.h>
#endif
#include <linux/ip_fw.h>
#include <net/ip_vs.h>

static int ip_vs_hprio_init_svc(struct ip_vs_service *svc) {
        svc->sched_data = &svc->destinations;
        MOD_INC_USE_COUNT;
        return 0;
}


static int ip_vs_hprio_done_svc(struct ip_vs_service *svc) {
        MOD_DEC_USE_COUNT;
        return 0;
}


static int ip_vs_hprio_update_svc(struct ip_vs_service *svc) {
        svc->sched_data = &svc->destinations;
        return 0;
}


/*
 *    Get the maximum weight of the service destinations.
 */
int ip_vs_hprio_max_weight(struct ip_vs_service *svc) {
        register struct list_head *l, *e;
        struct ip_vs_dest *dest;
        int weight = 0;

        l = &svc->destinations;
        for (e=l->next; e!=l; e=e->next) {
                dest = list_entry(e, struct ip_vs_dest, n_list);
                IP_VS_DBG(1, "    weight: %d\n", dest->weight);
                if (dest->weight > weight)
                        weight = dest->weight;
        }

        IP_VS_DBG(1, "max weight: %d\n", weight);
        return weight;
}

        
/*
 *    Weighted Round-Robin Highest Priority Scheduling
 */
static struct ip_vs_dest* ip_vs_hprio_schedule(struct ip_vs_service *svc,
                                             struct iphdr *iph) {
        register struct list_head *p, *q;
        struct ip_vs_dest *dest;
        int max_weight;

        IP_VS_DBG(1, "ip_vs_hprio_schedule(): Scheduling...\n");

        max_weight = ip_vs_hprio_max_weight(svc);
        p = (struct list_head *)svc->sched_data;
        p = p->next;
        q = p;

        do {
                if (q == &svc->destinations) {
                        q = q->next;
                        continue;
                }
                dest = list_entry(q, struct ip_vs_dest, n_list);
                if (dest->weight > 0 && dest->weight == max_weight) {
                        /* found a destination */
                        goto out;
                }
                q = q->next;
        } while (q != p);
        return NULL;

  out:
        svc->sched_data = q;
        IP_VS_DBG(1, "HPRIO: server %d.%d.%d.%d:%d "
                  "activeconns %d refcnt %d weight %d\n",
                  NIPQUAD(dest->addr), ntohs(dest->port),
                  atomic_read(&dest->activeconns),
                  atomic_read(&dest->refcnt), dest->weight);

        return dest;
}


static struct ip_vs_scheduler ip_vs_hprio_scheduler = {
        {0},                    /* n_list */
        "hprio",                  /* name */
        ATOMIC_INIT(0),         /* refcnt */
        ip_vs_hprio_init_svc,     /* service initializer */
        ip_vs_hprio_done_svc,     /* service done */
        ip_vs_hprio_update_svc,   /* service updater */
        ip_vs_hprio_schedule,     /* select a server from the destination list 
*/
};


__initfunc(int ip_vs_hprio_init(void)) {
        IP_VS_INFO("Initializing HPRIO scheduling\n");
        INIT_LIST_HEAD(&ip_vs_hprio_scheduler.n_list);
        return register_ip_vs_scheduler(&ip_vs_hprio_scheduler) ;
}

#ifdef MODULE
EXPORT_NO_SYMBOLS;

int init_module(void) {
        INIT_LIST_HEAD(&ip_vs_hprio_scheduler.n_list);

        /* module initialization by 'request_module' */
        if(register_ip_vs_scheduler(&ip_vs_hprio_scheduler) != 0) {
                return -EIO;
        }

        IP_VS_INFO("HPRIO scheduling module loaded.\n");
        
        return 0;
}

void cleanup_module(void) {
        /* module cleanup by 'release_module' */
        if(unregister_ip_vs_scheduler(&ip_vs_hprio_scheduler) != 0) {
                IP_VS_INFO("cannot remove HPRIO scheduling module\n");
        } else {
                IP_VS_INFO("HPRIO scheduling module unloaded.\n");
        }
}

#endif /* MODULE */
<Prev in Thread] Current Thread [Next in Thread>