| 
 
 
yuanyong wrote:
 
Hai experts!
    Now I am reading the lvs source code.But I have met a problem.The problem is where is 
the base type of "struct ip_vs_dest* (*schedule)(struct ip_vs_service *svc,struct 
iphdr *iph); ".Where I can find it?Please can you help me,thanks.
 
Please fix your mailer to wrap lines correctly.
 
struct ip_vs_scheduler {
        struct list_head        n_list;   /* d-linked list head */
        char                    *name;    /* scheduler name */
        atomic_t                refcnt;   /* reference counter */
        struct module           *module;  /* THIS_MODULE/NULL */
        /* scheduler initializing service */
        int (*init_service)(struct ip_vs_service *svc);
        /* scheduling service finish */
        int (*done_service)(struct ip_vs_service *svc);
        /* scheduler updating service */
        int (*update_service)(struct ip_vs_service *svc);
        /* selecting a server from the given service */
        struct ip_vs_dest* (*schedule)(struct ip_vs_service *svc,
                                       struct iphdr *iph);
};
 
Horms, we must talk at OLS about finally getting down to writing a dev guide :)
 Additionally to what Horms told you correctly I might help other readers of the 
code which are not very familiar with function pointers that the whole setup 
roughly works as follows:
 Each scheduler {rr,lc,...} will have to register itself by initialisation of the 
ip_vs_scheduler struct object. As you can see it contains above other data types 
4 function pointers:
int (*init_service)(struct ip_vs_service *svc)
int (*done_service)(struct ip_vs_service *svc)
int (*update_service)(struct ip_vs_service *svc)
struct ip_vs_dest* (*schedule)(struct ip_vs_service *svc,struct iphdr *iph)
 Each scheduler will need to provide a callback function for those prototypes 
with his own specific implementation.
Let's have a look at ip_vs_wrr.c:
 We start with the __init function which is kernel specific. It defines 
ip_vs_wrr_init() which in turn calls the required
 register_ip_vs_scheduler(&ip_vs_wrr_scheduler). You can see the 
ip_vs_wrr_scheduler structure definition just above the __init function. There 
you will note following:
static struct ip_vs_scheduler ip_vs_wrr_scheduler = {
        {0},                    /* n_list */
        "wrr",                  /* name */
        ATOMIC_INIT(0),         /* refcnt */
        THIS_MODULE,            /* this module */
        ip_vs_wrr_init_svc,     /* service initializer */
        ip_vs_wrr_done_svc,     /* service done */
        ip_vs_wrr_update_svc,   /* service updater */
        ip_vs_wrr_schedule,     /* select a server from the destination list */
};
This now is exactly the scheduler specific object instantiation of the struct 
ip_vs_scheduler prototype defined in ip_vs.h. Reading this you can see that the 
last for "names" map the function names to be called accordingly.
 So in case of the wrr scheduler, what does the init_service (mapped to the 
ip_vs_wrr_init_svc function) do?
 It generates a mark object (used for list chain traversal and mark point) which 
gets filled up with initial values, such as the maximum weight and the gcd 
weight. This is a very intelligent thing to do, because if you do not do this, 
you will need to compute those values every time the scheduler needs to schedule 
a new incoming request.
 The latter also requires a second callback. Why? Imagine someone decides to 
update the weights of one or more server from user space. This would mean that 
the initially computed weights are not valid anymore.
 What can be done against it? We could compute those values every time the 
scheduler needs to schedule a destination but that's exactly what we don't want. 
So in play comes the update_service protoype (mapped to the ip_vs_wrr_update_svc 
function).
 As you can easily see the ip_vs_wrr_update_svc function will do part of what we 
did for the init_service: it will compute the new max weight and the new gcd 
weight, so the world is saved again. The update_service callback will be called 
upon a user space ioctl call (you can read about this in the previous chapter of 
this marvellous developer guide :)).
 The ip_vs_wrr_schedule function provides us with the core functionality of 
finding an appropriate destination (real server) when a new incoming connection 
is hitting our cluster. Here you could write your own algorithm. You only need 
to either return NULL (if no real server can be found) or a destination which is 
of type: struct ip_vs_dest.
 The last function callback is the ip_vs_wrr_done_svc function which kfree()'s 
the initially kmalloc()'d mark variable.
 This short tour-de-scheduler show give you enough information to write your own 
scheduler, at least in theory :).
Best regards,
Roberto Nibali, ratz
--
echo '[q]sa[ln0=aln256%Pln256/snlbx]sb3135071790101768542287578439snlbxq' | dc
 
 |