blob: a302aa919267dc361b689662f7bb8ea5e5241ccd [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
205ospf_nbr_count (struct route_table *nbrs, int state)
206{
207 struct route_node *rn;
208 struct ospf_neighbor *nbr;
209 int count = 0;
210
211 /* Sanity check. */
212 if (nbrs == NULL)
213 return 0;
214
215 for (rn = route_top (nbrs); rn; rn = route_next (rn))
216 if ((nbr = rn->info) != NULL)
217 /* Ignore myself. */
218 if (!IPV4_ADDR_SAME (&nbr->router_id, &ospf_top->router_id))
219 if (state == 0 || nbr->state == state)
220 count++;
221
222 return count;
223}
224
225#ifdef HAVE_OPAQUE_LSA
226int
227ospf_opaque_capable_nbr_count (struct route_table *nbrs, int state)
228{
229 struct route_node *rn;
230 struct ospf_neighbor *nbr;
231 int count = 0;
232
233 /* Sanity check. */
234 if (nbrs == NULL)
235 return 0;
236
237 for (rn = route_top (nbrs); rn; rn = route_next (rn))
238 if ((nbr = rn->info) != NULL)
239 /* Ignore myself. */
240 if (!IPV4_ADDR_SAME (&nbr->router_id, &ospf_top->router_id))
241 if ((state == 0 || nbr->state == state)
242 && CHECK_FLAG (nbr->options, OSPF_OPTION_O))
243 count++;
244
245 return count;
246}
247#endif /* HAVE_OPAQUE_LSA */
248
249struct ospf_neighbor *
250ospf_nbr_lookup_by_addr (struct route_table *nbrs,
251 struct in_addr *addr)
252{
253 struct prefix p;
254 struct route_node *rn;
255 struct ospf_neighbor *nbr;
256
257 p.family = AF_INET;
258 p.prefixlen = IPV4_MAX_BITLEN;
259 p.u.prefix4 = *addr;
260
261 rn = route_node_lookup (nbrs, &p);
262 if (! rn)
263 return NULL;
264
265 if (rn->info == NULL)
266 {
267 route_unlock_node (rn);
268 return NULL;
269 }
270
271 nbr = (struct ospf_neighbor *) rn->info;
272 route_unlock_node (rn);
273
274 return nbr;
275}
276
277struct ospf_neighbor *
278ospf_nbr_lookup_by_routerid (struct route_table *nbrs,
279 struct in_addr *id)
280{
281 struct route_node *rn;
282 struct ospf_neighbor *nbr;
283
284 for (rn = route_top (nbrs); rn; rn = route_next (rn))
285 if ((nbr = rn->info) != NULL)
286 if (IPV4_ADDR_SAME (&nbr->router_id, id))
287 {
288 route_unlock_node(rn);
289 return nbr;
290 }
291
292 return NULL;
293}
294
295void
296ospf_renegotiate_optional_capabilities (struct ospf *top)
297{
298 listnode node;
299 struct ospf_interface *oi;
300 struct route_table *nbrs;
301 struct route_node *rn;
302 struct ospf_neighbor *nbr;
303
304 /* At first, flush self-originated LSAs from routing domain. */
305 ospf_flush_self_originated_lsas_now (top);
306
307 /* Revert all neighbor status to ExStart. */
308 for (node = listhead (top->oiflist); node; nextnode (node))
309 {
310 if ((oi = getdata (node)) == NULL || (nbrs = oi->nbrs) == NULL)
311 continue;
312
313 for (rn = route_top (nbrs); rn; rn = route_next (rn))
314 {
315 if ((nbr = rn->info) == NULL || nbr == oi->nbr_self)
316 continue;
317
318 if (nbr->state < NSM_ExStart)
319 continue;
320
321 if (IS_DEBUG_OSPF_EVENT)
322 zlog_info ("Renegotiate optional capabilities with neighbor(%s)", inet_ntoa (nbr->router_id));
323
324 OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
325 }
326 }
327
328 return;
329}