]> git.proxmox.com Git - mirror_frr.git/blame - ospfd/ospf_neighbor.c
Merge pull request #13649 from donaldsharp/unlock_the_node_or_else
[mirror_frr.git] / ospfd / ospf_neighbor.c
CommitLineData
acddc0ed 1// SPDX-License-Identifier: GPL-2.0-or-later
2d59836a 2/*
3 * OSPF Neighbor functions.
4 * Copyright (C) 1999, 2000 Toshiaki Takada
2d59836a 5 */
6
7#include <zebra.h>
8
659f4e40 9#include "lib/bfd.h"
2d59836a 10#include "linklist.h"
11#include "prefix.h"
12#include "memory.h"
13#include "command.h"
24a58196 14#include "frrevent.h"
2d59836a 15#include "stream.h"
16#include "table.h"
17#include "log.h"
68fe91d6 18#include "json.h"
2d59836a 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"
68fe91d6 31#include "ospfd/ospf_bfd.h"
cd52c44c 32#include "ospfd/ospf_gr.h"
2d59836a 33
478aab98
PJ
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
0ab4a2d6
JT
36 * for all cases except Virtual-link and PointToPoint interfaces, where
37 * neighbours are indexed by router-ID instead.
478aab98 38 */
d62a17ae 39static void ospf_nbr_key(struct ospf_interface *oi, struct ospf_neighbor *nbr,
40 struct prefix *key)
478aab98 41{
d62a17ae 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;
478aab98
PJ
52}
53
d62a17ae 54struct ospf_neighbor *ospf_nbr_new(struct ospf_interface *oi)
2d59836a 55{
d62a17ae 56 struct ospf_neighbor *nbr;
2d59836a 57
d62a17ae 58 /* Allcate new neighbor. */
59 nbr = XCALLOC(MTYPE_OSPF_NEIGHBOR, sizeof(struct ospf_neighbor));
2d59836a 60
d62a17ae 61 /* Relate neighbor to the interface. */
62 nbr->oi = oi;
2d59836a 63
d62a17ae 64 /* Set default values. */
65 nbr->state = NSM_Down;
2d59836a 66
d62a17ae 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;
2d59836a 73
d62a17ae 74 /* DD flags. */
75 nbr->dd_flags = OSPF_DD_FLAG_MS | OSPF_DD_FLAG_M | OSPF_DD_FLAG_I;
2d59836a 76
d62a17ae 77 /* Last received and sent DD. */
78 nbr->last_send = NULL;
2d59836a 79
d62a17ae 80 nbr->nbr_nbma = NULL;
2d59836a 81
d62a17ae 82 ospf_lsdb_init(&nbr->db_sum);
83 ospf_lsdb_init(&nbr->ls_rxmt);
84 ospf_lsdb_init(&nbr->ls_req);
2d59836a 85
d62a17ae 86 nbr->crypt_seqnum = 0;
2d59836a 87
06bc3110 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
d62a17ae 95 return nbr;
2d59836a 96}
97
d62a17ae 98void ospf_nbr_free(struct ospf_neighbor *nbr)
2d59836a 99{
d62a17ae 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. */
e16d030c
DS
128 EVENT_OFF(nbr->t_inactivity);
129 EVENT_OFF(nbr->t_db_desc);
130 EVENT_OFF(nbr->t_ls_req);
131 EVENT_OFF(nbr->t_ls_upd);
d62a17ae 132
133 /* Cancel all events. */ /* Thread lookup cost would be negligible. */
332beb64 134 event_cancel_event(master, nbr);
d62a17ae 135
659f4e40 136 bfd_sess_free(&nbr->bfd_session);
45559c4d 137
e16d030c 138 EVENT_OFF(nbr->gr_helper_info.t_grace_timer);
06bc3110 139
45559c4d 140 nbr->oi = NULL;
d62a17ae 141 XFREE(MTYPE_OSPF_NEIGHBOR, nbr);
2d59836a 142}
143
144/* Delete specified OSPF neighbor from interface. */
d62a17ae 145void ospf_nbr_delete(struct ospf_neighbor *nbr)
2d59836a 146{
d62a17ae 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
96b663a3
MS
171 zlog_info("Can't find neighbor %pI4 in the interface %s",
172 &nbr->src, IF_NAME(oi));
d62a17ae 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 }
2d59836a 202 }
2d59836a 203
d62a17ae 204 /* Free ospf_neighbor structure. */
205 ospf_nbr_free(nbr);
2d59836a 206}
207
208/* Check myself is in the neighbor list. */
d62a17ae 209int ospf_nbr_bidirectional(struct in_addr *router_id, struct in_addr *neighbors,
210 int size)
2d59836a 211{
d62a17ae 212 int i;
213 int max;
2d59836a 214
d62a17ae 215 max = size / sizeof(struct in_addr);
2d59836a 216
d62a17ae 217 for (i = 0; i < max; i++)
218 if (IPV4_ADDR_SAME(router_id, &neighbors[i]))
219 return 1;
2d59836a 220
d62a17ae 221 return 0;
2d59836a 222}
223
cdd0c849 224/* reset nbr_self */
d62a17ae 225void ospf_nbr_self_reset(struct ospf_interface *oi, struct in_addr router_id)
cdd0c849 226{
d62a17ae 227 if (oi->nbr_self)
228 ospf_nbr_delete(oi->nbr_self);
ecea0cb0 229
d62a17ae 230 oi->nbr_self = ospf_nbr_new(oi);
231 ospf_nbr_add_self(oi, router_id);
cdd0c849
PJ
232}
233
2d59836a 234/* Add self to nbr list. */
d62a17ae 235void ospf_nbr_add_self(struct ospf_interface *oi, struct in_addr router_id)
2d59836a 236{
d62a17ae 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. */
ed59abd5
DS
269 if (IS_DEBUG_OSPF_EVENT)
270 zlog_debug(
96b663a3
MS
271 "router_id %pI4 already present in neighbor table. node refcount %u",
272 &router_id, route_node_get_lock_count(rn));
d62a17ae 273 route_unlock_node(rn);
274 } else
275 rn->info = oi->nbr_self;
2d59836a 276}
277
278/* Get neighbor count by status.
279 Specify status = 0, get all neighbor other than myself. */
d62a17ae 280int ospf_nbr_count(struct ospf_interface *oi, int state)
2d59836a 281{
d62a17ae 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;
2d59836a 294}
295
d62a17ae 296int ospf_nbr_count_opaque_capable(struct ospf_interface *oi)
2d59836a 297{
d62a17ae 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;
2d59836a 312}
2d59836a 313
d3f0d621 314/* lookup nbr by address - use this only if you know you must
0ab4a2d6
JT
315 * otherwise use the ospf_nbr_lookup() wrapper, which deals
316 * with virtual link and PointToPoint neighbours
d3f0d621 317 */
d62a17ae 318struct 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
347struct ospf_neighbor *ospf_nbr_lookup_by_routerid(struct route_table *nbrs,
348 struct in_addr *id)
2d59836a 349{
d62a17ae 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;
2d59836a 361}
362
d62a17ae 363void ospf_renegotiate_optional_capabilities(struct ospf *top)
2d59836a 364{
d62a17ae 365 struct listnode *node;
366 struct ospf_interface *oi;
367 struct route_table *nbrs;
368 struct route_node *rn;
369 struct ospf_neighbor *nbr;
a1638c7c 370 uint8_t shutdown_save = top->inst_shutdown;
d62a17ae 371
372 /* At first, flush self-originated LSAs from routing domain. */
373 ospf_flush_self_originated_lsas_now(top);
374
a1638c7c
YY
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
d62a17ae 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(
96b663a3
MS
395 "Renegotiate optional capabilities with neighbor(%pI4)",
396 &nbr->router_id);
d62a17ae 397
398 OSPF_NSM_EVENT_SCHEDULE(nbr, NSM_SeqNumberMismatch);
399 }
2d59836a 400 }
401
a4d9009d 402 /* Refresh/Re-originate external LSAs (Type-7 and Type-5).*/
403 ospf_external_lsa_rid_change(top);
404
d62a17ae 405 return;
2d59836a 406}
407
d62a17ae 408
409struct ospf_neighbor *ospf_nbr_lookup(struct ospf_interface *oi, struct ip *iph,
410 struct ospf_header *ospfh)
2d59836a 411{
9e030550
MS
412 struct in_addr srcaddr = iph->ip_src;
413
d62a17ae 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
9e030550 419 return (ospf_nbr_lookup_by_addr(oi->nbrs, &srcaddr));
d62a17ae 420}
2d59836a 421
d62a17ae 422static 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;
2d59836a 427
d62a17ae 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));
2d59836a 432
d62a17ae 433 nbr->nbr_nbma = NULL;
434 if (oi->type == OSPF_IFTYPE_NBMA) {
435 struct ospf_nbr_nbma *nbr_nbma;
436 struct listnode *node;
2d59836a 437
d62a17ae 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;
2d59836a 442
d62a17ae 443 if (nbr_nbma->t_poll)
e16d030c 444 EVENT_OFF(nbr_nbma->t_poll);
2d59836a 445
d62a17ae 446 nbr->state_change = nbr_nbma->state_change + 1;
447 }
448 }
449 }
2d59836a 450
d62a17ae 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;
d3f0d621 454
659f4e40
RZ
455 /* Configure BFD if interface has it. */
456 ospf_neighbor_bfd_apply(nbr);
457
d62a17ae 458 if (IS_DEBUG_OSPF_EVENT)
96b663a3
MS
459 zlog_debug("NSM[%s:%pI4]: start", IF_NAME(oi),
460 &nbr->router_id);
d3f0d621 461
d62a17ae 462 return nbr;
d3f0d621 463}
464
d62a17ae 465struct ospf_neighbor *ospf_nbr_get(struct ospf_interface *oi,
466 struct ospf_header *ospfh, struct ip *iph,
467 struct prefix *p)
d3f0d621 468{
d62a17ae 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)
996c9314
LB
478 key.u.prefix4 = ospfh->router_id; /* index vlink and ptp nbrs by
479 router-id */
d62a17ae 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 }
d3f0d621 495
d62a17ae 496 nbr->router_id = ospfh->router_id;
497
498 return nbr;
d3f0d621 499}