blob: 43da8e09d1c134a8b8e91c0e30be9eaf5e1eda86 [file] [log] [blame]
Paul Jakma57345092011-12-25 17:52:09 +01001/*
2 * This file is free software: you may copy, redistribute and/or modify it
3 * under the terms of the GNU General Public License as published by the
4 * Free Software Foundation, either version 2 of the License, or (at your
5 * option) any later version.
6 *
7 * This file is distributed in the hope that it will be useful, but
8 * WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 * General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program. If not, see <http://www.gnu.org/licenses/>.
14 *
15 * This file incorporates work covered by the following copyright and
16 * permission notice:
17 *
18Copyright (c) 2007, 2008 by Juliusz Chroboczek
19
20Permission is hereby granted, free of charge, to any person obtaining a copy
21of this software and associated documentation files (the "Software"), to deal
22in the Software without restriction, including without limitation the rights
23to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
24copies of the Software, and to permit persons to whom the Software is
25furnished to do so, subject to the following conditions:
26
27The above copyright notice and this permission notice shall be included in
28all copies or substantial portions of the Software.
29
30THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
31IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
32FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
33AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
34LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
35OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
36THE SOFTWARE.
37*/
38
39#include <stdlib.h>
40#include <string.h>
41#include <stdio.h>
42#include <sys/time.h>
43#include <time.h>
44
45#include <zebra.h>
46#include "if.h"
47
48#include "babel_main.h"
49#include "babeld.h"
50#include "util.h"
51#include "babel_interface.h"
52#include "neighbour.h"
53#include "source.h"
54#include "route.h"
55#include "message.h"
56#include "resend.h"
57
58struct neighbour *neighs = NULL;
59
60static struct neighbour *
61find_neighbour_nocreate(const unsigned char *address, struct interface *ifp)
62{
63 struct neighbour *neigh;
64 FOR_ALL_NEIGHBOURS(neigh) {
65 if(memcmp(address, neigh->address, 16) == 0 &&
66 neigh->ifp == ifp)
67 return neigh;
68 }
69 return NULL;
70}
71
72void
73flush_neighbour(struct neighbour *neigh)
74{
75 flush_neighbour_routes(neigh);
76 if(unicast_neighbour == neigh)
77 flush_unicast(1);
78 flush_resends(neigh);
79
80 if(neighs == neigh) {
81 neighs = neigh->next;
82 } else {
83 struct neighbour *previous = neighs;
84 while(previous->next != neigh)
85 previous = previous->next;
86 previous->next = neigh->next;
87 }
88 free(neigh);
89}
90
91struct neighbour *
92find_neighbour(const unsigned char *address, struct interface *ifp)
93{
94 struct neighbour *neigh;
95 const struct timeval zero = {0, 0};
96
97 neigh = find_neighbour_nocreate(address, ifp);
98 if(neigh)
99 return neigh;
100
101 debugf(BABEL_DEBUG_COMMON,"Creating neighbour %s on %s.",
102 format_address(address), ifp->name);
103
104 neigh = malloc(sizeof(struct neighbour));
105 if(neigh == NULL) {
106 zlog_err("malloc(neighbour): %s", safe_strerror(errno));
107 return NULL;
108 }
109
110 neigh->hello_seqno = -1;
111 memcpy(neigh->address, address, 16);
112 neigh->reach = 0;
113 neigh->txcost = INFINITY;
114 neigh->ihu_time = babel_now;
115 neigh->hello_time = zero;
116 neigh->hello_interval = 0;
117 neigh->ihu_interval = 0;
118 neigh->ifp = ifp;
119 neigh->next = neighs;
120 neighs = neigh;
121 send_hello(ifp);
122 return neigh;
123}
124
125/* Recompute a neighbour's rxcost. Return true if anything changed. */
126int
127update_neighbour(struct neighbour *neigh, int hello, int hello_interval)
128{
129 int missed_hellos;
130 int rc = 0;
131
132 if(hello < 0) {
133 if(neigh->hello_interval <= 0)
134 return rc;
135 missed_hellos =
136 ((int)timeval_minus_msec(&babel_now, &neigh->hello_time) -
137 neigh->hello_interval * 7) /
138 (neigh->hello_interval * 10);
139 if(missed_hellos <= 0)
140 return rc;
141 timeval_add_msec(&neigh->hello_time, &neigh->hello_time,
142 missed_hellos * neigh->hello_interval * 10);
143 } else {
144 if(neigh->hello_seqno >= 0 && neigh->reach > 0) {
145 missed_hellos = seqno_minus(hello, neigh->hello_seqno) - 1;
146 if(missed_hellos < -8) {
147 /* Probably a neighbour that rebooted and lost its seqno.
148 Reboot the universe. */
149 neigh->reach = 0;
150 missed_hellos = 0;
151 rc = 1;
152 } else if(missed_hellos < 0) {
153 if(hello_interval > neigh->hello_interval) {
154 /* This neighbour has increased its hello interval,
155 and we didn't notice. */
156 neigh->reach <<= -missed_hellos;
157 missed_hellos = 0;
158 } else {
159 /* Late hello. Probably due to the link layer buffering
160 packets during a link outage. Ignore it, but reset
161 the expected seqno. */
162 neigh->hello_seqno = hello;
163 hello = -1;
164 missed_hellos = 0;
165 }
166 rc = 1;
167 }
168 } else {
169 missed_hellos = 0;
170 }
171 neigh->hello_time = babel_now;
172 neigh->hello_interval = hello_interval;
173 }
174
175 if(missed_hellos > 0) {
176 neigh->reach >>= missed_hellos;
177 neigh->hello_seqno = seqno_plus(neigh->hello_seqno, missed_hellos);
178 missed_hellos = 0;
179 rc = 1;
180 }
181
182 if(hello >= 0) {
183 neigh->hello_seqno = hello;
184 neigh->reach >>= 1;
185 neigh->reach |= 0x8000;
186 if((neigh->reach & 0xFC00) != 0xFC00)
187 rc = 1;
188 }
189
190 /* Make sure to give neighbours some feedback early after association */
191 if((neigh->reach & 0xBF00) == 0x8000) {
192 /* A new neighbour */
193 send_hello(neigh->ifp);
194 } else {
195 /* Don't send hellos, in order to avoid a positive feedback loop. */
196 int a = (neigh->reach & 0xC000);
197 int b = (neigh->reach & 0x3000);
198 if((a == 0xC000 && b == 0) || (a == 0 && b == 0x3000)) {
199 /* Reachability is either 1100 or 0011 */
200 send_self_update(neigh->ifp);
201 }
202 }
203
204 if((neigh->reach & 0xFC00) == 0xC000) {
205 /* This is a newish neighbour, let's request a full route dump.
206 We ought to avoid this when the network is dense */
207 send_unicast_request(neigh, NULL, 0);
208 send_ihu(neigh, NULL);
209 }
210 return rc;
211}
212
213static int
214reset_txcost(struct neighbour *neigh)
215{
216 unsigned delay;
217
218 delay = timeval_minus_msec(&babel_now, &neigh->ihu_time);
219
220 if(neigh->ihu_interval > 0 && delay < neigh->ihu_interval * 10 * 3)
221 return 0;
222
223 /* If we're losing a lot of packets, we probably lost an IHU too */
224 if(delay >= 180000 || (neigh->reach & 0xFFF0) == 0 ||
225 (neigh->ihu_interval > 0 &&
226 delay >= neigh->ihu_interval * 10 * 10)) {
227 neigh->txcost = INFINITY;
228 neigh->ihu_time = babel_now;
229 return 1;
230 }
231
232 return 0;
233}
234
235unsigned
236neighbour_txcost(struct neighbour *neigh)
237{
238 return neigh->txcost;
239}
240
241unsigned
242check_neighbours()
243{
244 struct neighbour *neigh;
245 int changed, rc;
246 unsigned msecs = 50000;
247
248 debugf(BABEL_DEBUG_COMMON,"Checking neighbours.");
249
250 neigh = neighs;
251 while(neigh) {
252 changed = update_neighbour(neigh, -1, 0);
253
254 if(neigh->reach == 0 ||
255 neigh->hello_time.tv_sec > babel_now.tv_sec || /* clock stepped */
256 timeval_minus_msec(&babel_now, &neigh->hello_time) > 300000) {
257 struct neighbour *old = neigh;
258 neigh = neigh->next;
259 flush_neighbour(old);
260 continue;
261 }
262
263 rc = reset_txcost(neigh);
264 changed = changed || rc;
265
266 update_neighbour_metric(neigh, changed);
267
268 if(neigh->hello_interval > 0)
269 msecs = MIN(msecs, neigh->hello_interval * 10);
270 if(neigh->ihu_interval > 0)
271 msecs = MIN(msecs, neigh->ihu_interval * 10);
272 neigh = neigh->next;
273 }
274
275 return msecs;
276}
277
278unsigned
279neighbour_rxcost(struct neighbour *neigh)
280{
281 unsigned delay;
282 unsigned short reach = neigh->reach;
283
284 delay = timeval_minus_msec(&babel_now, &neigh->hello_time);
285
286 if((reach & 0xFFF0) == 0 || delay >= 180000) {
287 return INFINITY;
288 } else if(babel_get_if_nfo(neigh->ifp)->flags & BABEL_IF_LQ) {
289 int sreach =
290 ((reach & 0x8000) >> 2) +
291 ((reach & 0x4000) >> 1) +
292 (reach & 0x3FFF);
293 /* 0 <= sreach <= 0x7FFF */
294 int cost = (0x8000 * babel_get_if_nfo(neigh->ifp)->cost) / (sreach + 1);
295 /* cost >= interface->cost */
296 if(delay >= 40000)
297 cost = (cost * (delay - 20000) + 10000) / 20000;
298 return MIN(cost, INFINITY);
299 } else {
300 /* To lose one hello is a misfortune, to lose two is carelessness. */
301 if((reach & 0xC000) == 0xC000)
302 return babel_get_if_nfo(neigh->ifp)->cost;
303 else if((reach & 0xC000) == 0)
304 return INFINITY;
305 else if((reach & 0x2000))
306 return babel_get_if_nfo(neigh->ifp)->cost;
307 else
308 return INFINITY;
309 }
310}
311
312unsigned
313neighbour_cost(struct neighbour *neigh)
314{
315 unsigned a, b;
316
317 if(!if_up(neigh->ifp))
318 return INFINITY;
319
320 a = neighbour_txcost(neigh);
321
322 if(a >= INFINITY)
323 return INFINITY;
324
325 b = neighbour_rxcost(neigh);
326 if(b >= INFINITY)
327 return INFINITY;
328
329 if(!(babel_get_if_nfo(neigh->ifp)->flags & BABEL_IF_LQ)
330 || (a <= 256 && b <= 256)) {
331 return a;
332 } else {
333 /* a = 256/alpha, b = 256/beta, where alpha and beta are the expected
334 probabilities of a packet getting through in the direct and reverse
335 directions. */
336 a = MAX(a, 256);
337 b = MAX(b, 256);
338 /* 1/(alpha * beta), which is just plain ETX. */
339 /* Since a and b are capped to 16 bits, overflow is impossible. */
340 return (a * b + 128) >> 8;
341 }
342}