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