1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * IPVS: Round-Robin Scheduling module
5 * Authors: Wensong Zhang <wensong@linuxvirtualserver.org>
6 * Peter Kese <peter.kese@ijs.si>
9 * Wensong Zhang : changed the ip_vs_rr_schedule to return dest
10 * Julian Anastasov : fixed the NULL pointer access bug in debugging
11 * Wensong Zhang : changed some comestics things for debugging
12 * Wensong Zhang : changed for the d-linked destination list
13 * Wensong Zhang : added the ip_vs_rr_update_svc
14 * Wensong Zhang : added any dest with weight=0 is quiesced
17 #define KMSG_COMPONENT "IPVS"
18 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
20 #include <linux/module.h>
21 #include <linux/kernel.h>
23 #include <net/ip_vs.h>
26 static int ip_vs_rr_init_svc(struct ip_vs_service
*svc
)
28 svc
->sched_data
= &svc
->destinations
;
33 static int ip_vs_rr_del_dest(struct ip_vs_service
*svc
, struct ip_vs_dest
*dest
)
37 spin_lock_bh(&svc
->sched_lock
);
38 p
= (struct list_head
*) svc
->sched_data
;
39 /* dest is already unlinked, so p->prev is not valid but
40 * p->next is valid, use it to reach previous entry.
42 if (p
== &dest
->n_list
)
43 svc
->sched_data
= p
->next
->prev
;
44 spin_unlock_bh(&svc
->sched_lock
);
50 * Round-Robin Scheduling
52 static struct ip_vs_dest
*
53 ip_vs_rr_schedule(struct ip_vs_service
*svc
, const struct sk_buff
*skb
,
54 struct ip_vs_iphdr
*iph
)
57 struct ip_vs_dest
*dest
, *last
;
60 IP_VS_DBG(6, "%s(): Scheduling...\n", __func__
);
62 spin_lock_bh(&svc
->sched_lock
);
63 p
= (struct list_head
*) svc
->sched_data
;
64 last
= dest
= list_entry(p
, struct ip_vs_dest
, n_list
);
67 list_for_each_entry_continue_rcu(dest
,
70 if (!(dest
->flags
& IP_VS_DEST_F_OVERLOAD
) &&
71 atomic_read(&dest
->weight
) > 0)
78 /* Previous dest could be unlinked, do not loop forever.
79 * If we stay at head there is no need for 2nd pass.
81 } while (pass
< 2 && p
!= &svc
->destinations
);
84 spin_unlock_bh(&svc
->sched_lock
);
85 ip_vs_scheduler_err(svc
, "no destination available");
89 svc
->sched_data
= &dest
->n_list
;
90 spin_unlock_bh(&svc
->sched_lock
);
91 IP_VS_DBG_BUF(6, "RR: server %s:%u "
92 "activeconns %d refcnt %d weight %d\n",
93 IP_VS_DBG_ADDR(dest
->af
, &dest
->addr
), ntohs(dest
->port
),
94 atomic_read(&dest
->activeconns
),
95 refcount_read(&dest
->refcnt
), atomic_read(&dest
->weight
));
101 static struct ip_vs_scheduler ip_vs_rr_scheduler
= {
102 .name
= "rr", /* name */
103 .refcnt
= ATOMIC_INIT(0),
104 .module
= THIS_MODULE
,
105 .n_list
= LIST_HEAD_INIT(ip_vs_rr_scheduler
.n_list
),
106 .init_service
= ip_vs_rr_init_svc
,
108 .del_dest
= ip_vs_rr_del_dest
,
109 .schedule
= ip_vs_rr_schedule
,
112 static int __init
ip_vs_rr_init(void)
114 return register_ip_vs_scheduler(&ip_vs_rr_scheduler
);
117 static void __exit
ip_vs_rr_cleanup(void)
119 unregister_ip_vs_scheduler(&ip_vs_rr_scheduler
);
123 module_init(ip_vs_rr_init
);
124 module_exit(ip_vs_rr_cleanup
);
125 MODULE_LICENSE("GPL");