ip_vs_rr.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  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. #include <linux/module.h>
  22. #include <linux/kernel.h>
  23. #include <net/ip_vs.h>
  24. static int ip_vs_rr_init_svc(struct ip_vs_service *svc)
  25. {
  26. svc->sched_data = &svc->destinations;
  27. return 0;
  28. }
  29. static int ip_vs_rr_done_svc(struct ip_vs_service *svc)
  30. {
  31. return 0;
  32. }
  33. static int ip_vs_rr_update_svc(struct ip_vs_service *svc)
  34. {
  35. svc->sched_data = &svc->destinations;
  36. return 0;
  37. }
  38. /*
  39. * Round-Robin Scheduling
  40. */
  41. static struct ip_vs_dest *
  42. ip_vs_rr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
  43. {
  44. struct list_head *p, *q;
  45. struct ip_vs_dest *dest;
  46. IP_VS_DBG(6, "ip_vs_rr_schedule(): Scheduling...\n");
  47. write_lock(&svc->sched_lock);
  48. p = (struct list_head *)svc->sched_data;
  49. p = p->next;
  50. q = p;
  51. do {
  52. /* skip list head */
  53. if (q == &svc->destinations) {
  54. q = q->next;
  55. continue;
  56. }
  57. dest = list_entry(q, struct ip_vs_dest, n_list);
  58. if (!(dest->flags & IP_VS_DEST_F_OVERLOAD) &&
  59. atomic_read(&dest->weight) > 0)
  60. /* HIT */
  61. goto out;
  62. q = q->next;
  63. } while (q != p);
  64. write_unlock(&svc->sched_lock);
  65. return NULL;
  66. out:
  67. svc->sched_data = q;
  68. write_unlock(&svc->sched_lock);
  69. IP_VS_DBG(6, "RR: server %u.%u.%u.%u:%u "
  70. "activeconns %d refcnt %d weight %d\n",
  71. NIPQUAD(dest->addr), ntohs(dest->port),
  72. atomic_read(&dest->activeconns),
  73. atomic_read(&dest->refcnt), atomic_read(&dest->weight));
  74. return dest;
  75. }
  76. static struct ip_vs_scheduler ip_vs_rr_scheduler = {
  77. .name = "rr", /* name */
  78. .refcnt = ATOMIC_INIT(0),
  79. .module = THIS_MODULE,
  80. .init_service = ip_vs_rr_init_svc,
  81. .done_service = ip_vs_rr_done_svc,
  82. .update_service = ip_vs_rr_update_svc,
  83. .schedule = ip_vs_rr_schedule,
  84. };
  85. static int __init ip_vs_rr_init(void)
  86. {
  87. INIT_LIST_HEAD(&ip_vs_rr_scheduler.n_list);
  88. return register_ip_vs_scheduler(&ip_vs_rr_scheduler);
  89. }
  90. static void __exit ip_vs_rr_cleanup(void)
  91. {
  92. unregister_ip_vs_scheduler(&ip_vs_rr_scheduler);
  93. }
  94. module_init(ip_vs_rr_init);
  95. module_exit(ip_vs_rr_cleanup);
  96. MODULE_LICENSE("GPL");