]> git.proxmox.com Git - mirror_frr.git/blob - ospfd/ospf_neighbor.c
*: Convert thread_cancelXXX to event_cancelXXX
[mirror_frr.git] / ospfd / ospf_neighbor.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * OSPF Neighbor functions.
4 * Copyright (C) 1999, 2000 Toshiaki Takada
5 */
6
7 #include <zebra.h>
8
9 #include "lib/bfd.h"
10 #include "linklist.h"
11 #include "prefix.h"
12 #include "memory.h"
13 #include "command.h"
14 #include "event.h"
15 #include "stream.h"
16 #include "table.h"
17 #include "log.h"
18 #include "json.h"
19
20 #include "ospfd/ospfd.h"
21 #include "ospfd/ospf_interface.h"
22 #include "ospfd/ospf_asbr.h"
23 #include "ospfd/ospf_lsa.h"
24 #include "ospfd/ospf_lsdb.h"
25 #include "ospfd/ospf_neighbor.h"
26 #include "ospfd/ospf_nsm.h"
27 #include "ospfd/ospf_packet.h"
28 #include "ospfd/ospf_network.h"
29 #include "ospfd/ospf_flood.h"
30 #include "ospfd/ospf_dump.h"
31 #include "ospfd/ospf_bfd.h"
32 #include "ospfd/ospf_gr.h"
33
34 /* Fill in the the 'key' as appropriate to retrieve the entry for nbr
35 * from the ospf_interface's nbrs table. Indexed by interface address
36 * for all cases except Virtual-link and PointToPoint interfaces, where
37 * neighbours are indexed by router-ID instead.
38 */
39 static void ospf_nbr_key(struct ospf_interface *oi, struct ospf_neighbor *nbr,
40 struct prefix *key)
41 {
42 key->family = AF_INET;
43 key->prefixlen = IPV4_MAX_BITLEN;
44
45 /* vlinks are indexed by router-id */
46 if (oi->type == OSPF_IFTYPE_VIRTUALLINK
47 || oi->type == OSPF_IFTYPE_POINTOPOINT)
48 key->u.prefix4 = nbr->router_id;
49 else
50 key->u.prefix4 = nbr->src;
51 return;
52 }
53
54 struct ospf_neighbor *ospf_nbr_new(struct ospf_interface *oi)
55 {
56 struct ospf_neighbor *nbr;
57
58 /* Allcate new neighbor. */
59 nbr = XCALLOC(MTYPE_OSPF_NEIGHBOR, sizeof(struct ospf_neighbor));
60
61 /* Relate neighbor to the interface. */
62 nbr->oi = oi;
63
64 /* Set default values. */
65 nbr->state = NSM_Down;
66
67 /* Set inheritance values. */
68 nbr->v_inactivity = OSPF_IF_PARAM(oi, v_wait);
69 nbr->v_db_desc = OSPF_IF_PARAM(oi, retransmit_interval);
70 nbr->v_ls_req = OSPF_IF_PARAM(oi, retransmit_interval);
71 nbr->v_ls_upd = OSPF_IF_PARAM(oi, retransmit_interval);
72 nbr->priority = -1;
73
74 /* DD flags. */
75 nbr->dd_flags = OSPF_DD_FLAG_MS | OSPF_DD_FLAG_M | OSPF_DD_FLAG_I;
76
77 /* Last received and sent DD. */
78 nbr->last_send = NULL;
79
80 nbr->nbr_nbma = NULL;
81
82 ospf_lsdb_init(&nbr->db_sum);
83 ospf_lsdb_init(&nbr->ls_rxmt);
84 ospf_lsdb_init(&nbr->ls_req);
85
86 nbr->crypt_seqnum = 0;
87
88 /* Initialize GR Helper info*/
89 nbr->gr_helper_info.recvd_grace_period = 0;
90 nbr->gr_helper_info.actual_grace_period = 0;
91 nbr->gr_helper_info.gr_helper_status = OSPF_GR_NOT_HELPER;
92 nbr->gr_helper_info.helper_exit_reason = OSPF_GR_HELPER_EXIT_NONE;
93 nbr->gr_helper_info.gr_restart_reason = OSPF_GR_UNKNOWN_RESTART;
94
95 return nbr;
96 }
97
98 void ospf_nbr_free(struct ospf_neighbor *nbr)
99 {
100 /* Free DB summary list. */
101 if (ospf_db_summary_count(nbr))
102 ospf_db_summary_clear(nbr);
103 /* ospf_db_summary_delete_all (nbr); */
104
105 /* Free ls request list. */
106 if (ospf_ls_request_count(nbr))
107 ospf_ls_request_delete_all(nbr);
108
109 /* Free retransmit list. */
110 if (ospf_ls_retransmit_count(nbr))
111 ospf_ls_retransmit_clear(nbr);
112
113 /* Cleanup LSDBs. */
114 ospf_lsdb_cleanup(&nbr->db_sum);
115 ospf_lsdb_cleanup(&nbr->ls_req);
116 ospf_lsdb_cleanup(&nbr->ls_rxmt);
117
118 /* Clear last send packet. */
119 if (nbr->last_send)
120 ospf_packet_free(nbr->last_send);
121
122 if (nbr->nbr_nbma) {
123 nbr->nbr_nbma->nbr = NULL;
124 nbr->nbr_nbma = NULL;
125 }
126
127 /* Cancel all timers. */
128 THREAD_OFF(nbr->t_inactivity);
129 THREAD_OFF(nbr->t_db_desc);
130 THREAD_OFF(nbr->t_ls_req);
131 THREAD_OFF(nbr->t_ls_upd);
132
133 /* Cancel all events. */ /* Thread lookup cost would be negligible. */
134 event_cancel_event(master, nbr);
135
136 bfd_sess_free(&nbr->bfd_session);
137
138 THREAD_OFF(nbr->gr_helper_info.t_grace_timer);
139
140 nbr->oi = NULL;
141 XFREE(MTYPE_OSPF_NEIGHBOR, nbr);
142 }
143
144 /* Delete specified OSPF neighbor from interface. */
145 void ospf_nbr_delete(struct ospf_neighbor *nbr)
146 {
147 struct ospf_interface *oi;
148 struct route_node *rn;
149 struct prefix p;
150
151 oi = nbr->oi;
152
153 /* get appropriate prefix 'key' */
154 ospf_nbr_key(oi, nbr, &p);
155
156 rn = route_node_lookup(oi->nbrs, &p);
157 if (rn) {
158 /* If lookup for a NBR succeeds, the leaf route_node could
159 * only exist because there is (or was) a nbr there.
160 * If the nbr was deleted, the leaf route_node should have
161 * lost its last refcount too, and be deleted.
162 * Therefore a looked-up leaf route_node in nbrs table
163 * should never have NULL info.
164 */
165 assert(rn->info);
166
167 if (rn->info) {
168 rn->info = NULL;
169 route_unlock_node(rn);
170 } else
171 zlog_info("Can't find neighbor %pI4 in the interface %s",
172 &nbr->src, IF_NAME(oi));
173
174 route_unlock_node(rn);
175 } else {
176 /*
177 * This neighbor was not found, but before we move on and
178 * free the neighbor structre, make sure that it was not
179 * indexed incorrectly and ended up in the "worng" place
180 */
181
182 /* Reverse the lookup rules */
183 if (oi->type == OSPF_IFTYPE_VIRTUALLINK
184 || oi->type == OSPF_IFTYPE_POINTOPOINT)
185 p.u.prefix4 = nbr->src;
186 else
187 p.u.prefix4 = nbr->router_id;
188
189 rn = route_node_lookup(oi->nbrs, &p);
190 if (rn) {
191 /* We found the neighbor!
192 * Now make sure it is not the exact same neighbor
193 * structure that we are about to free
194 */
195 if (nbr == rn->info) {
196 /* Same neighbor, drop the reference to it */
197 rn->info = NULL;
198 route_unlock_node(rn);
199 }
200 route_unlock_node(rn);
201 }
202 }
203
204 /* Free ospf_neighbor structure. */
205 ospf_nbr_free(nbr);
206 }
207
208 /* Check myself is in the neighbor list. */
209 int ospf_nbr_bidirectional(struct in_addr *router_id, struct in_addr *neighbors,
210 int size)
211 {
212 int i;
213 int max;
214
215 max = size / sizeof(struct in_addr);
216
217 for (i = 0; i < max; i++)
218 if (IPV4_ADDR_SAME(router_id, &neighbors[i]))
219 return 1;
220
221 return 0;
222 }
223
224 /* reset nbr_self */
225 void ospf_nbr_self_reset(struct ospf_interface *oi, struct in_addr router_id)
226 {
227 if (oi->nbr_self)
228 ospf_nbr_delete(oi->nbr_self);
229
230 oi->nbr_self = ospf_nbr_new(oi);
231 ospf_nbr_add_self(oi, router_id);
232 }
233
234 /* Add self to nbr list. */
235 void ospf_nbr_add_self(struct ospf_interface *oi, struct in_addr router_id)
236 {
237 struct prefix p;
238 struct route_node *rn;
239
240 if (!oi->nbr_self)
241 oi->nbr_self = ospf_nbr_new(oi);
242
243 /* Initial state */
244 oi->nbr_self->address = *oi->address;
245 oi->nbr_self->priority = OSPF_IF_PARAM(oi, priority);
246 oi->nbr_self->router_id = router_id;
247 oi->nbr_self->src = oi->address->u.prefix4;
248 oi->nbr_self->state = NSM_TwoWay;
249
250 switch (oi->area->external_routing) {
251 case OSPF_AREA_DEFAULT:
252 SET_FLAG(oi->nbr_self->options, OSPF_OPTION_E);
253 break;
254 case OSPF_AREA_STUB:
255 UNSET_FLAG(oi->nbr_self->options, OSPF_OPTION_E);
256 break;
257 case OSPF_AREA_NSSA:
258 UNSET_FLAG(oi->nbr_self->options, OSPF_OPTION_E);
259 SET_FLAG(oi->nbr_self->options, OSPF_OPTION_NP);
260 break;
261 }
262
263 /* Add nbr_self to nbrs table */
264 ospf_nbr_key(oi, oi->nbr_self, &p);
265
266 rn = route_node_get(oi->nbrs, &p);
267 if (rn->info) {
268 /* There is already pseudo neighbor. */
269 if (IS_DEBUG_OSPF_EVENT)
270 zlog_debug(
271 "router_id %pI4 already present in neighbor table. node refcount %u",
272 &router_id, route_node_get_lock_count(rn));
273 route_unlock_node(rn);
274 } else
275 rn->info = oi->nbr_self;
276 }
277
278 /* Get neighbor count by status.
279 Specify status = 0, get all neighbor other than myself. */
280 int ospf_nbr_count(struct ospf_interface *oi, int state)
281 {
282 struct ospf_neighbor *nbr;
283 struct route_node *rn;
284 int count = 0;
285
286 for (rn = route_top(oi->nbrs); rn; rn = route_next(rn))
287 if ((nbr = rn->info))
288 if (!IPV4_ADDR_SAME(&nbr->router_id,
289 &oi->ospf->router_id))
290 if (state == 0 || nbr->state == state)
291 count++;
292
293 return count;
294 }
295
296 int ospf_nbr_count_opaque_capable(struct ospf_interface *oi)
297 {
298 struct ospf_neighbor *nbr;
299 struct route_node *rn;
300 int count = 0;
301
302 for (rn = route_top(oi->nbrs); rn; rn = route_next(rn))
303 if ((nbr = rn->info))
304 if (!IPV4_ADDR_SAME(&nbr->router_id,
305 &oi->ospf->router_id))
306 if (nbr->state == NSM_Full)
307 if (CHECK_FLAG(nbr->options,
308 OSPF_OPTION_O))
309 count++;
310
311 return count;
312 }
313
314 /* lookup nbr by address - use this only if you know you must
315 * otherwise use the ospf_nbr_lookup() wrapper, which deals
316 * with virtual link and PointToPoint neighbours
317 */
318 struct ospf_neighbor *ospf_nbr_lookup_by_addr(struct route_table *nbrs,
319 struct in_addr *addr)
320 {
321 struct prefix p;
322 struct route_node *rn;
323 struct ospf_neighbor *nbr;
324
325 p.family = AF_INET;
326 p.prefixlen = IPV4_MAX_BITLEN;
327 p.u.prefix4 = *addr;
328
329 rn = route_node_lookup(nbrs, &p);
330 if (!rn)
331 return NULL;
332
333 /* See comment in ospf_nbr_delete */
334 assert(rn->info);
335
336 if (rn->info == NULL) {
337 route_unlock_node(rn);
338 return NULL;
339 }
340
341 nbr = (struct ospf_neighbor *)rn->info;
342 route_unlock_node(rn);
343
344 return nbr;
345 }
346
347 struct ospf_neighbor *ospf_nbr_lookup_by_routerid(struct route_table *nbrs,
348 struct in_addr *id)
349 {
350 struct route_node *rn;
351 struct ospf_neighbor *nbr;
352
353 for (rn = route_top(nbrs); rn; rn = route_next(rn))
354 if ((nbr = rn->info) != NULL)
355 if (IPV4_ADDR_SAME(&nbr->router_id, id)) {
356 route_unlock_node(rn);
357 return nbr;
358 }
359
360 return NULL;
361 }
362
363 void ospf_renegotiate_optional_capabilities(struct ospf *top)
364 {
365 struct listnode *node;
366 struct ospf_interface *oi;
367 struct route_table *nbrs;
368 struct route_node *rn;
369 struct ospf_neighbor *nbr;
370 uint8_t shutdown_save = top->inst_shutdown;
371
372 /* At first, flush self-originated LSAs from routing domain. */
373 ospf_flush_self_originated_lsas_now(top);
374
375 /* ospf_flush_self_originated_lsas_now is primarily intended for shut
376 * down scenarios. Reset the inst_shutdown flag that it sets. We are
377 * just changing configuration, and the flag can change the scheduling
378 * of when maxage LSAs are sent. */
379 top->inst_shutdown = shutdown_save;
380
381 /* Revert all neighbor status to ExStart. */
382 for (ALL_LIST_ELEMENTS_RO(top->oiflist, node, oi)) {
383 if ((nbrs = oi->nbrs) == NULL)
384 continue;
385
386 for (rn = route_top(nbrs); rn; rn = route_next(rn)) {
387 if ((nbr = rn->info) == NULL || nbr == oi->nbr_self)
388 continue;
389
390 if (nbr->state < NSM_ExStart)
391 continue;
392
393 if (IS_DEBUG_OSPF_EVENT)
394 zlog_debug(
395 "Renegotiate optional capabilities with neighbor(%pI4)",
396 &nbr->router_id);
397
398 OSPF_NSM_EVENT_SCHEDULE(nbr, NSM_SeqNumberMismatch);
399 }
400 }
401
402 /* Refresh/Re-originate external LSAs (Type-7 and Type-5).*/
403 ospf_external_lsa_rid_change(top);
404
405 return;
406 }
407
408
409 struct ospf_neighbor *ospf_nbr_lookup(struct ospf_interface *oi, struct ip *iph,
410 struct ospf_header *ospfh)
411 {
412 struct in_addr srcaddr = iph->ip_src;
413
414 if (oi->type == OSPF_IFTYPE_VIRTUALLINK
415 || oi->type == OSPF_IFTYPE_POINTOPOINT)
416 return (ospf_nbr_lookup_by_routerid(oi->nbrs,
417 &ospfh->router_id));
418 else
419 return (ospf_nbr_lookup_by_addr(oi->nbrs, &srcaddr));
420 }
421
422 static struct ospf_neighbor *ospf_nbr_add(struct ospf_interface *oi,
423 struct ospf_header *ospfh,
424 struct prefix *p)
425 {
426 struct ospf_neighbor *nbr;
427
428 nbr = ospf_nbr_new(oi);
429 nbr->state = NSM_Down;
430 nbr->src = p->u.prefix4;
431 memcpy(&nbr->address, p, sizeof(struct prefix));
432
433 nbr->nbr_nbma = NULL;
434 if (oi->type == OSPF_IFTYPE_NBMA) {
435 struct ospf_nbr_nbma *nbr_nbma;
436 struct listnode *node;
437
438 for (ALL_LIST_ELEMENTS_RO(oi->nbr_nbma, node, nbr_nbma)) {
439 if (IPV4_ADDR_SAME(&nbr_nbma->addr, &nbr->src)) {
440 nbr_nbma->nbr = nbr;
441 nbr->nbr_nbma = nbr_nbma;
442
443 if (nbr_nbma->t_poll)
444 THREAD_OFF(nbr_nbma->t_poll);
445
446 nbr->state_change = nbr_nbma->state_change + 1;
447 }
448 }
449 }
450
451 /* New nbr, save the crypto sequence number if necessary */
452 if (ntohs(ospfh->auth_type) == OSPF_AUTH_CRYPTOGRAPHIC)
453 nbr->crypt_seqnum = ospfh->u.crypt.crypt_seqnum;
454
455 /* Configure BFD if interface has it. */
456 ospf_neighbor_bfd_apply(nbr);
457
458 if (IS_DEBUG_OSPF_EVENT)
459 zlog_debug("NSM[%s:%pI4]: start", IF_NAME(oi),
460 &nbr->router_id);
461
462 return nbr;
463 }
464
465 struct ospf_neighbor *ospf_nbr_get(struct ospf_interface *oi,
466 struct ospf_header *ospfh, struct ip *iph,
467 struct prefix *p)
468 {
469 struct route_node *rn;
470 struct prefix key;
471 struct ospf_neighbor *nbr;
472
473 key.family = AF_INET;
474 key.prefixlen = IPV4_MAX_BITLEN;
475
476 if (oi->type == OSPF_IFTYPE_VIRTUALLINK
477 || oi->type == OSPF_IFTYPE_POINTOPOINT)
478 key.u.prefix4 = ospfh->router_id; /* index vlink and ptp nbrs by
479 router-id */
480 else
481 key.u.prefix4 = iph->ip_src;
482
483 rn = route_node_get(oi->nbrs, &key);
484 if (rn->info) {
485 route_unlock_node(rn);
486 nbr = rn->info;
487
488 if (oi->type == OSPF_IFTYPE_NBMA && nbr->state == NSM_Attempt) {
489 nbr->src = iph->ip_src;
490 memcpy(&nbr->address, p, sizeof(struct prefix));
491 }
492 } else {
493 rn->info = nbr = ospf_nbr_add(oi, ospfh, p);
494 }
495
496 nbr->router_id = ospfh->router_id;
497
498 return nbr;
499 }