]> git.proxmox.com Git - mirror_frr.git/blob - ospf6d/ospf6_nsm.c
Start of new ospf6d merge from Zebra.
[mirror_frr.git] / ospf6d / ospf6_nsm.c
1 /*
2 * Copyright (C) 1999 Yasuhiro Ohara
3 *
4 * This file is part of GNU Zebra.
5 *
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with GNU Zebra; see the file COPYING. If not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
20 */
21
22 #include "ospf6d.h"
23
24 static int
25 nbs_full_change (struct ospf6_interface *ospf6_interface)
26 {
27 CALL_FOREACH_LSA_HOOK (hook_interface, hook_change, ospf6_interface);
28 return 0;
29 }
30
31 static int
32 nbs_change (state_t nbs_next, char *reason, struct ospf6_neighbor *o6n)
33 {
34 state_t nbs_previous;
35
36 nbs_previous = o6n->state;
37 o6n->state = nbs_next;
38
39 if (nbs_previous == nbs_next)
40 return 0;
41
42 /* statistics */
43 o6n->ospf6_stat_state_changed++;
44 gettimeofday (&o6n->last_changed, NULL);
45
46 /* log */
47 if (IS_OSPF6_DUMP_NEIGHBOR)
48 {
49 if (reason)
50 zlog_info ("Neighbor status change %s: [%s]->[%s](%s)",
51 o6n->str,
52 ospf6_neighbor_state_string[nbs_previous],
53 ospf6_neighbor_state_string[nbs_next],
54 reason);
55 else
56 zlog_info ("Neighbor status change %s: [%s]->[%s]",
57 o6n->str,
58 ospf6_neighbor_state_string[nbs_previous],
59 ospf6_neighbor_state_string[nbs_next]);
60 }
61
62 if (nbs_previous == NBS_FULL || nbs_next == NBS_FULL)
63 nbs_full_change (o6n->ospf6_interface);
64
65 /* check for LSAs that already reached MaxAge */
66 if ((nbs_previous == NBS_EXCHANGE || nbs_previous == NBS_LOADING) &&
67 (nbs_next != NBS_EXCHANGE && nbs_next != NBS_LOADING))
68 {
69 ospf6_maxage_remover ();
70 }
71
72 CALL_CHANGE_HOOK (&neighbor_hook, o6n);
73
74 return 0;
75 }
76
77 /* RFC2328 section 10.4 */
78 int
79 need_adjacency (struct ospf6_neighbor *o6n)
80 {
81
82 if (o6n->ospf6_interface->state == IFS_PTOP)
83 return 1;
84 if (o6n->ospf6_interface->state == IFS_DR)
85 return 1;
86 if (o6n->ospf6_interface->state == IFS_BDR)
87 return 1;
88 if (o6n->router_id == o6n->ospf6_interface->dr)
89 return 1;
90 if (o6n->router_id == o6n->ospf6_interface->bdr)
91 return 1;
92
93 return 0;
94 }
95
96 int
97 hello_received (struct thread *thread)
98 {
99 struct ospf6_neighbor *o6n;
100
101 o6n = (struct ospf6_neighbor *) THREAD_ARG (thread);
102 assert (o6n);
103
104 if (IS_OSPF6_DUMP_NEIGHBOR)
105 zlog_info ("Neighbor Event %s: *HelloReceived*", o6n->str);
106
107 if (o6n->inactivity_timer)
108 thread_cancel (o6n->inactivity_timer);
109
110 o6n->inactivity_timer = thread_add_timer (master, inactivity_timer, o6n,
111 o6n->ospf6_interface->dead_interval);
112 if (o6n->state <= NBS_DOWN)
113 nbs_change (NBS_INIT, "HelloReceived", o6n);
114 return 0;
115 }
116
117 int
118 twoway_received (struct thread *thread)
119 {
120 struct ospf6_neighbor *o6n;
121
122 o6n = (struct ospf6_neighbor *) THREAD_ARG (thread);
123 assert (o6n);
124
125 if (o6n->state > NBS_INIT)
126 return 0;
127
128 if (IS_OSPF6_DUMP_NEIGHBOR)
129 zlog_info ("Neighbor Event %s: *2Way-Received*", o6n->str);
130
131 thread_add_event (master, neighbor_change, o6n->ospf6_interface, 0);
132
133 if (!need_adjacency (o6n))
134 {
135 nbs_change (NBS_TWOWAY, "No Need Adjacency", o6n);
136 return 0;
137 }
138 else
139 nbs_change (NBS_EXSTART, "Need Adjacency", o6n);
140
141 DD_MSBIT_SET (o6n->dbdesc_bits);
142 DD_MBIT_SET (o6n->dbdesc_bits);
143 DD_IBIT_SET (o6n->dbdesc_bits);
144
145 if (o6n->thread_send_dbdesc)
146 thread_cancel (o6n->thread_send_dbdesc);
147 o6n->thread_send_dbdesc =
148 thread_add_event (master, ospf6_send_dbdesc, o6n, 0);
149 if (o6n->thread_rxmt_dbdesc)
150 thread_cancel (o6n->thread_rxmt_dbdesc);
151 o6n->thread_rxmt_dbdesc = (struct thread *) NULL;
152
153 return 0;
154 }
155
156 int
157 negotiation_done (struct thread *thread)
158 {
159 struct ospf6_neighbor *o6n;
160
161 o6n = (struct ospf6_neighbor *) THREAD_ARG (thread);
162 assert (o6n);
163
164 if (o6n->state != NBS_EXSTART)
165 return 0;
166
167 if (IS_OSPF6_DUMP_NEIGHBOR)
168 zlog_info ("Neighbor Event %s: *NegotiationDone*", o6n->str);
169
170 nbs_change (NBS_EXCHANGE, "NegotiationDone", o6n);
171 DD_IBIT_CLEAR (o6n->dbdesc_bits);
172
173 return 0;
174 }
175
176 int
177 exchange_done (struct thread *thread)
178 {
179 struct ospf6_neighbor *o6n;
180
181 o6n = (struct ospf6_neighbor *) THREAD_ARG (thread);
182 assert (o6n);
183
184 if (o6n->state != NBS_EXCHANGE)
185 return 0;
186
187 if (o6n->thread_rxmt_dbdesc)
188 thread_cancel (o6n->thread_rxmt_dbdesc);
189 o6n->thread_rxmt_dbdesc = (struct thread *) NULL;
190
191 if (IS_OSPF6_DUMP_NEIGHBOR)
192 zlog_info ("Neighbor Event %s: *ExchangeDone*", o6n->str);
193
194 ospf6_lsdb_remove_all (o6n->dbdesc_list);
195
196 thread_add_timer (master, ospf6_neighbor_last_dbdesc_release, o6n,
197 o6n->ospf6_interface->dead_interval);
198
199 if (o6n->request_list->count == 0)
200 nbs_change (NBS_FULL, "Requestlist Empty", o6n);
201 else
202 {
203 thread_add_event (master, ospf6_send_lsreq, o6n, 0);
204 nbs_change (NBS_LOADING, "Requestlist Not Empty", o6n);
205 }
206 return 0;
207 }
208
209 int
210 loading_done (struct thread *thread)
211 {
212 struct ospf6_neighbor *o6n;
213
214 o6n = (struct ospf6_neighbor *) THREAD_ARG (thread);
215 assert (o6n);
216
217 if (o6n->state != NBS_LOADING)
218 return 0;
219
220 if (IS_OSPF6_DUMP_NEIGHBOR)
221 zlog_info ("Neighbor Event %s: *LoadingDone*", o6n->str);
222
223 assert (o6n->request_list->count == 0);
224
225 nbs_change (NBS_FULL, "LoadingDone", o6n);
226
227 return 0;
228 }
229
230 int
231 adj_ok (struct thread *thread)
232 {
233 struct ospf6_neighbor *o6n;
234
235 o6n = (struct ospf6_neighbor *) THREAD_ARG (thread);
236 assert (o6n);
237
238 if (IS_OSPF6_DUMP_NEIGHBOR)
239 zlog_info ("Neighbor Event %s: *AdjOK?*", o6n->str);
240
241 if (o6n->state == NBS_TWOWAY)
242 {
243 if (!need_adjacency (o6n))
244 {
245 nbs_change (NBS_TWOWAY, "No Need Adjacency", o6n);
246 return 0;
247 }
248 else
249 nbs_change (NBS_EXSTART, "Need Adjacency", o6n);
250
251 DD_MSBIT_SET (o6n->dbdesc_bits);
252 DD_MBIT_SET (o6n->dbdesc_bits);
253 DD_IBIT_SET (o6n->dbdesc_bits);
254
255 if (o6n->thread_send_dbdesc)
256 thread_cancel (o6n->thread_send_dbdesc);
257 o6n->thread_send_dbdesc =
258 thread_add_event (master, ospf6_send_dbdesc, o6n, 0);
259
260 return 0;
261 }
262
263 if (o6n->state >= NBS_EXSTART)
264 {
265 if (need_adjacency (o6n))
266 return 0;
267 else
268 {
269 nbs_change (NBS_TWOWAY, "No Need Adjacency", o6n);
270 ospf6_neighbor_lslist_clear (o6n);
271 }
272 }
273 return 0;
274 }
275
276 int
277 seqnumber_mismatch (struct thread *thread)
278 {
279 struct ospf6_neighbor *o6n;
280
281 o6n = (struct ospf6_neighbor *) THREAD_ARG (thread);
282 assert (o6n);
283
284 if (o6n->state < NBS_EXCHANGE)
285 return 0;
286
287 /* statistics */
288 o6n->ospf6_stat_seqnum_mismatch++;
289
290 if (IS_OSPF6_DUMP_NEIGHBOR)
291 zlog_info ("Neighbor Event %s: *SeqNumberMismatch*", o6n->str);
292
293 nbs_change (NBS_EXSTART, "SeqNumberMismatch", o6n);
294
295 DD_MSBIT_SET (o6n->dbdesc_bits);
296 DD_MBIT_SET (o6n->dbdesc_bits);
297 DD_IBIT_SET (o6n->dbdesc_bits);
298 ospf6_neighbor_lslist_clear (o6n);
299
300 if (o6n->thread_send_dbdesc)
301 thread_cancel (o6n->thread_send_dbdesc);
302 o6n->thread_send_dbdesc =
303 thread_add_event (master, ospf6_send_dbdesc, o6n, 0);
304
305 return 0;
306 }
307
308 int
309 bad_lsreq (struct thread *thread)
310 {
311 struct ospf6_neighbor *o6n;
312
313 o6n = (struct ospf6_neighbor *) THREAD_ARG (thread);
314 assert (o6n);
315
316 if (o6n->state < NBS_EXCHANGE)
317 return 0;
318
319 /* statistics */
320 o6n->ospf6_stat_bad_lsreq++;
321
322 if (IS_OSPF6_DUMP_NEIGHBOR)
323 zlog_info ("Neighbor Event %s: *BadLSReq*", o6n->str);
324
325 nbs_change (NBS_EXSTART, "BadLSReq", o6n);
326
327 DD_MSBIT_SET (o6n->dbdesc_bits);
328 DD_MBIT_SET (o6n->dbdesc_bits);
329 DD_IBIT_SET (o6n->dbdesc_bits);
330 ospf6_neighbor_lslist_clear (o6n);
331
332 if (o6n->thread_send_dbdesc)
333 thread_cancel (o6n->thread_send_dbdesc);
334 o6n->thread_send_dbdesc =
335 thread_add_event (master, ospf6_send_dbdesc, o6n, 0);
336
337 return 0;
338 }
339
340 int
341 oneway_received (struct thread *thread)
342 {
343 struct ospf6_neighbor *o6n;
344
345 o6n = (struct ospf6_neighbor *) THREAD_ARG (thread);
346 assert (o6n);
347
348 if (o6n->state < NBS_TWOWAY)
349 return 0;
350
351 /* statistics */
352 o6n->ospf6_stat_oneway_received++;
353
354 if (IS_OSPF6_DUMP_NEIGHBOR)
355 zlog_info ("Neighbor Event %s: *1Way-Received*", o6n->str);
356
357 nbs_change (NBS_INIT, "1Way-Received", o6n);
358
359 thread_add_event (master, neighbor_change, o6n->ospf6_interface, 0);
360
361 ospf6_neighbor_thread_cancel_all (o6n);
362 ospf6_neighbor_lslist_clear (o6n);
363 return 0;
364 }
365
366 int
367 inactivity_timer (struct thread *thread)
368 {
369 struct ospf6_neighbor *o6n;
370
371 o6n = (struct ospf6_neighbor *) THREAD_ARG (thread);
372 assert (o6n);
373
374 /* statistics */
375 o6n->ospf6_stat_inactivity_timer++;
376
377 if (IS_OSPF6_DUMP_NEIGHBOR)
378 zlog_info ("Neighbor Event %s: *InactivityTimer*", o6n->str);
379
380 o6n->inactivity_timer = NULL;
381 o6n->dr = o6n->bdr = o6n->prevdr = o6n->prevbdr = 0;
382 nbs_change (NBS_DOWN, "InactivityTimer", o6n);
383
384 thread_add_event (master, neighbor_change, o6n->ospf6_interface, 0);
385
386 listnode_delete (o6n->ospf6_interface->neighbor_list, o6n);
387 ospf6_neighbor_delete (o6n);
388
389 return 0;
390 }
391