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