blob: a6064515c39858b5830c651ba902d5879c5b119e [file] [log] [blame]
Brian Waters13d96012017-12-08 16:53:31 -06001/*********************************************************************************************************
2* Software License Agreement (BSD License) *
3* Author: Thomas Klausner <tk@giga.or.at> *
4* *
5* Copyright (c) 2014 Thomas Klausner *
6* All rights reserved. *
7* *
8* Written under contract by nfotex IT GmbH, http://nfotex.com/ *
9* *
10* Redistribution and use of this software in source and binary forms, with or without modification, are *
11* permitted provided that the following conditions are met: *
12* *
13* * Redistributions of source code must retain the above *
14* copyright notice, this list of conditions and the *
15* following disclaimer. *
16* *
17* * Redistributions in binary form must reproduce the above *
18* copyright notice, this list of conditions and the *
19* following disclaimer in the documentation and/or other *
20* materials provided with the distribution. *
21* *
22* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
23* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
24* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
25* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT *
26* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS *
27* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
28* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF *
29* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
30*********************************************************************************************************/
31
32#include <freeDiameter/extension.h>
33
34/*
35 * Load balancing extension. If there are multiple highest-rated hosts with the same score,
36 * randomly increase the score of one of them.
37 */
38
39#include <stdlib.h>
40
41static unsigned int seed;
42
43static int rt_randomizing(void * cbdata, struct msg ** pmsg, struct fd_list * candidates)
44{
45 struct fd_list *lic;
46 struct msg * msg = *pmsg;
47 int max_score = -1;
48 int max_score_count = 0;
49
50 TRACE_ENTRY("%p %p %p", cbdata, msg, candidates);
51
52 CHECK_PARAMS(msg && candidates);
53
54 /* Check if it is worth processing the message */
55 if (FD_IS_LIST_EMPTY(candidates))
56 return 0;
57
58 /* find out maximal score and how many candidates have it */
59 for (lic = candidates->next; lic != candidates; lic = lic->next) {
60 struct rtd_candidate * cand = (struct rtd_candidate *) lic;
61 if (max_score < cand->score) {
62 max_score = cand->score;
63 max_score_count = 1;
64 }
65 else if (cand->score == max_score) {
66 max_score_count++;
67 }
68 }
69
70 /* if there is more than one with positive score, randomly increase one of their scores by one */
71 if (max_score >= 0 && max_score_count > 1) {
72 int lucky_candidate = rand_r(&seed) % max_score_count;
73 int i = 0;
74
75 for (lic = candidates->next; lic != candidates; lic = lic->next) {
76 struct rtd_candidate * cand = (struct rtd_candidate *) lic;
77 if (cand->score == max_score) {
78 if (i == lucky_candidate) {
79 cand->score++;
80 break;
81 }
82 i++;
83 }
84 }
85 }
86
87 return 0;
88}
89
90/* handler */
91static struct fd_rt_out_hdl * rt_randomizing_hdl = NULL;
92
93/* entry point */
94static int rt_randomize_entry(char * conffile)
95{
96 /* Register the callback */
97 CHECK_FCT(fd_rt_out_register(rt_randomizing, NULL, 4, &rt_randomizing_hdl));
98 seed = (unsigned int)time(NULL);
99 TRACE_DEBUG(INFO, "Extension 'Randomizing' initialized");
100 return 0;
101}
102
103/* Unload */
104void fd_ext_fini(void)
105{
106 /* Unregister the callbacks */
107 CHECK_FCT_DO(fd_rt_out_unregister(rt_randomizing_hdl, NULL), /* continue */);
108 return ;
109}
110
111EXTENSION_ENTRY("rt_randomize", rt_randomize_entry);