gateway: split variable declarations
[olsrd.git] / src / gateway_default_handler.c
1 /*
2  * gateway_default_handler.c
3  *
4  *  Created on: Jan 29, 2010
5  *      Author: rogge
6  */
7 #ifdef linux
8
9 #include "defs.h"
10 #include "gateway.h"
11 #include "gateway_default_handler.h"
12 #include "scheduler.h"
13 #include "tc_set.h"
14 #include "log.h"
15 #include "lq_plugin.h"
16
17 #include "assert.h"
18
19
20 static uint32_t gw_def_nodecount;
21 static uint32_t gw_def_stablecount;
22 static bool gw_def_finished_ipv4;
23 static bool gw_def_finished_ipv6;
24 static struct timer_entry *gw_def_timer;
25
26 static void gw_default_startup_handler(void);
27 static void gw_default_choosegw_handler(bool ipv4, bool ipv6);
28 static void gw_default_update_handler(struct gateway_entry *);
29 static void gw_default_delete_handler(struct gateway_entry *);
30
31 static struct olsr_gw_handler gw_def_handler = {
32   &gw_default_startup_handler,
33   &gw_default_choosegw_handler,
34   &gw_default_update_handler,
35   &gw_default_delete_handler
36 };
37
38 /*
39  * Helper functions
40  */
41
42 /**
43  * Look through the gateway list and select the best gateway
44  * depending on the distance to this router
45  */
46 static void gw_default_choose_gateway(void) {
47   struct tc_entry *tc;
48   struct gateway_entry *inet_ipv4, *inet_ipv6;
49   olsr_linkcost cost_ipv4, cost_ipv6;
50   struct gateway_entry *gw;
51   bool dual;
52   olsr_linkcost path_cost_times_threshold;
53
54   cost_ipv4 = ROUTE_COST_BROKEN;
55   cost_ipv6 = ROUTE_COST_BROKEN;
56
57   inet_ipv4 = NULL;
58   inet_ipv6 = NULL;
59
60   OLSR_FOR_ALL_GATEWAY_ENTRIES(gw) {
61     /* gateways should not exist without tc entry */
62     if ((tc = olsr_lookup_tc_entry(&gw->originator)) == NULL) {
63       continue;
64     }
65
66     if (olsr_cnf->smart_gw_thresh == 0) {
67       path_cost_times_threshold = tc->path_cost;
68     } else {
69       path_cost_times_threshold = ((long long)tc->path_cost * (long long)olsr_cnf->smart_gw_thresh + 50LL) / 100LL;
70     }
71     if (!gw_def_finished_ipv4 && gw->ipv4 && gw->ipv4nat == olsr_cnf->smart_gw_allow_nat && path_cost_times_threshold < cost_ipv4) {
72       inet_ipv4 = gw;
73       cost_ipv4 = path_cost_times_threshold;
74     }
75     if (!gw_def_finished_ipv6 && gw->ipv6 && path_cost_times_threshold < cost_ipv6) {
76       inet_ipv6 = gw;
77       cost_ipv6 = path_cost_times_threshold;
78     }
79   } OLSR_FOR_ALL_GATEWAY_ENTRIES_END(gw)
80
81   /* found an IPv4 gateway ? */
82   gw_def_finished_ipv4 |= inet_ipv4 != NULL;
83   gw_def_finished_ipv6 |= inet_ipv6 != NULL;
84   dual = inet_ipv4 == inet_ipv6;
85   if (inet_ipv4) {
86     olsr_set_inet_gateway(&inet_ipv4->originator, true, dual, false);
87   }
88   if (inet_ipv6 && !dual) {
89     olsr_set_inet_gateway(&inet_ipv6->originator, false, true, false);
90   }
91
92   /* finished ? */
93   if ((olsr_cnf->smart_gw_thresh == 0) && gw_def_finished_ipv4 && gw_def_finished_ipv6) {
94     olsr_stop_timer(gw_def_timer);
95     gw_def_timer = NULL;
96   }
97 }
98
99 /**
100  * Timer callback for lazy gateway selection
101  *
102  * @param unused unused
103  */
104 static void gw_default_timer(void *unused __attribute__ ((unused))) {
105   /* accept a 10% increase/decrease in the number of gateway nodes without triggering a stablecount reset */
106   if (((tc_tree.count * 10) <= (gw_def_nodecount * 11)) ||
107       ((tc_tree.count * 10) >= (gw_def_nodecount *  9))) {
108     gw_def_nodecount = tc_tree.count;
109   }
110
111   if (tc_tree.count == gw_def_nodecount) {
112     /* the number of gateway nodes is 'stable' */
113     gw_def_stablecount++;
114   }
115   else {
116     /* there was a significant change in the number of gateway nodes */
117     gw_def_nodecount = tc_tree.count;
118     gw_def_stablecount = 0;
119   }
120
121   if (gw_def_stablecount >= olsr_cnf->smart_gw_stablecount) {
122     /* the number of gateway nodes is stable enough, so we should select a new gateway now */
123     gw_default_choose_gateway();
124   }
125 }
126
127 /**
128  * Lookup a new gateway based on distance metric
129  *
130  * @param ipv4 lookup new v4 gateway
131  * @param ipv6 lookup new v6 gateway
132  */
133 static void olsr_gw_default_lookup_gateway(bool ipv4, bool ipv6) {
134   if (ipv4) {
135     /* get new ipv4 GW if we use OLSRv4 or NIIT */
136     gw_def_finished_ipv4 = !(olsr_cnf->ip_version == AF_INET || olsr_cnf->use_niit);
137   }
138   if (ipv6) {
139     /* get new ipv6 GW if we use OLSRv6 */
140     gw_def_finished_ipv6 = !(olsr_cnf->ip_version == AF_INET6);
141   }
142
143   if (!(gw_def_finished_ipv4 && gw_def_finished_ipv6)) {
144     gw_default_choose_gateway();
145   }
146 }
147
148 /*
149  * Exported functions
150  */
151
152 /**
153  * initialization of default gateway handler
154  */
155 void olsr_gw_default_init(void) {
156   /* initialize values */
157   gw_def_nodecount = 0;
158   gw_def_stablecount = 0;
159   gw_def_finished_ipv4 = false;
160   gw_def_finished_ipv6 = false;
161   gw_def_timer = NULL;
162
163   /* setup default handler */
164   olsr_set_inetgw_handler(&gw_def_handler);
165 }
166
167 /*
168  * Handler functions
169  */
170
171 /* gateway handler callbacks */
172 static void gw_default_startup_handler(void) {
173   /* reset node count */
174   gw_def_nodecount = tc_tree.count;
175   gw_def_stablecount = 0;
176
177   /* get new ipv4 GW if we use OLSRv4 or NIIT */
178   gw_def_finished_ipv4 = !(olsr_cnf->ip_version == AF_INET || olsr_cnf->use_niit);
179
180   /* get new ipv6 GW if we use OLSRv6 */
181   gw_def_finished_ipv6 = !(olsr_cnf->ip_version == AF_INET6);
182
183   /* keep in mind we might be a gateway ourself */
184   gw_def_finished_ipv4 |= olsr_cnf->has_ipv4_gateway;
185   gw_def_finished_ipv6 |= olsr_cnf->has_ipv6_gateway;
186
187   /* start gateway selection timer */
188   olsr_set_timer(&gw_def_timer, olsr_cnf->smart_gw_period, 0, true, &gw_default_timer, NULL, 0);
189 }
190
191 static void gw_default_choosegw_handler(bool ipv4, bool ipv6) {
192   olsr_gw_default_lookup_gateway(ipv4, ipv6);
193
194   if (!(gw_def_finished_ipv4 && gw_def_finished_ipv6)) {
195     gw_default_startup_handler();
196   }
197 }
198
199 static void gw_default_update_handler(struct gateway_entry *gw) {
200   bool v4changed, v6changed;
201
202   v4changed = (gw == olsr_get_ipv4_inet_gateway(NULL))
203       && (!gw->ipv4 || (gw->ipv4nat && !olsr_cnf->smart_gw_allow_nat));
204   v6changed = (gw == olsr_get_ipv6_inet_gateway(NULL)) && !gw->ipv6;
205
206   if (v4changed || v6changed) {
207     olsr_gw_default_lookup_gateway(v4changed, v6changed);
208   }
209 }
210
211 static void gw_default_delete_handler(struct gateway_entry *gw) {
212   bool isv4, isv6;
213
214   isv4 = gw == olsr_get_ipv4_inet_gateway(NULL);
215   isv6 = gw == olsr_get_ipv6_inet_gateway(NULL);
216
217   if (gw != NULL && (isv4 || isv6)) {
218     olsr_gw_default_lookup_gateway(isv4, isv6);
219   }
220 }
221 #endif /* linux */