@@ -28,6 +28,9 @@
#define IP_VS_SVC_F_SCHED_SH_FALLBACK IP_VS_SVC_F_SCHED1 /* SH fallback */
#define IP_VS_SVC_F_SCHED_SH_PORT IP_VS_SVC_F_SCHED2 /* SH use port */
+#define IP_VS_SVC_F_SCHED_WRR_RANDOM IP_VS_SVC_F_SCHED1 /* random start */
+#define IP_VS_SVC_F_SCHED_RR_RANDOM IP_VS_SVC_F_SCHED1 /* random start */
+
/*
* Destination Server Flags
*/
@@ -22,13 +22,36 @@
#include <net/ip_vs.h>
+static void ip_vs_rr_random_start(struct ip_vs_service *svc)
+{
+ struct list_head *cur;
+ u32 start;
+
+ if (!(svc->flags & IP_VS_SVC_F_SCHED_RR_RANDOM) ||
+ svc->num_dests <= 1)
+ return;
+
+ start = prandom_u32_max(svc->num_dests);
+ spin_lock_bh(&svc->sched_lock);
+ cur = &svc->destinations;
+ while (start--)
+ cur = cur->next;
+ svc->sched_data = cur;
+ spin_unlock_bh(&svc->sched_lock);
+}
static int ip_vs_rr_init_svc(struct ip_vs_service *svc)
{
svc->sched_data = &svc->destinations;
+ ip_vs_rr_random_start(svc);
return 0;
}
+static int ip_vs_rr_add_dest(struct ip_vs_service *svc, struct ip_vs_dest *dest)
+{
+ ip_vs_rr_random_start(svc);
+ return 0;
+}
static int ip_vs_rr_del_dest(struct ip_vs_service *svc, struct ip_vs_dest *dest)
{
@@ -104,7 +127,7 @@ static struct ip_vs_scheduler ip_vs_rr_scheduler = {
.module = THIS_MODULE,
.n_list = LIST_HEAD_INIT(ip_vs_rr_scheduler.n_list),
.init_service = ip_vs_rr_init_svc,
- .add_dest = NULL,
+ .add_dest = ip_vs_rr_add_dest,
.del_dest = ip_vs_rr_del_dest,
.schedule = ip_vs_rr_schedule,
};
@@ -102,6 +102,24 @@ static int ip_vs_wrr_max_weight(struct ip_vs_service *svc)
return weight;
}
+static void ip_vs_wrr_random_start(struct ip_vs_service *svc)
+{
+ struct ip_vs_wrr_mark *mark = svc->sched_data;
+ struct list_head *cur;
+ u32 start;
+
+ if (!(svc->flags & IP_VS_SVC_F_SCHED_WRR_RANDOM) ||
+ svc->num_dests <= 1)
+ return;
+
+ start = prandom_u32_max(svc->num_dests);
+ spin_lock_bh(&svc->sched_lock);
+ cur = &svc->destinations;
+ while (start--)
+ cur = cur->next;
+ mark->cl = list_entry(cur, struct ip_vs_dest, n_list);
+ spin_unlock_bh(&svc->sched_lock);
+}
static int ip_vs_wrr_init_svc(struct ip_vs_service *svc)
{
@@ -119,6 +137,7 @@ static int ip_vs_wrr_init_svc(struct ip_vs_service *svc)
mark->mw = ip_vs_wrr_max_weight(svc) - (mark->di - 1);
mark->cw = mark->mw;
svc->sched_data = mark;
+ ip_vs_wrr_random_start(svc);
return 0;
}
@@ -149,6 +168,7 @@ static int ip_vs_wrr_dest_changed(struct ip_vs_service *svc,
else if (mark->di > 1)
mark->cw = (mark->cw / mark->di) * mark->di + 1;
spin_unlock_bh(&svc->sched_lock);
+ ip_vs_wrr_random_start(svc);
return 0;
}