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
|