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