]>
git.proxmox.com Git - mirror_frr.git/blob - ospfd/ospf_neighbor.c
8725497f2de9cd110cb8ba70667fc8fb79410f3e
2 * OSPF Neighbor functions.
3 * Copyright (C) 1999, 2000 Toshiaki Takada
5 * This file is part of GNU Zebra.
7 * GNU Zebra is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published
9 * by the Free Software Foundation; either version 2, or (at your
10 * option) any later version.
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; see the file COPYING; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
35 #include "ospfd/ospfd.h"
36 #include "ospfd/ospf_interface.h"
37 #include "ospfd/ospf_asbr.h"
38 #include "ospfd/ospf_lsa.h"
39 #include "ospfd/ospf_lsdb.h"
40 #include "ospfd/ospf_neighbor.h"
41 #include "ospfd/ospf_nsm.h"
42 #include "ospfd/ospf_packet.h"
43 #include "ospfd/ospf_network.h"
44 #include "ospfd/ospf_flood.h"
45 #include "ospfd/ospf_dump.h"
46 #include "ospfd/ospf_bfd.h"
47 #include "ospfd/ospf_gr_helper.h"
49 /* Fill in the the 'key' as appropriate to retrieve the entry for nbr
50 * from the ospf_interface's nbrs table. Indexed by interface address
51 * for all cases except Virtual-link and PointToPoint interfaces, where
52 * neighbours are indexed by router-ID instead.
54 static void ospf_nbr_key(struct ospf_interface
*oi
, struct ospf_neighbor
*nbr
,
57 key
->family
= AF_INET
;
58 key
->prefixlen
= IPV4_MAX_BITLEN
;
60 /* vlinks are indexed by router-id */
61 if (oi
->type
== OSPF_IFTYPE_VIRTUALLINK
62 || oi
->type
== OSPF_IFTYPE_POINTOPOINT
)
63 key
->u
.prefix4
= nbr
->router_id
;
65 key
->u
.prefix4
= nbr
->src
;
69 struct ospf_neighbor
*ospf_nbr_new(struct ospf_interface
*oi
)
71 struct ospf_neighbor
*nbr
;
73 /* Allcate new neighbor. */
74 nbr
= XCALLOC(MTYPE_OSPF_NEIGHBOR
, sizeof(struct ospf_neighbor
));
76 /* Relate neighbor to the interface. */
79 /* Set default values. */
80 nbr
->state
= NSM_Down
;
82 /* Set inheritance values. */
83 nbr
->v_inactivity
= OSPF_IF_PARAM(oi
, v_wait
);
84 nbr
->v_db_desc
= OSPF_IF_PARAM(oi
, retransmit_interval
);
85 nbr
->v_ls_req
= OSPF_IF_PARAM(oi
, retransmit_interval
);
86 nbr
->v_ls_upd
= OSPF_IF_PARAM(oi
, retransmit_interval
);
90 nbr
->dd_flags
= OSPF_DD_FLAG_MS
| OSPF_DD_FLAG_M
| OSPF_DD_FLAG_I
;
92 /* Last received and sent DD. */
93 nbr
->last_send
= NULL
;
97 ospf_lsdb_init(&nbr
->db_sum
);
98 ospf_lsdb_init(&nbr
->ls_rxmt
);
99 ospf_lsdb_init(&nbr
->ls_req
);
101 nbr
->crypt_seqnum
= 0;
103 /* Initialize GR Helper info*/
104 nbr
->gr_helper_info
.recvd_grace_period
= 0;
105 nbr
->gr_helper_info
.actual_grace_period
= 0;
106 nbr
->gr_helper_info
.gr_helper_status
= OSPF_GR_NOT_HELPER
;
107 nbr
->gr_helper_info
.helper_exit_reason
= OSPF_GR_HELPER_EXIT_NONE
;
108 nbr
->gr_helper_info
.gr_restart_reason
= OSPF_GR_UNKNOWN_RESTART
;
113 void ospf_nbr_free(struct ospf_neighbor
*nbr
)
115 /* Free DB summary list. */
116 if (ospf_db_summary_count(nbr
))
117 ospf_db_summary_clear(nbr
);
118 /* ospf_db_summary_delete_all (nbr); */
120 /* Free ls request list. */
121 if (ospf_ls_request_count(nbr
))
122 ospf_ls_request_delete_all(nbr
);
124 /* Free retransmit list. */
125 if (ospf_ls_retransmit_count(nbr
))
126 ospf_ls_retransmit_clear(nbr
);
129 ospf_lsdb_cleanup(&nbr
->db_sum
);
130 ospf_lsdb_cleanup(&nbr
->ls_req
);
131 ospf_lsdb_cleanup(&nbr
->ls_rxmt
);
133 /* Clear last send packet. */
135 ospf_packet_free(nbr
->last_send
);
138 nbr
->nbr_nbma
->nbr
= NULL
;
139 nbr
->nbr_nbma
= NULL
;
142 /* Cancel all timers. */
143 OSPF_NSM_TIMER_OFF(nbr
->t_inactivity
);
144 OSPF_NSM_TIMER_OFF(nbr
->t_db_desc
);
145 OSPF_NSM_TIMER_OFF(nbr
->t_ls_req
);
146 OSPF_NSM_TIMER_OFF(nbr
->t_ls_upd
);
148 /* Cancel all events. */ /* Thread lookup cost would be negligible. */
149 thread_cancel_event(master
, nbr
);
151 bfd_sess_free(&nbr
->bfd_session
);
153 OSPF_NSM_TIMER_OFF(nbr
->gr_helper_info
.t_grace_timer
);
156 XFREE(MTYPE_OSPF_NEIGHBOR
, nbr
);
159 /* Delete specified OSPF neighbor from interface. */
160 void ospf_nbr_delete(struct ospf_neighbor
*nbr
)
162 struct ospf_interface
*oi
;
163 struct route_node
*rn
;
168 /* get appropriate prefix 'key' */
169 ospf_nbr_key(oi
, nbr
, &p
);
171 rn
= route_node_lookup(oi
->nbrs
, &p
);
173 /* If lookup for a NBR succeeds, the leaf route_node could
174 * only exist because there is (or was) a nbr there.
175 * If the nbr was deleted, the leaf route_node should have
176 * lost its last refcount too, and be deleted.
177 * Therefore a looked-up leaf route_node in nbrs table
178 * should never have NULL info.
184 route_unlock_node(rn
);
186 zlog_info("Can't find neighbor %pI4 in the interface %s",
187 &nbr
->src
, IF_NAME(oi
));
189 route_unlock_node(rn
);
192 * This neighbor was not found, but before we move on and
193 * free the neighbor structre, make sure that it was not
194 * indexed incorrectly and ended up in the "worng" place
197 /* Reverse the lookup rules */
198 if (oi
->type
== OSPF_IFTYPE_VIRTUALLINK
199 || oi
->type
== OSPF_IFTYPE_POINTOPOINT
)
200 p
.u
.prefix4
= nbr
->src
;
202 p
.u
.prefix4
= nbr
->router_id
;
204 rn
= route_node_lookup(oi
->nbrs
, &p
);
206 /* We found the neighbor!
207 * Now make sure it is not the exact same neighbor
208 * structure that we are about to free
210 if (nbr
== rn
->info
) {
211 /* Same neighbor, drop the reference to it */
213 route_unlock_node(rn
);
215 route_unlock_node(rn
);
219 /* Free ospf_neighbor structure. */
223 /* Check myself is in the neighbor list. */
224 int ospf_nbr_bidirectional(struct in_addr
*router_id
, struct in_addr
*neighbors
,
230 max
= size
/ sizeof(struct in_addr
);
232 for (i
= 0; i
< max
; i
++)
233 if (IPV4_ADDR_SAME(router_id
, &neighbors
[i
]))
240 void ospf_nbr_self_reset(struct ospf_interface
*oi
, struct in_addr router_id
)
243 ospf_nbr_delete(oi
->nbr_self
);
245 oi
->nbr_self
= ospf_nbr_new(oi
);
246 ospf_nbr_add_self(oi
, router_id
);
249 /* Add self to nbr list. */
250 void ospf_nbr_add_self(struct ospf_interface
*oi
, struct in_addr router_id
)
253 struct route_node
*rn
;
256 oi
->nbr_self
= ospf_nbr_new(oi
);
259 oi
->nbr_self
->address
= *oi
->address
;
260 oi
->nbr_self
->priority
= OSPF_IF_PARAM(oi
, priority
);
261 oi
->nbr_self
->router_id
= router_id
;
262 oi
->nbr_self
->src
= oi
->address
->u
.prefix4
;
263 oi
->nbr_self
->state
= NSM_TwoWay
;
265 switch (oi
->area
->external_routing
) {
266 case OSPF_AREA_DEFAULT
:
267 SET_FLAG(oi
->nbr_self
->options
, OSPF_OPTION_E
);
270 UNSET_FLAG(oi
->nbr_self
->options
, OSPF_OPTION_E
);
273 UNSET_FLAG(oi
->nbr_self
->options
, OSPF_OPTION_E
);
274 SET_FLAG(oi
->nbr_self
->options
, OSPF_OPTION_NP
);
278 /* Add nbr_self to nbrs table */
279 ospf_nbr_key(oi
, oi
->nbr_self
, &p
);
281 rn
= route_node_get(oi
->nbrs
, &p
);
283 /* There is already pseudo neighbor. */
284 if (IS_DEBUG_OSPF_EVENT
)
286 "router_id %pI4 already present in neighbor table. node refcount %u",
287 &router_id
, route_node_get_lock_count(rn
));
288 route_unlock_node(rn
);
290 rn
->info
= oi
->nbr_self
;
293 /* Get neighbor count by status.
294 Specify status = 0, get all neighbor other than myself. */
295 int ospf_nbr_count(struct ospf_interface
*oi
, int state
)
297 struct ospf_neighbor
*nbr
;
298 struct route_node
*rn
;
301 for (rn
= route_top(oi
->nbrs
); rn
; rn
= route_next(rn
))
302 if ((nbr
= rn
->info
))
303 if (!IPV4_ADDR_SAME(&nbr
->router_id
,
304 &oi
->ospf
->router_id
))
305 if (state
== 0 || nbr
->state
== state
)
311 int ospf_nbr_count_opaque_capable(struct ospf_interface
*oi
)
313 struct ospf_neighbor
*nbr
;
314 struct route_node
*rn
;
317 for (rn
= route_top(oi
->nbrs
); rn
; rn
= route_next(rn
))
318 if ((nbr
= rn
->info
))
319 if (!IPV4_ADDR_SAME(&nbr
->router_id
,
320 &oi
->ospf
->router_id
))
321 if (nbr
->state
== NSM_Full
)
322 if (CHECK_FLAG(nbr
->options
,
329 /* lookup nbr by address - use this only if you know you must
330 * otherwise use the ospf_nbr_lookup() wrapper, which deals
331 * with virtual link and PointToPoint neighbours
333 struct ospf_neighbor
*ospf_nbr_lookup_by_addr(struct route_table
*nbrs
,
334 struct in_addr
*addr
)
337 struct route_node
*rn
;
338 struct ospf_neighbor
*nbr
;
341 p
.prefixlen
= IPV4_MAX_BITLEN
;
344 rn
= route_node_lookup(nbrs
, &p
);
348 /* See comment in ospf_nbr_delete */
351 if (rn
->info
== NULL
) {
352 route_unlock_node(rn
);
356 nbr
= (struct ospf_neighbor
*)rn
->info
;
357 route_unlock_node(rn
);
362 struct ospf_neighbor
*ospf_nbr_lookup_by_routerid(struct route_table
*nbrs
,
365 struct route_node
*rn
;
366 struct ospf_neighbor
*nbr
;
368 for (rn
= route_top(nbrs
); rn
; rn
= route_next(rn
))
369 if ((nbr
= rn
->info
) != NULL
)
370 if (IPV4_ADDR_SAME(&nbr
->router_id
, id
)) {
371 route_unlock_node(rn
);
378 void ospf_renegotiate_optional_capabilities(struct ospf
*top
)
380 struct listnode
*node
;
381 struct ospf_interface
*oi
;
382 struct route_table
*nbrs
;
383 struct route_node
*rn
;
384 struct ospf_neighbor
*nbr
;
386 /* At first, flush self-originated LSAs from routing domain. */
387 ospf_flush_self_originated_lsas_now(top
);
389 /* Revert all neighbor status to ExStart. */
390 for (ALL_LIST_ELEMENTS_RO(top
->oiflist
, node
, oi
)) {
391 if ((nbrs
= oi
->nbrs
) == NULL
)
394 for (rn
= route_top(nbrs
); rn
; rn
= route_next(rn
)) {
395 if ((nbr
= rn
->info
) == NULL
|| nbr
== oi
->nbr_self
)
398 if (nbr
->state
< NSM_ExStart
)
401 if (IS_DEBUG_OSPF_EVENT
)
403 "Renegotiate optional capabilities with neighbor(%pI4)",
406 OSPF_NSM_EVENT_SCHEDULE(nbr
, NSM_SeqNumberMismatch
);
410 /* Refresh/Re-originate external LSAs (Type-7 and Type-5).*/
411 ospf_external_lsa_rid_change(top
);
417 struct ospf_neighbor
*ospf_nbr_lookup(struct ospf_interface
*oi
, struct ip
*iph
,
418 struct ospf_header
*ospfh
)
420 struct in_addr srcaddr
= iph
->ip_src
;
422 if (oi
->type
== OSPF_IFTYPE_VIRTUALLINK
423 || oi
->type
== OSPF_IFTYPE_POINTOPOINT
)
424 return (ospf_nbr_lookup_by_routerid(oi
->nbrs
,
427 return (ospf_nbr_lookup_by_addr(oi
->nbrs
, &srcaddr
));
430 static struct ospf_neighbor
*ospf_nbr_add(struct ospf_interface
*oi
,
431 struct ospf_header
*ospfh
,
434 struct ospf_neighbor
*nbr
;
436 nbr
= ospf_nbr_new(oi
);
437 nbr
->state
= NSM_Down
;
438 nbr
->src
= p
->u
.prefix4
;
439 memcpy(&nbr
->address
, p
, sizeof(struct prefix
));
441 nbr
->nbr_nbma
= NULL
;
442 if (oi
->type
== OSPF_IFTYPE_NBMA
) {
443 struct ospf_nbr_nbma
*nbr_nbma
;
444 struct listnode
*node
;
446 for (ALL_LIST_ELEMENTS_RO(oi
->nbr_nbma
, node
, nbr_nbma
)) {
447 if (IPV4_ADDR_SAME(&nbr_nbma
->addr
, &nbr
->src
)) {
449 nbr
->nbr_nbma
= nbr_nbma
;
451 if (nbr_nbma
->t_poll
)
452 OSPF_POLL_TIMER_OFF(nbr_nbma
->t_poll
);
454 nbr
->state_change
= nbr_nbma
->state_change
+ 1;
459 /* New nbr, save the crypto sequence number if necessary */
460 if (ntohs(ospfh
->auth_type
) == OSPF_AUTH_CRYPTOGRAPHIC
)
461 nbr
->crypt_seqnum
= ospfh
->u
.crypt
.crypt_seqnum
;
463 /* Configure BFD if interface has it. */
464 ospf_neighbor_bfd_apply(nbr
);
466 if (IS_DEBUG_OSPF_EVENT
)
467 zlog_debug("NSM[%s:%pI4]: start", IF_NAME(oi
),
473 struct ospf_neighbor
*ospf_nbr_get(struct ospf_interface
*oi
,
474 struct ospf_header
*ospfh
, struct ip
*iph
,
477 struct route_node
*rn
;
479 struct ospf_neighbor
*nbr
;
481 key
.family
= AF_INET
;
482 key
.prefixlen
= IPV4_MAX_BITLEN
;
484 if (oi
->type
== OSPF_IFTYPE_VIRTUALLINK
485 || oi
->type
== OSPF_IFTYPE_POINTOPOINT
)
486 key
.u
.prefix4
= ospfh
->router_id
; /* index vlink and ptp nbrs by
489 key
.u
.prefix4
= iph
->ip_src
;
491 rn
= route_node_get(oi
->nbrs
, &key
);
493 route_unlock_node(rn
);
496 if (oi
->type
== OSPF_IFTYPE_NBMA
&& nbr
->state
== NSM_Attempt
) {
497 nbr
->src
= iph
->ip_src
;
498 memcpy(&nbr
->address
, p
, sizeof(struct prefix
));
501 rn
->info
= nbr
= ospf_nbr_add(oi
, ospfh
, p
);
504 nbr
->router_id
= ospfh
->router_id
;