blob: ccef055924a37a34dadf967658f38b4686711513 [file] [log] [blame]
paul2d598362003-01-17 23:48:42 +00001/*
2 * OSPF Neighbor functions.
3 * Copyright (C) 1999, 2000 Toshiaki Takada
4 *
5 * This file is part of GNU Zebra.
6 *
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.
11 *
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.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with GNU Zebra; see the file COPYING. If not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
21 */
22
23#include <zebra.h>
24
25#include "linklist.h"
26#include "prefix.h"
27#include "memory.h"
28#include "command.h"
29#include "thread.h"
30#include "stream.h"
31#include "table.h"
32#include "log.h"
33
34#include "ospfd/ospfd.h"
35#include "ospfd/ospf_interface.h"
36#include "ospfd/ospf_asbr.h"
37#include "ospfd/ospf_lsa.h"
38#include "ospfd/ospf_lsdb.h"
39#include "ospfd/ospf_neighbor.h"
40#include "ospfd/ospf_nsm.h"
41#include "ospfd/ospf_packet.h"
42#include "ospfd/ospf_network.h"
43#include "ospfd/ospf_flood.h"
44#include "ospfd/ospf_dump.h"
45
46struct ospf_neighbor *
47ospf_nbr_new (struct ospf_interface *oi)
48{
49 struct ospf_neighbor *nbr;
50
51 /* Allcate new neighbor. */
52 nbr = XMALLOC (MTYPE_OSPF_NEIGHBOR, sizeof (struct ospf_neighbor));
53 memset (nbr, 0, sizeof (struct ospf_neighbor));
54
55 /* Relate neighbor to the interface. */
56 nbr->oi = oi;
57
58 /* Set default values. */
59 nbr->state = NSM_Down;
60
61 /* Set inheritance values. */
62 nbr->v_inactivity = OSPF_IF_PARAM (oi, v_wait);
63 nbr->v_db_desc = OSPF_IF_PARAM (oi, retransmit_interval);
64 nbr->v_ls_req = OSPF_IF_PARAM (oi, retransmit_interval);
65 nbr->v_ls_upd = OSPF_IF_PARAM (oi, retransmit_interval);
66 nbr->priority = -1;
67
68 /* DD flags. */
69 nbr->dd_flags = OSPF_DD_FLAG_MS|OSPF_DD_FLAG_M|OSPF_DD_FLAG_I;
70
71 /* Last received and sent DD. */
72 nbr->last_send = NULL;
73
74 nbr->nbr_nbma = NULL;
75
76 ospf_lsdb_init (&nbr->db_sum);
77 ospf_lsdb_init (&nbr->ls_rxmt);
78 ospf_lsdb_init (&nbr->ls_req);
79
80 nbr->crypt_seqnum = 0;
81
82 return nbr;
83}
84
85void
86ospf_nbr_free (struct ospf_neighbor *nbr)
87{
88 /* Free DB summary list. */
89 if (ospf_db_summary_count (nbr))
90 ospf_db_summary_clear (nbr);
91 /* ospf_db_summary_delete_all (nbr); */
92
93 /* Free ls request list. */
94 if (ospf_ls_request_count (nbr))
95 ospf_ls_request_delete_all (nbr);
96
97 /* Free retransmit list. */
98 if (ospf_ls_retransmit_count (nbr))
99 ospf_ls_retransmit_clear (nbr);
100
101 /* Cleanup LSDBs. */
102 ospf_lsdb_cleanup (&nbr->db_sum);
103 ospf_lsdb_cleanup (&nbr->ls_req);
104 ospf_lsdb_cleanup (&nbr->ls_rxmt);
105
106 /* Clear last send packet. */
107 if (nbr->last_send)
108 ospf_packet_free (nbr->last_send);
109
110 if (nbr->nbr_nbma)
111 {
112 nbr->nbr_nbma->nbr = NULL;
113 nbr->nbr_nbma = NULL;
114 }
115
116 /* Cancel all timers. */
117 OSPF_NSM_TIMER_OFF (nbr->t_inactivity);
118 OSPF_NSM_TIMER_OFF (nbr->t_db_desc);
119 OSPF_NSM_TIMER_OFF (nbr->t_ls_req);
120 OSPF_NSM_TIMER_OFF (nbr->t_ls_upd);
121
122 /* Cancel all events. *//* Thread lookup cost would be negligible. */
123 thread_cancel_event (master, nbr);
124
125 XFREE (MTYPE_OSPF_NEIGHBOR, nbr);
126}
127
128/* Delete specified OSPF neighbor from interface. */
129void
130ospf_nbr_delete (struct ospf_neighbor *nbr)
131{
132 struct ospf_interface *oi;
133 struct route_node *rn;
134 struct prefix p;
135
136 oi = nbr->oi;
137
138 /* Unlink ospf neighbor from the interface. */
139 p.family = AF_INET;
140 p.prefixlen = IPV4_MAX_BITLEN;
141 p.u.prefix4 = nbr->src;
142
143 rn = route_node_lookup (oi->nbrs, &p);
144 if (rn)
145 {
146 if (rn->info)
147 {
148 rn->info = NULL;
149 route_unlock_node (rn);
150 }
151 else
152 zlog_info ("Can't find neighbor %s in the interface %s",
153 inet_ntoa (nbr->src), IF_NAME (oi));
154
155 route_unlock_node (rn);
156 }
157
158 /* Free ospf_neighbor structure. */
159 ospf_nbr_free (nbr);
160}
161
162/* Check myself is in the neighbor list. */
163int
164ospf_nbr_bidirectional (struct in_addr *router_id,
165 struct in_addr *neighbors, int size)
166{
167 int i;
168 int max;
169
170 max = size / sizeof (struct in_addr);
171
172 for (i = 0; i < max; i ++)
173 if (IPV4_ADDR_SAME (router_id, &neighbors[i]))
174 return 1;
175
176 return 0;
177}
178
179/* Add self to nbr list. */
180void
181ospf_nbr_add_self (struct ospf_interface *oi)
182{
183 struct ospf_neighbor *nbr;
184 struct prefix p;
185 struct route_node *rn;
186
187 p.family = AF_INET;
188 p.prefixlen = 32;
189 p.u.prefix4 = oi->address->u.prefix4;
190
191 rn = route_node_get (oi->nbrs, &p);
192 if (rn->info)
193 {
194 /* There is already pseudo neighbor. */
195 nbr = rn->info;
196 route_unlock_node (rn);
197 }
198 else
199 rn->info = oi->nbr_self;
200}
201
202/* Get neighbor count by status.
203 Specify status = 0, get all neighbor other than myself. */
204int
paul68980082003-03-25 05:07:42 +0000205ospf_nbr_count (struct ospf_interface *oi, int state)
paul2d598362003-01-17 23:48:42 +0000206{
paul2d598362003-01-17 23:48:42 +0000207 struct ospf_neighbor *nbr;
paul68980082003-03-25 05:07:42 +0000208 struct route_node *rn;
paul2d598362003-01-17 23:48:42 +0000209 int count = 0;
210
paul68980082003-03-25 05:07:42 +0000211 for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
212 if ((nbr = rn->info))
213 if (!IPV4_ADDR_SAME (&nbr->router_id, &oi->ospf->router_id))
paul2d598362003-01-17 23:48:42 +0000214 if (state == 0 || nbr->state == state)
215 count++;
216
217 return count;
218}
219
220#ifdef HAVE_OPAQUE_LSA
221int
paul68980082003-03-25 05:07:42 +0000222ospf_nbr_count_opaque_capable (struct ospf_interface *oi)
paul2d598362003-01-17 23:48:42 +0000223{
paul2d598362003-01-17 23:48:42 +0000224 struct ospf_neighbor *nbr;
paul68980082003-03-25 05:07:42 +0000225 struct route_node *rn;
paul2d598362003-01-17 23:48:42 +0000226 int count = 0;
227
paul68980082003-03-25 05:07:42 +0000228 for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
229 if ((nbr = rn->info))
230 if (!IPV4_ADDR_SAME (&nbr->router_id, &oi->ospf->router_id))
231 if (nbr->state == NSM_Full)
232 if (CHECK_FLAG (nbr->options, OSPF_OPTION_O))
233 count++;
paul2d598362003-01-17 23:48:42 +0000234
235 return count;
236}
237#endif /* HAVE_OPAQUE_LSA */
238
239struct ospf_neighbor *
240ospf_nbr_lookup_by_addr (struct route_table *nbrs,
241 struct in_addr *addr)
242{
243 struct prefix p;
244 struct route_node *rn;
245 struct ospf_neighbor *nbr;
246
247 p.family = AF_INET;
248 p.prefixlen = IPV4_MAX_BITLEN;
249 p.u.prefix4 = *addr;
250
251 rn = route_node_lookup (nbrs, &p);
252 if (! rn)
253 return NULL;
254
255 if (rn->info == NULL)
256 {
257 route_unlock_node (rn);
258 return NULL;
259 }
260
261 nbr = (struct ospf_neighbor *) rn->info;
262 route_unlock_node (rn);
263
264 return nbr;
265}
266
267struct ospf_neighbor *
268ospf_nbr_lookup_by_routerid (struct route_table *nbrs,
269 struct in_addr *id)
270{
271 struct route_node *rn;
272 struct ospf_neighbor *nbr;
273
274 for (rn = route_top (nbrs); rn; rn = route_next (rn))
275 if ((nbr = rn->info) != NULL)
276 if (IPV4_ADDR_SAME (&nbr->router_id, id))
277 {
278 route_unlock_node(rn);
279 return nbr;
280 }
281
282 return NULL;
283}
284
285void
286ospf_renegotiate_optional_capabilities (struct ospf *top)
287{
288 listnode node;
289 struct ospf_interface *oi;
290 struct route_table *nbrs;
291 struct route_node *rn;
292 struct ospf_neighbor *nbr;
293
294 /* At first, flush self-originated LSAs from routing domain. */
295 ospf_flush_self_originated_lsas_now (top);
296
297 /* Revert all neighbor status to ExStart. */
298 for (node = listhead (top->oiflist); node; nextnode (node))
299 {
300 if ((oi = getdata (node)) == NULL || (nbrs = oi->nbrs) == NULL)
301 continue;
302
303 for (rn = route_top (nbrs); rn; rn = route_next (rn))
304 {
305 if ((nbr = rn->info) == NULL || nbr == oi->nbr_self)
306 continue;
307
308 if (nbr->state < NSM_ExStart)
309 continue;
310
311 if (IS_DEBUG_OSPF_EVENT)
312 zlog_info ("Renegotiate optional capabilities with neighbor(%s)", inet_ntoa (nbr->router_id));
313
314 OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
315 }
316 }
317
318 return;
319}