]>
git.proxmox.com Git - mirror_frr.git/blob - babeld/neighbour.c
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.
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.
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/>.
15 * This file incorporates work covered by the following copyright and
18 Copyright (c) 2007, 2008 by Juliusz Chroboczek
20 Permission is hereby granted, free of charge, to any person obtaining a copy
21 of this software and associated documentation files (the "Software"), to deal
22 in the Software without restriction, including without limitation the rights
23 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
24 copies of the Software, and to permit persons to whom the Software is
25 furnished to do so, subject to the following conditions:
27 The above copyright notice and this permission notice shall be included in
28 all copies or substantial portions of the Software.
30 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
31 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
32 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
33 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
34 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
35 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
48 #include "babel_main.h"
51 #include "babel_interface.h"
52 #include "neighbour.h"
58 struct neighbour
*neighs
= NULL
;
60 static struct neighbour
*
61 find_neighbour_nocreate(const unsigned char *address
, struct interface
*ifp
)
63 struct neighbour
*neigh
;
64 FOR_ALL_NEIGHBOURS(neigh
) {
65 if(memcmp(address
, neigh
->address
, 16) == 0 &&
73 flush_neighbour(struct neighbour
*neigh
)
75 flush_neighbour_routes(neigh
);
76 if(unicast_neighbour
== neigh
)
83 struct neighbour
*previous
= neighs
;
84 while(previous
->next
!= neigh
)
85 previous
= previous
->next
;
86 previous
->next
= neigh
->next
;
92 find_neighbour(const unsigned char *address
, struct interface
*ifp
)
94 struct neighbour
*neigh
;
95 const struct timeval zero
= {0, 0};
97 neigh
= find_neighbour_nocreate(address
, ifp
);
101 debugf(BABEL_DEBUG_COMMON
,"Creating neighbour %s on %s.",
102 format_address(address
), ifp
->name
);
104 neigh
= malloc(sizeof(struct neighbour
));
106 zlog_err("malloc(neighbour): %s", safe_strerror(errno
));
110 neigh
->hello_seqno
= -1;
111 memcpy(neigh
->address
, address
, 16);
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;
119 neigh
->next
= neighs
;
125 /* Recompute a neighbour's rxcost. Return true if anything changed.
126 This does not call local_notify_neighbour, see update_neighbour_metric. */
128 update_neighbour(struct neighbour
*neigh
, int hello
, int hello_interval
)
134 if(neigh
->hello_interval
<= 0)
137 ((int)timeval_minus_msec(&babel_now
, &neigh
->hello_time
) -
138 neigh
->hello_interval
* 7) /
139 (neigh
->hello_interval
* 10);
140 if(missed_hellos
<= 0)
142 timeval_add_msec(&neigh
->hello_time
, &neigh
->hello_time
,
143 missed_hellos
* neigh
->hello_interval
* 10);
145 if(neigh
->hello_seqno
>= 0 && neigh
->reach
> 0) {
146 missed_hellos
= seqno_minus(hello
, neigh
->hello_seqno
) - 1;
147 if(missed_hellos
< -8) {
148 /* Probably a neighbour that rebooted and lost its seqno.
149 Reboot the universe. */
153 } else if(missed_hellos
< 0) {
154 if(hello_interval
> neigh
->hello_interval
) {
155 /* This neighbour has increased its hello interval,
156 and we didn't notice. */
157 neigh
->reach
<<= -missed_hellos
;
160 /* Late hello. Probably due to the link layer buffering
161 packets during a link outage. Ignore it, but reset
162 the expected seqno. */
163 neigh
->hello_seqno
= hello
;
172 neigh
->hello_time
= babel_now
;
173 neigh
->hello_interval
= hello_interval
;
176 if(missed_hellos
> 0) {
177 neigh
->reach
>>= missed_hellos
;
178 neigh
->hello_seqno
= seqno_plus(neigh
->hello_seqno
, missed_hellos
);
184 neigh
->hello_seqno
= hello
;
186 neigh
->reach
|= 0x8000;
187 if((neigh
->reach
& 0xFC00) != 0xFC00)
191 /* Make sure to give neighbours some feedback early after association */
192 if((neigh
->reach
& 0xBF00) == 0x8000) {
193 /* A new neighbour */
194 send_hello(neigh
->ifp
);
196 /* Don't send hellos, in order to avoid a positive feedback loop. */
197 int a
= (neigh
->reach
& 0xC000);
198 int b
= (neigh
->reach
& 0x3000);
199 if((a
== 0xC000 && b
== 0) || (a
== 0 && b
== 0x3000)) {
200 /* Reachability is either 1100 or 0011 */
201 send_self_update(neigh
->ifp
);
205 if((neigh
->reach
& 0xFC00) == 0xC000) {
206 /* This is a newish neighbour, let's request a full route dump.
207 We ought to avoid this when the network is dense */
208 send_unicast_request(neigh
, NULL
, 0);
209 send_ihu(neigh
, NULL
);
215 reset_txcost(struct neighbour
*neigh
)
219 delay
= timeval_minus_msec(&babel_now
, &neigh
->ihu_time
);
221 if(neigh
->ihu_interval
> 0 && delay
< neigh
->ihu_interval
* 10U * 3U)
224 /* If we're losing a lot of packets, we probably lost an IHU too */
225 if(delay
>= 180000 || (neigh
->reach
& 0xFFF0) == 0 ||
226 (neigh
->ihu_interval
> 0 &&
227 delay
>= neigh
->ihu_interval
* 10U * 10U)) {
228 neigh
->txcost
= INFINITY
;
229 neigh
->ihu_time
= babel_now
;
237 neighbour_txcost(struct neighbour
*neigh
)
239 return neigh
->txcost
;
245 struct neighbour
*neigh
;
247 unsigned msecs
= 50000;
249 debugf(BABEL_DEBUG_COMMON
,"Checking neighbours.");
253 changed
= update_neighbour(neigh
, -1, 0);
255 if(neigh
->reach
== 0 ||
256 neigh
->hello_time
.tv_sec
> babel_now
.tv_sec
|| /* clock stepped */
257 timeval_minus_msec(&babel_now
, &neigh
->hello_time
) > 300000) {
258 struct neighbour
*old
= neigh
;
260 flush_neighbour(old
);
264 rc
= reset_txcost(neigh
);
265 changed
= changed
|| rc
;
267 update_neighbour_metric(neigh
, changed
);
269 if(neigh
->hello_interval
> 0)
270 msecs
= MIN(msecs
, neigh
->hello_interval
* 10U);
271 if(neigh
->ihu_interval
> 0)
272 msecs
= MIN(msecs
, neigh
->ihu_interval
* 10U);
280 neighbour_rxcost(struct neighbour
*neigh
)
283 unsigned short reach
= neigh
->reach
;
285 delay
= timeval_minus_msec(&babel_now
, &neigh
->hello_time
);
287 if((reach
& 0xFFF0) == 0 || delay
>= 180000) {
289 } else if(babel_get_if_nfo(neigh
->ifp
)->flags
& BABEL_IF_LQ
) {
291 ((reach
& 0x8000) >> 2) +
292 ((reach
& 0x4000) >> 1) +
294 /* 0 <= sreach <= 0x7FFF */
295 int cost
= (0x8000 * babel_get_if_nfo(neigh
->ifp
)->cost
) / (sreach
+ 1);
296 /* cost >= interface->cost */
298 cost
= (cost
* (delay
- 20000) + 10000) / 20000;
299 return MIN(cost
, INFINITY
);
301 /* To lose one hello is a misfortune, to lose two is carelessness. */
302 if((reach
& 0xC000) == 0xC000)
303 return babel_get_if_nfo(neigh
->ifp
)->cost
;
304 else if((reach
& 0xC000) == 0)
306 else if((reach
& 0x2000))
307 return babel_get_if_nfo(neigh
->ifp
)->cost
;
314 neighbour_cost(struct neighbour
*neigh
)
318 if(!if_up(neigh
->ifp
))
321 a
= neighbour_txcost(neigh
);
326 b
= neighbour_rxcost(neigh
);
330 if(!(babel_get_if_nfo(neigh
->ifp
)->flags
& BABEL_IF_LQ
)
331 || (a
< 256 && b
< 256)) {
334 /* a = 256/alpha, b = 256/beta, where alpha and beta are the expected
335 probabilities of a packet getting through in the direct and reverse
339 /* 1/(alpha * beta), which is just plain ETX. */
340 /* Since a and b are capped to 16 bits, overflow is impossible. */
341 return (a
* b
+ 128) >> 8;