4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #include <sys/errno.h>
28 #include <sys/sysmacros.h>
29 #include <sys/debug.h>
32 #include <sys/debug.h>
33 #include <sys/types.h>
36 #include <netinet/in.h>
38 #include <inet/ilb/ilb_impl.h>
39 #include <inet/ilb/ilb_alg.h>
53 static void rr_fini(ilb_alg_data_t
**);
57 rr_lb(in6_addr_t
*saddr
, in_port_t sport
, in6_addr_t
*daddr
,
58 in_port_t dport
, void *alg_data
, ilb_server_t
**ret_server
)
60 rr_t
*rr_alg
= (rr_t
*)alg_data
;
64 ASSERT(ret_server
!= NULL
);
67 mutex_enter(&rr_alg
->rr_lock
);
68 servers
= &rr_alg
->rr_servers
;
69 if (list_is_empty(servers
)) {
70 mutex_exit(&rr_alg
->rr_lock
);
73 if (rr_alg
->rr_next
== NULL
)
74 rr_alg
->rr_next
= list_head(servers
);
75 start
= rr_alg
->rr_next
;
76 while (!rr_alg
->rr_next
->enabled
) {
77 rr_alg
->rr_next
= list_next(servers
, rr_alg
->rr_next
);
78 if (rr_alg
->rr_next
== NULL
)
79 rr_alg
->rr_next
= list_head(servers
);
80 if (rr_alg
->rr_next
== start
) {
81 mutex_exit(&rr_alg
->rr_lock
);
86 *ret_server
= rr_alg
->rr_next
->server
;
87 rr_alg
->rr_next
= list_next(servers
, rr_alg
->rr_next
);
88 mutex_exit(&rr_alg
->rr_lock
);
93 rr_server_del(ilb_server_t
*host
, void *alg_data
)
95 rr_t
*rr_alg
= (rr_t
*)alg_data
;
96 list_t
*servers
= &rr_alg
->rr_servers
;
97 rr_server_t
*tmp_server
;
99 mutex_enter(&rr_alg
->rr_lock
);
100 for (tmp_server
= list_head(servers
); tmp_server
!= NULL
;
101 tmp_server
= list_next(servers
, tmp_server
)) {
102 if (tmp_server
->server
== host
) {
103 if (rr_alg
->rr_next
== tmp_server
) {
104 rr_alg
->rr_next
= list_next(servers
,
107 list_remove(servers
, tmp_server
);
111 mutex_exit(&rr_alg
->rr_lock
);
112 if (tmp_server
== NULL
)
114 kmem_free(tmp_server
, sizeof (rr_server_t
));
116 ILB_SERVER_REFRELE(host
);
121 rr_server_add(ilb_server_t
*host
, void *alg_data
)
123 rr_t
*rr_alg
= (rr_t
*)alg_data
;
124 rr_server_t
*new_server
;
126 new_server
= kmem_alloc(sizeof (rr_server_t
), KM_NOSLEEP
);
127 if (new_server
== NULL
)
129 new_server
->server
= host
;
130 new_server
->enabled
= host
->iser_enabled
;
132 mutex_enter(&rr_alg
->rr_lock
);
133 list_insert_head(&rr_alg
->rr_servers
, new_server
);
134 mutex_exit(&rr_alg
->rr_lock
);
136 ILB_SERVER_REFHOLD(host
);
141 rr_server_toggle(list_t
*servers
, ilb_server_t
*host
, boolean_t value
)
143 rr_server_t
*tmp_server
;
145 if (list_is_empty(servers
))
148 for (tmp_server
= list_head(servers
); tmp_server
!= NULL
;
149 tmp_server
= list_next(servers
, tmp_server
)) {
150 if (tmp_server
->server
== host
) {
151 tmp_server
->enabled
= value
;
155 if (tmp_server
!= NULL
)
162 rr_server_enable(ilb_server_t
*host
, void *alg_data
)
164 rr_t
*rr_alg
= (rr_t
*)alg_data
;
168 mutex_enter(&rr_alg
->rr_lock
);
169 servers
= &rr_alg
->rr_servers
;
170 ret
= rr_server_toggle(servers
, host
, B_TRUE
);
171 mutex_exit(&rr_alg
->rr_lock
);
176 rr_server_disable(ilb_server_t
*host
, void *alg_data
)
178 rr_t
*rr_alg
= (rr_t
*)alg_data
;
182 mutex_enter(&rr_alg
->rr_lock
);
183 servers
= &rr_alg
->rr_servers
;
184 ret
= rr_server_toggle(servers
, host
, B_FALSE
);
185 mutex_exit(&rr_alg
->rr_lock
);
191 ilb_alg_rr_init(ilb_rule_t
*rule
, void *arg
)
196 if ((alg
= kmem_alloc(sizeof (ilb_alg_data_t
), KM_NOSLEEP
)) == NULL
)
198 if ((rr_alg
= kmem_alloc(sizeof (rr_t
), KM_NOSLEEP
)) == NULL
) {
199 kmem_free(alg
, sizeof (ilb_alg_data_t
));
203 alg
->ilb_alg_lb
= rr_lb
;
204 alg
->ilb_alg_server_del
= rr_server_del
;
205 alg
->ilb_alg_server_add
= rr_server_add
;
206 alg
->ilb_alg_server_enable
= rr_server_enable
;
207 alg
->ilb_alg_server_disable
= rr_server_disable
;
208 alg
->ilb_alg_fini
= rr_fini
;
209 alg
->ilb_alg_data
= rr_alg
;
211 mutex_init(&rr_alg
->rr_lock
, NULL
, MUTEX_DEFAULT
, NULL
);
212 list_create(&rr_alg
->rr_servers
, sizeof (rr_server_t
),
213 offsetof(rr_server_t
, list
));
214 rr_alg
->rr_next
= NULL
;
220 rr_fini(ilb_alg_data_t
**alg
)
223 rr_server_t
*tmp_server
;
226 rr_alg
= (*alg
)->ilb_alg_data
;
227 servers
= &rr_alg
->rr_servers
;
228 while ((tmp_server
= list_head(servers
)) != NULL
) {
229 list_remove(servers
, tmp_server
);
230 ILB_SERVER_REFRELE(tmp_server
->server
);
231 kmem_free(tmp_server
, sizeof (rr_server_t
));
233 list_destroy(servers
);
234 kmem_free(rr_alg
, sizeof (rr_t
));
235 kmem_free(*alg
, sizeof (ilb_alg_data_t
));