]>
Commit | Line | Data |
---|---|---|
718e3744 | 1 | /* |
508e53e2 | 2 | * Copyright (C) 2003 Yasuhiro Ohara |
718e3744 | 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 | * | |
896014f4 DL |
16 | * You should have received a copy of the GNU General Public License along |
17 | * with this program; see the file COPYING; if not, write to the Free Software | |
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
718e3744 | 19 | */ |
20 | ||
718e3744 | 21 | #include <zebra.h> |
22 | ||
23 | #include "log.h" | |
508e53e2 | 24 | #include "memory.h" |
718e3744 | 25 | #include "thread.h" |
26 | #include "linklist.h" | |
27 | #include "vty.h" | |
28 | #include "command.h" | |
29 | ||
508e53e2 | 30 | #include "ospf6_proto.h" |
718e3744 | 31 | #include "ospf6_lsa.h" |
508e53e2 | 32 | #include "ospf6_lsdb.h" |
718e3744 | 33 | #include "ospf6_message.h" |
508e53e2 | 34 | #include "ospf6_top.h" |
35 | #include "ospf6_area.h" | |
36 | #include "ospf6_interface.h" | |
718e3744 | 37 | #include "ospf6_neighbor.h" |
508e53e2 | 38 | #include "ospf6_intra.h" |
3b4cd3a9 | 39 | #include "ospf6_flood.h" |
049207c3 | 40 | #include "ospf6d.h" |
7f342629 | 41 | #include "ospf6_bfd.h" |
4dfd8aff DW |
42 | #include "ospf6_abr.h" |
43 | #include "ospf6_asbr.h" | |
44 | #include "ospf6_lsa.h" | |
45 | #include "ospf6_spf.h" | |
46 | #include "ospf6_zebra.h" | |
718e3744 | 47 | |
3012671f | 48 | DEFINE_HOOK(ospf6_neighbor_change, |
d62a17ae | 49 | (struct ospf6_neighbor * on, int state, int next_state), |
50 | (on, state, next_state)) | |
3012671f | 51 | |
508e53e2 | 52 | unsigned char conf_debug_ospf6_neighbor = 0; |
53 | ||
2b64873d | 54 | const char *const ospf6_neighbor_state_str[] = { |
d62a17ae | 55 | "None", "Down", "Attempt", "Init", "Twoway", |
56 | "ExStart", "ExChange", "Loading", "Full", NULL}; | |
718e3744 | 57 | |
2b64873d DL |
58 | const char *const ospf6_neighbor_event_str[] = { |
59 | "NoEvent", "HelloReceived", "2-WayReceived", "NegotiationDone", | |
60 | "ExchangeDone", "LoadingDone", "AdjOK?", "SeqNumberMismatch", | |
61 | "BadLSReq", "1-WayReceived", "InactivityTimer", | |
62 | }; | |
63 | ||
d62a17ae | 64 | int ospf6_neighbor_cmp(void *va, void *vb) |
718e3744 | 65 | { |
d62a17ae | 66 | struct ospf6_neighbor *ona = (struct ospf6_neighbor *)va; |
67 | struct ospf6_neighbor *onb = (struct ospf6_neighbor *)vb; | |
27fa3398 DS |
68 | |
69 | if (ona->router_id == onb->router_id) | |
70 | return 0; | |
71 | ||
72 | return (ntohl(ona->router_id) < ntohl(onb->router_id)) ? -1 : 1; | |
718e3744 | 73 | } |
74 | ||
d7c0a89a | 75 | struct ospf6_neighbor *ospf6_neighbor_lookup(uint32_t router_id, |
d62a17ae | 76 | struct ospf6_interface *oi) |
718e3744 | 77 | { |
d62a17ae | 78 | struct listnode *n; |
79 | struct ospf6_neighbor *on; | |
80 | ||
81 | for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, n, on)) | |
82 | if (on->router_id == router_id) | |
83 | return on; | |
84 | ||
85 | return (struct ospf6_neighbor *)NULL; | |
718e3744 | 86 | } |
87 | ||
508e53e2 | 88 | /* create ospf6_neighbor */ |
d7c0a89a | 89 | struct ospf6_neighbor *ospf6_neighbor_create(uint32_t router_id, |
d62a17ae | 90 | struct ospf6_interface *oi) |
718e3744 | 91 | { |
d62a17ae | 92 | struct ospf6_neighbor *on; |
93 | char buf[16]; | |
94 | ||
aa406bbc | 95 | on = XCALLOC(MTYPE_OSPF6_NEIGHBOR, sizeof(struct ospf6_neighbor)); |
d62a17ae | 96 | inet_ntop(AF_INET, &router_id, buf, sizeof(buf)); |
97 | snprintf(on->name, sizeof(on->name), "%s%%%s", buf, | |
98 | oi->interface->name); | |
99 | on->ospf6_if = oi; | |
100 | on->state = OSPF6_NEIGHBOR_DOWN; | |
101 | on->state_change = 0; | |
102 | monotime(&on->last_changed); | |
103 | on->router_id = router_id; | |
104 | ||
105 | on->summary_list = ospf6_lsdb_create(on); | |
106 | on->request_list = ospf6_lsdb_create(on); | |
107 | on->retrans_list = ospf6_lsdb_create(on); | |
108 | ||
109 | on->dbdesc_list = ospf6_lsdb_create(on); | |
110 | on->lsupdate_list = ospf6_lsdb_create(on); | |
111 | on->lsack_list = ospf6_lsdb_create(on); | |
112 | ||
113 | listnode_add_sort(oi->neighbor_list, on); | |
114 | ||
115 | ospf6_bfd_info_nbr_create(oi, on); | |
116 | return on; | |
718e3744 | 117 | } |
118 | ||
d62a17ae | 119 | void ospf6_neighbor_delete(struct ospf6_neighbor *on) |
718e3744 | 120 | { |
0f9f74ba DS |
121 | struct ospf6_lsa *lsa, *lsa_next; |
122 | const struct route_node *iterend; | |
3b4cd3a9 | 123 | |
d62a17ae | 124 | ospf6_lsdb_remove_all(on->summary_list); |
125 | ospf6_lsdb_remove_all(on->request_list); | |
0f9f74ba DS |
126 | |
127 | for (iterend = ospf6_lsdb_head(on->retrans_list, 0, 0, 0, &lsa); lsa; | |
128 | lsa = lsa_next) { | |
129 | lsa_next = ospf6_lsdb_next(iterend, lsa); | |
d62a17ae | 130 | ospf6_decrement_retrans_count(lsa); |
131 | ospf6_lsdb_remove(lsa, on->retrans_list); | |
132 | } | |
718e3744 | 133 | |
d62a17ae | 134 | ospf6_lsdb_remove_all(on->dbdesc_list); |
135 | ospf6_lsdb_remove_all(on->lsupdate_list); | |
136 | ospf6_lsdb_remove_all(on->lsack_list); | |
508e53e2 | 137 | |
d62a17ae | 138 | ospf6_lsdb_delete(on->summary_list); |
139 | ospf6_lsdb_delete(on->request_list); | |
140 | ospf6_lsdb_delete(on->retrans_list); | |
718e3744 | 141 | |
d62a17ae | 142 | ospf6_lsdb_delete(on->dbdesc_list); |
143 | ospf6_lsdb_delete(on->lsupdate_list); | |
144 | ospf6_lsdb_delete(on->lsack_list); | |
508e53e2 | 145 | |
d62a17ae | 146 | THREAD_OFF(on->inactivity_timer); |
508e53e2 | 147 | |
d62a17ae | 148 | THREAD_OFF(on->thread_send_dbdesc); |
149 | THREAD_OFF(on->thread_send_lsreq); | |
150 | THREAD_OFF(on->thread_send_lsupdate); | |
151 | THREAD_OFF(on->thread_send_lsack); | |
508e53e2 | 152 | |
d62a17ae | 153 | ospf6_bfd_reg_dereg_nbr(on, ZEBRA_BFD_DEST_DEREGISTER); |
154 | XFREE(MTYPE_OSPF6_NEIGHBOR, on); | |
718e3744 | 155 | } |
156 | ||
d7c0a89a | 157 | static void ospf6_neighbor_state_change(uint8_t next_state, |
d62a17ae | 158 | struct ospf6_neighbor *on, int event) |
718e3744 | 159 | { |
d7c0a89a | 160 | uint8_t prev_state; |
d62a17ae | 161 | |
162 | prev_state = on->state; | |
163 | on->state = next_state; | |
164 | ||
165 | if (prev_state == next_state) | |
166 | return; | |
167 | ||
168 | on->state_change++; | |
169 | monotime(&on->last_changed); | |
170 | ||
171 | /* log */ | |
172 | if (IS_OSPF6_DEBUG_NEIGHBOR(STATE)) { | |
173 | zlog_debug("Neighbor state change %s: [%s]->[%s] (%s)", | |
174 | on->name, ospf6_neighbor_state_str[prev_state], | |
175 | ospf6_neighbor_state_str[next_state], | |
176 | ospf6_neighbor_event_string(event)); | |
177 | } | |
178 | ||
179 | /* Optionally notify about adjacency changes */ | |
180 | if (CHECK_FLAG(on->ospf6_if->area->ospf6->config_flags, | |
181 | OSPF6_LOG_ADJACENCY_CHANGES) | |
182 | && (CHECK_FLAG(on->ospf6_if->area->ospf6->config_flags, | |
183 | OSPF6_LOG_ADJACENCY_DETAIL) | |
184 | || (next_state == OSPF6_NEIGHBOR_FULL) | |
185 | || (next_state < prev_state))) | |
186 | zlog_notice("AdjChg: Nbr %s: %s -> %s (%s)", on->name, | |
187 | ospf6_neighbor_state_str[prev_state], | |
188 | ospf6_neighbor_state_str[next_state], | |
189 | ospf6_neighbor_event_string(event)); | |
190 | ||
191 | if (prev_state == OSPF6_NEIGHBOR_FULL | |
192 | || next_state == OSPF6_NEIGHBOR_FULL) { | |
193 | OSPF6_ROUTER_LSA_SCHEDULE(on->ospf6_if->area); | |
194 | if (on->ospf6_if->state == OSPF6_INTERFACE_DR) { | |
195 | OSPF6_NETWORK_LSA_SCHEDULE(on->ospf6_if); | |
196 | OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT(on->ospf6_if); | |
197 | } | |
690df177 CS |
198 | if (next_state == OSPF6_NEIGHBOR_FULL) |
199 | on->ospf6_if->area->intra_prefix_originate = 1; | |
200 | ||
d62a17ae | 201 | OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(on->ospf6_if->area); |
76249532 | 202 | |
6b1886f5 CS |
203 | if ((prev_state == OSPF6_NEIGHBOR_LOADING || |
204 | prev_state == OSPF6_NEIGHBOR_EXCHANGE) && | |
205 | next_state == OSPF6_NEIGHBOR_FULL) { | |
76249532 | 206 | OSPF6_AS_EXTERN_LSA_SCHEDULE(on->ospf6_if); |
d6927cf3 | 207 | on->ospf6_if->area->full_nbrs++; |
76249532 | 208 | } |
d6927cf3 CS |
209 | |
210 | if (prev_state == OSPF6_NEIGHBOR_FULL) | |
211 | on->ospf6_if->area->full_nbrs--; | |
d62a17ae | 212 | } |
213 | ||
214 | if ((prev_state == OSPF6_NEIGHBOR_EXCHANGE | |
215 | || prev_state == OSPF6_NEIGHBOR_LOADING) | |
216 | && (next_state != OSPF6_NEIGHBOR_EXCHANGE | |
217 | && next_state != OSPF6_NEIGHBOR_LOADING)) | |
218 | ospf6_maxage_remove(on->ospf6_if->area->ospf6); | |
219 | ||
220 | hook_call(ospf6_neighbor_change, on, next_state, prev_state); | |
221 | ospf6_bfd_trigger_event(on, prev_state, next_state); | |
718e3744 | 222 | } |
223 | ||
508e53e2 | 224 | /* RFC2328 section 10.4 */ |
d62a17ae | 225 | static int need_adjacency(struct ospf6_neighbor *on) |
718e3744 | 226 | { |
d62a17ae | 227 | if (on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT |
228 | || on->ospf6_if->state == OSPF6_INTERFACE_DR | |
229 | || on->ospf6_if->state == OSPF6_INTERFACE_BDR) | |
230 | return 1; | |
718e3744 | 231 | |
d62a17ae | 232 | if (on->ospf6_if->drouter == on->router_id |
233 | || on->ospf6_if->bdrouter == on->router_id) | |
234 | return 1; | |
508e53e2 | 235 | |
d62a17ae | 236 | return 0; |
718e3744 | 237 | } |
238 | ||
d62a17ae | 239 | int hello_received(struct thread *thread) |
718e3744 | 240 | { |
d62a17ae | 241 | struct ospf6_neighbor *on; |
718e3744 | 242 | |
d62a17ae | 243 | on = (struct ospf6_neighbor *)THREAD_ARG(thread); |
244 | assert(on); | |
718e3744 | 245 | |
d62a17ae | 246 | if (IS_OSPF6_DEBUG_NEIGHBOR(EVENT)) |
247 | zlog_debug("Neighbor Event %s: *HelloReceived*", on->name); | |
508e53e2 | 248 | |
d62a17ae | 249 | /* reset Inactivity Timer */ |
250 | THREAD_OFF(on->inactivity_timer); | |
251 | on->inactivity_timer = NULL; | |
252 | thread_add_timer(master, inactivity_timer, on, | |
253 | on->ospf6_if->dead_interval, &on->inactivity_timer); | |
508e53e2 | 254 | |
d62a17ae | 255 | if (on->state <= OSPF6_NEIGHBOR_DOWN) |
256 | ospf6_neighbor_state_change(OSPF6_NEIGHBOR_INIT, on, | |
257 | OSPF6_NEIGHBOR_EVENT_HELLO_RCVD); | |
508e53e2 | 258 | |
d62a17ae | 259 | return 0; |
718e3744 | 260 | } |
261 | ||
d62a17ae | 262 | int twoway_received(struct thread *thread) |
718e3744 | 263 | { |
d62a17ae | 264 | struct ospf6_neighbor *on; |
508e53e2 | 265 | |
d62a17ae | 266 | on = (struct ospf6_neighbor *)THREAD_ARG(thread); |
267 | assert(on); | |
508e53e2 | 268 | |
d62a17ae | 269 | if (on->state > OSPF6_NEIGHBOR_INIT) |
270 | return 0; | |
508e53e2 | 271 | |
d62a17ae | 272 | if (IS_OSPF6_DEBUG_NEIGHBOR(EVENT)) |
273 | zlog_debug("Neighbor Event %s: *2Way-Received*", on->name); | |
508e53e2 | 274 | |
d62a17ae | 275 | thread_add_event(master, neighbor_change, on->ospf6_if, 0, NULL); |
508e53e2 | 276 | |
d62a17ae | 277 | if (!need_adjacency(on)) { |
278 | ospf6_neighbor_state_change(OSPF6_NEIGHBOR_TWOWAY, on, | |
279 | OSPF6_NEIGHBOR_EVENT_TWOWAY_RCVD); | |
280 | return 0; | |
281 | } | |
718e3744 | 282 | |
d62a17ae | 283 | ospf6_neighbor_state_change(OSPF6_NEIGHBOR_EXSTART, on, |
284 | OSPF6_NEIGHBOR_EVENT_TWOWAY_RCVD); | |
285 | SET_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MSBIT); | |
286 | SET_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MBIT); | |
287 | SET_FLAG(on->dbdesc_bits, OSPF6_DBDESC_IBIT); | |
508e53e2 | 288 | |
d62a17ae | 289 | THREAD_OFF(on->thread_send_dbdesc); |
290 | on->thread_send_dbdesc = NULL; | |
291 | thread_add_event(master, ospf6_dbdesc_send, on, 0, | |
292 | &on->thread_send_dbdesc); | |
508e53e2 | 293 | |
d62a17ae | 294 | return 0; |
718e3744 | 295 | } |
296 | ||
d62a17ae | 297 | int negotiation_done(struct thread *thread) |
718e3744 | 298 | { |
d62a17ae | 299 | struct ospf6_neighbor *on; |
0f9f74ba DS |
300 | struct ospf6_lsa *lsa, *lsa_next; |
301 | const struct route_node *iterend; | |
d62a17ae | 302 | |
303 | on = (struct ospf6_neighbor *)THREAD_ARG(thread); | |
304 | assert(on); | |
305 | ||
306 | if (on->state != OSPF6_NEIGHBOR_EXSTART) | |
307 | return 0; | |
308 | ||
309 | if (IS_OSPF6_DEBUG_NEIGHBOR(EVENT)) | |
310 | zlog_debug("Neighbor Event %s: *NegotiationDone*", on->name); | |
311 | ||
312 | /* clear ls-list */ | |
313 | ospf6_lsdb_remove_all(on->summary_list); | |
314 | ospf6_lsdb_remove_all(on->request_list); | |
0f9f74ba DS |
315 | |
316 | for (iterend = ospf6_lsdb_head(on->retrans_list, 0, 0, 0, &lsa); lsa; | |
317 | lsa = lsa_next) { | |
318 | lsa_next = ospf6_lsdb_next(iterend, lsa); | |
d62a17ae | 319 | ospf6_decrement_retrans_count(lsa); |
320 | ospf6_lsdb_remove(lsa, on->retrans_list); | |
321 | } | |
322 | ||
323 | /* Interface scoped LSAs */ | |
324 | for (ALL_LSDB(on->ospf6_if->lsdb, lsa)) { | |
325 | if (OSPF6_LSA_IS_MAXAGE(lsa)) { | |
326 | ospf6_increment_retrans_count(lsa); | |
327 | ospf6_lsdb_add(ospf6_lsa_copy(lsa), on->retrans_list); | |
328 | } else | |
329 | ospf6_lsdb_add(ospf6_lsa_copy(lsa), on->summary_list); | |
330 | } | |
331 | ||
332 | /* Area scoped LSAs */ | |
333 | for (ALL_LSDB(on->ospf6_if->area->lsdb, lsa)) { | |
334 | if (OSPF6_LSA_IS_MAXAGE(lsa)) { | |
335 | ospf6_increment_retrans_count(lsa); | |
336 | ospf6_lsdb_add(ospf6_lsa_copy(lsa), on->retrans_list); | |
337 | } else | |
338 | ospf6_lsdb_add(ospf6_lsa_copy(lsa), on->summary_list); | |
339 | } | |
340 | ||
341 | /* AS scoped LSAs */ | |
342 | for (ALL_LSDB(on->ospf6_if->area->ospf6->lsdb, lsa)) { | |
343 | if (OSPF6_LSA_IS_MAXAGE(lsa)) { | |
344 | ospf6_increment_retrans_count(lsa); | |
345 | ospf6_lsdb_add(ospf6_lsa_copy(lsa), on->retrans_list); | |
346 | } else | |
347 | ospf6_lsdb_add(ospf6_lsa_copy(lsa), on->summary_list); | |
348 | } | |
349 | ||
350 | UNSET_FLAG(on->dbdesc_bits, OSPF6_DBDESC_IBIT); | |
351 | ospf6_neighbor_state_change(OSPF6_NEIGHBOR_EXCHANGE, on, | |
352 | OSPF6_NEIGHBOR_EVENT_NEGOTIATION_DONE); | |
353 | ||
354 | return 0; | |
718e3744 | 355 | } |
356 | ||
d62a17ae | 357 | int exchange_done(struct thread *thread) |
718e3744 | 358 | { |
d62a17ae | 359 | struct ospf6_neighbor *on; |
718e3744 | 360 | |
d62a17ae | 361 | on = (struct ospf6_neighbor *)THREAD_ARG(thread); |
362 | assert(on); | |
508e53e2 | 363 | |
d62a17ae | 364 | if (on->state != OSPF6_NEIGHBOR_EXCHANGE) |
365 | return 0; | |
508e53e2 | 366 | |
d62a17ae | 367 | if (IS_OSPF6_DEBUG_NEIGHBOR(EVENT)) |
368 | zlog_debug("Neighbor Event %s: *ExchangeDone*", on->name); | |
508e53e2 | 369 | |
d62a17ae | 370 | THREAD_OFF(on->thread_send_dbdesc); |
371 | ospf6_lsdb_remove_all(on->dbdesc_list); | |
508e53e2 | 372 | |
d62a17ae | 373 | /* XXX |
374 | thread_add_timer (master, ospf6_neighbor_last_dbdesc_release, on, | |
375 | on->ospf6_if->dead_interval); | |
376 | */ | |
508e53e2 | 377 | |
d62a17ae | 378 | if (on->request_list->count == 0) |
379 | ospf6_neighbor_state_change(OSPF6_NEIGHBOR_FULL, on, | |
380 | OSPF6_NEIGHBOR_EVENT_EXCHANGE_DONE); | |
381 | else { | |
382 | ospf6_neighbor_state_change(OSPF6_NEIGHBOR_LOADING, on, | |
383 | OSPF6_NEIGHBOR_EVENT_EXCHANGE_DONE); | |
eb82e9ee | 384 | |
d62a17ae | 385 | thread_add_event(master, ospf6_lsreq_send, on, 0, |
386 | &on->thread_send_lsreq); | |
387 | } | |
508e53e2 | 388 | |
d62a17ae | 389 | return 0; |
508e53e2 | 390 | } |
391 | ||
eb82e9ee | 392 | /* Check loading state. */ |
d62a17ae | 393 | void ospf6_check_nbr_loading(struct ospf6_neighbor *on) |
eb82e9ee DD |
394 | { |
395 | ||
d62a17ae | 396 | /* RFC2328 Section 10.9: When the neighbor responds to these requests |
397 | with the proper Link State Update packet(s), the Link state request | |
398 | list is truncated and a new Link State Request packet is sent. | |
399 | */ | |
400 | if ((on->state == OSPF6_NEIGHBOR_LOADING) | |
401 | || (on->state == OSPF6_NEIGHBOR_EXCHANGE)) { | |
402 | if (on->request_list->count == 0) | |
403 | thread_add_event(master, loading_done, on, 0, NULL); | |
404 | else if (on->last_ls_req == NULL) { | |
405 | if (on->thread_send_lsreq != NULL) | |
406 | THREAD_OFF(on->thread_send_lsreq); | |
407 | on->thread_send_lsreq = NULL; | |
408 | thread_add_event(master, ospf6_lsreq_send, on, 0, | |
409 | &on->thread_send_lsreq); | |
410 | } | |
eb82e9ee | 411 | } |
eb82e9ee DD |
412 | } |
413 | ||
d62a17ae | 414 | int loading_done(struct thread *thread) |
508e53e2 | 415 | { |
d62a17ae | 416 | struct ospf6_neighbor *on; |
508e53e2 | 417 | |
d62a17ae | 418 | on = (struct ospf6_neighbor *)THREAD_ARG(thread); |
419 | assert(on); | |
508e53e2 | 420 | |
d62a17ae | 421 | if (on->state != OSPF6_NEIGHBOR_LOADING) |
422 | return 0; | |
508e53e2 | 423 | |
d62a17ae | 424 | if (IS_OSPF6_DEBUG_NEIGHBOR(EVENT)) |
425 | zlog_debug("Neighbor Event %s: *LoadingDone*", on->name); | |
508e53e2 | 426 | |
d62a17ae | 427 | assert(on->request_list->count == 0); |
508e53e2 | 428 | |
d62a17ae | 429 | ospf6_neighbor_state_change(OSPF6_NEIGHBOR_FULL, on, |
430 | OSPF6_NEIGHBOR_EVENT_LOADING_DONE); | |
508e53e2 | 431 | |
d62a17ae | 432 | return 0; |
508e53e2 | 433 | } |
434 | ||
d62a17ae | 435 | int adj_ok(struct thread *thread) |
508e53e2 | 436 | { |
d62a17ae | 437 | struct ospf6_neighbor *on; |
438 | struct ospf6_lsa *lsa; | |
439 | ||
440 | on = (struct ospf6_neighbor *)THREAD_ARG(thread); | |
441 | assert(on); | |
442 | ||
443 | if (IS_OSPF6_DEBUG_NEIGHBOR(EVENT)) | |
444 | zlog_debug("Neighbor Event %s: *AdjOK?*", on->name); | |
445 | ||
446 | if (on->state == OSPF6_NEIGHBOR_TWOWAY && need_adjacency(on)) { | |
447 | ospf6_neighbor_state_change(OSPF6_NEIGHBOR_EXSTART, on, | |
448 | OSPF6_NEIGHBOR_EVENT_ADJ_OK); | |
449 | SET_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MSBIT); | |
450 | SET_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MBIT); | |
451 | SET_FLAG(on->dbdesc_bits, OSPF6_DBDESC_IBIT); | |
452 | ||
453 | THREAD_OFF(on->thread_send_dbdesc); | |
454 | on->thread_send_dbdesc = NULL; | |
455 | thread_add_event(master, ospf6_dbdesc_send, on, 0, | |
456 | &on->thread_send_dbdesc); | |
457 | ||
458 | } else if (on->state >= OSPF6_NEIGHBOR_EXSTART && !need_adjacency(on)) { | |
459 | ospf6_neighbor_state_change(OSPF6_NEIGHBOR_TWOWAY, on, | |
460 | OSPF6_NEIGHBOR_EVENT_ADJ_OK); | |
461 | ospf6_lsdb_remove_all(on->summary_list); | |
462 | ospf6_lsdb_remove_all(on->request_list); | |
463 | for (ALL_LSDB(on->retrans_list, lsa)) { | |
464 | ospf6_decrement_retrans_count(lsa); | |
465 | ospf6_lsdb_remove(lsa, on->retrans_list); | |
466 | } | |
467 | } | |
468 | ||
469 | return 0; | |
508e53e2 | 470 | } |
718e3744 | 471 | |
d62a17ae | 472 | int seqnumber_mismatch(struct thread *thread) |
508e53e2 | 473 | { |
d62a17ae | 474 | struct ospf6_neighbor *on; |
475 | struct ospf6_lsa *lsa; | |
718e3744 | 476 | |
d62a17ae | 477 | on = (struct ospf6_neighbor *)THREAD_ARG(thread); |
478 | assert(on); | |
718e3744 | 479 | |
d62a17ae | 480 | if (on->state < OSPF6_NEIGHBOR_EXCHANGE) |
481 | return 0; | |
718e3744 | 482 | |
d62a17ae | 483 | if (IS_OSPF6_DEBUG_NEIGHBOR(EVENT)) |
484 | zlog_debug("Neighbor Event %s: *SeqNumberMismatch*", on->name); | |
718e3744 | 485 | |
d62a17ae | 486 | ospf6_neighbor_state_change(OSPF6_NEIGHBOR_EXSTART, on, |
487 | OSPF6_NEIGHBOR_EVENT_SEQNUMBER_MISMATCH); | |
488 | SET_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MSBIT); | |
489 | SET_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MBIT); | |
490 | SET_FLAG(on->dbdesc_bits, OSPF6_DBDESC_IBIT); | |
718e3744 | 491 | |
d62a17ae | 492 | ospf6_lsdb_remove_all(on->summary_list); |
493 | ospf6_lsdb_remove_all(on->request_list); | |
494 | for (ALL_LSDB(on->retrans_list, lsa)) { | |
495 | ospf6_decrement_retrans_count(lsa); | |
496 | ospf6_lsdb_remove(lsa, on->retrans_list); | |
497 | } | |
508e53e2 | 498 | |
d62a17ae | 499 | THREAD_OFF(on->thread_send_dbdesc); |
500 | on->dbdesc_seqnum++; /* Incr seqnum as per RFC2328, sec 10.3 */ | |
931b1b8c | 501 | |
d62a17ae | 502 | on->thread_send_dbdesc = NULL; |
503 | thread_add_event(master, ospf6_dbdesc_send, on, 0, | |
504 | &on->thread_send_dbdesc); | |
508e53e2 | 505 | |
d62a17ae | 506 | return 0; |
718e3744 | 507 | } |
508 | ||
d62a17ae | 509 | int bad_lsreq(struct thread *thread) |
718e3744 | 510 | { |
d62a17ae | 511 | struct ospf6_neighbor *on; |
0f9f74ba DS |
512 | struct ospf6_lsa *lsa, *lsa_next; |
513 | const struct route_node *iterend; | |
508e53e2 | 514 | |
d62a17ae | 515 | on = (struct ospf6_neighbor *)THREAD_ARG(thread); |
516 | assert(on); | |
508e53e2 | 517 | |
d62a17ae | 518 | if (on->state < OSPF6_NEIGHBOR_EXCHANGE) |
519 | return 0; | |
718e3744 | 520 | |
d62a17ae | 521 | if (IS_OSPF6_DEBUG_NEIGHBOR(EVENT)) |
522 | zlog_debug("Neighbor Event %s: *BadLSReq*", on->name); | |
718e3744 | 523 | |
d62a17ae | 524 | ospf6_neighbor_state_change(OSPF6_NEIGHBOR_EXSTART, on, |
525 | OSPF6_NEIGHBOR_EVENT_BAD_LSREQ); | |
526 | SET_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MSBIT); | |
527 | SET_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MBIT); | |
528 | SET_FLAG(on->dbdesc_bits, OSPF6_DBDESC_IBIT); | |
718e3744 | 529 | |
d62a17ae | 530 | ospf6_lsdb_remove_all(on->summary_list); |
531 | ospf6_lsdb_remove_all(on->request_list); | |
0f9f74ba DS |
532 | |
533 | for (iterend = ospf6_lsdb_head(on->retrans_list, 0, 0, 0, &lsa); lsa; | |
534 | lsa = lsa_next) { | |
535 | lsa_next = ospf6_lsdb_next(iterend, lsa); | |
d62a17ae | 536 | ospf6_decrement_retrans_count(lsa); |
537 | ospf6_lsdb_remove(lsa, on->retrans_list); | |
538 | } | |
718e3744 | 539 | |
d62a17ae | 540 | THREAD_OFF(on->thread_send_dbdesc); |
541 | on->dbdesc_seqnum++; /* Incr seqnum as per RFC2328, sec 10.3 */ | |
931b1b8c | 542 | |
d62a17ae | 543 | on->thread_send_dbdesc = NULL; |
544 | thread_add_event(master, ospf6_dbdesc_send, on, 0, | |
545 | &on->thread_send_dbdesc); | |
508e53e2 | 546 | |
d62a17ae | 547 | return 0; |
718e3744 | 548 | } |
549 | ||
d62a17ae | 550 | int oneway_received(struct thread *thread) |
718e3744 | 551 | { |
d62a17ae | 552 | struct ospf6_neighbor *on; |
0f9f74ba DS |
553 | struct ospf6_lsa *lsa, *lsa_next; |
554 | const struct route_node *iterend; | |
718e3744 | 555 | |
d62a17ae | 556 | on = (struct ospf6_neighbor *)THREAD_ARG(thread); |
557 | assert(on); | |
508e53e2 | 558 | |
d62a17ae | 559 | if (on->state < OSPF6_NEIGHBOR_TWOWAY) |
560 | return 0; | |
508e53e2 | 561 | |
d62a17ae | 562 | if (IS_OSPF6_DEBUG_NEIGHBOR(EVENT)) |
563 | zlog_debug("Neighbor Event %s: *1Way-Received*", on->name); | |
508e53e2 | 564 | |
d62a17ae | 565 | ospf6_neighbor_state_change(OSPF6_NEIGHBOR_INIT, on, |
566 | OSPF6_NEIGHBOR_EVENT_ONEWAY_RCVD); | |
567 | thread_add_event(master, neighbor_change, on->ospf6_if, 0, NULL); | |
508e53e2 | 568 | |
d62a17ae | 569 | ospf6_lsdb_remove_all(on->summary_list); |
570 | ospf6_lsdb_remove_all(on->request_list); | |
0f9f74ba DS |
571 | for (iterend = ospf6_lsdb_head(on->retrans_list, 0, 0, 0, &lsa); lsa; |
572 | lsa = lsa_next) { | |
573 | lsa_next = ospf6_lsdb_next(iterend, lsa); | |
d62a17ae | 574 | ospf6_decrement_retrans_count(lsa); |
575 | ospf6_lsdb_remove(lsa, on->retrans_list); | |
576 | } | |
508e53e2 | 577 | |
d62a17ae | 578 | THREAD_OFF(on->thread_send_dbdesc); |
579 | THREAD_OFF(on->thread_send_lsreq); | |
580 | THREAD_OFF(on->thread_send_lsupdate); | |
581 | THREAD_OFF(on->thread_send_lsack); | |
508e53e2 | 582 | |
d62a17ae | 583 | return 0; |
508e53e2 | 584 | } |
585 | ||
d62a17ae | 586 | int inactivity_timer(struct thread *thread) |
508e53e2 | 587 | { |
d62a17ae | 588 | struct ospf6_neighbor *on; |
508e53e2 | 589 | |
d62a17ae | 590 | on = (struct ospf6_neighbor *)THREAD_ARG(thread); |
591 | assert(on); | |
508e53e2 | 592 | |
d62a17ae | 593 | if (IS_OSPF6_DEBUG_NEIGHBOR(EVENT)) |
594 | zlog_debug("Neighbor Event %s: *InactivityTimer*", on->name); | |
508e53e2 | 595 | |
d62a17ae | 596 | on->inactivity_timer = NULL; |
597 | on->drouter = on->prev_drouter = 0; | |
598 | on->bdrouter = on->prev_bdrouter = 0; | |
508e53e2 | 599 | |
d62a17ae | 600 | ospf6_neighbor_state_change(OSPF6_NEIGHBOR_DOWN, on, |
601 | OSPF6_NEIGHBOR_EVENT_INACTIVITY_TIMER); | |
602 | thread_add_event(master, neighbor_change, on->ospf6_if, 0, NULL); | |
508e53e2 | 603 | |
d62a17ae | 604 | listnode_delete(on->ospf6_if->neighbor_list, on); |
605 | ospf6_neighbor_delete(on); | |
508e53e2 | 606 | |
d62a17ae | 607 | return 0; |
718e3744 | 608 | } |
609 | ||
508e53e2 | 610 | |
718e3744 | 611 | /* vty functions */ |
612 | /* show neighbor structure */ | |
d62a17ae | 613 | static void ospf6_neighbor_show(struct vty *vty, struct ospf6_neighbor *on) |
718e3744 | 614 | { |
d62a17ae | 615 | char router_id[16]; |
68bfcc05 | 616 | char duration[64]; |
d62a17ae | 617 | struct timeval res; |
618 | char nstate[16]; | |
68bfcc05 | 619 | char deadtime[64]; |
d62a17ae | 620 | long h, m, s; |
621 | ||
622 | /* Router-ID (Name) */ | |
623 | inet_ntop(AF_INET, &on->router_id, router_id, sizeof(router_id)); | |
508e53e2 | 624 | #ifdef HAVE_GETNAMEINFO |
d62a17ae | 625 | { |
626 | } | |
508e53e2 | 627 | #endif /*HAVE_GETNAMEINFO*/ |
628 | ||
d62a17ae | 629 | /* Dead time */ |
630 | h = m = s = 0; | |
631 | if (on->inactivity_timer) { | |
632 | s = monotime_until(&on->inactivity_timer->u.sands, NULL) | |
633 | / 1000000LL; | |
634 | h = s / 3600; | |
635 | s -= h * 3600; | |
636 | m = s / 60; | |
637 | s -= m * 60; | |
638 | } | |
639 | snprintf(deadtime, sizeof(deadtime), "%02ld:%02ld:%02ld", h, m, s); | |
640 | ||
641 | /* Neighbor State */ | |
e5973353 | 642 | if (on->ospf6_if->type == OSPF_IFTYPE_POINTOPOINT) |
d62a17ae | 643 | snprintf(nstate, sizeof(nstate), "PointToPoint"); |
644 | else { | |
645 | if (on->router_id == on->drouter) | |
646 | snprintf(nstate, sizeof(nstate), "DR"); | |
647 | else if (on->router_id == on->bdrouter) | |
648 | snprintf(nstate, sizeof(nstate), "BDR"); | |
649 | else | |
650 | snprintf(nstate, sizeof(nstate), "DROther"); | |
651 | } | |
652 | ||
653 | /* Duration */ | |
654 | monotime_since(&on->last_changed, &res); | |
655 | timerstring(&res, duration, sizeof(duration)); | |
656 | ||
657 | /* | |
658 | vty_out (vty, "%-15s %3d %11s %6s/%-12s %11s %s[%s]\n", | |
659 | "Neighbor ID", "Pri", "DeadTime", "State", "", "Duration", | |
660 | "I/F", "State"); | |
661 | */ | |
662 | ||
663 | vty_out(vty, "%-15s %3d %11s %8s/%-12s %11s %s[%s]\n", router_id, | |
664 | on->priority, deadtime, ospf6_neighbor_state_str[on->state], | |
665 | nstate, duration, on->ospf6_if->interface->name, | |
666 | ospf6_interface_state_str[on->ospf6_if->state]); | |
508e53e2 | 667 | } |
668 | ||
d62a17ae | 669 | static void ospf6_neighbor_show_drchoice(struct vty *vty, |
670 | struct ospf6_neighbor *on) | |
508e53e2 | 671 | { |
d62a17ae | 672 | char router_id[16]; |
673 | char drouter[16], bdrouter[16]; | |
68bfcc05 | 674 | char duration[64]; |
d62a17ae | 675 | struct timeval now, res; |
676 | ||
677 | /* | |
678 | vty_out (vty, "%-15s %6s/%-11s %-15s %-15s %s[%s]\n", | |
679 | "RouterID", "State", "Duration", "DR", "BDR", "I/F", | |
680 | "State"); | |
681 | */ | |
682 | ||
683 | inet_ntop(AF_INET, &on->router_id, router_id, sizeof(router_id)); | |
684 | inet_ntop(AF_INET, &on->drouter, drouter, sizeof(drouter)); | |
685 | inet_ntop(AF_INET, &on->bdrouter, bdrouter, sizeof(bdrouter)); | |
686 | ||
687 | monotime(&now); | |
688 | timersub(&now, &on->last_changed, &res); | |
689 | timerstring(&res, duration, sizeof(duration)); | |
690 | ||
691 | vty_out(vty, "%-15s %8s/%-11s %-15s %-15s %s[%s]\n", router_id, | |
692 | ospf6_neighbor_state_str[on->state], duration, drouter, | |
693 | bdrouter, on->ospf6_if->interface->name, | |
694 | ospf6_interface_state_str[on->ospf6_if->state]); | |
718e3744 | 695 | } |
696 | ||
d62a17ae | 697 | static void ospf6_neighbor_show_detail(struct vty *vty, |
698 | struct ospf6_neighbor *on) | |
718e3744 | 699 | { |
d62a17ae | 700 | char drouter[16], bdrouter[16]; |
701 | char linklocal_addr[64], duration[32]; | |
702 | struct timeval now, res; | |
703 | struct ospf6_lsa *lsa; | |
704 | ||
705 | inet_ntop(AF_INET6, &on->linklocal_addr, linklocal_addr, | |
706 | sizeof(linklocal_addr)); | |
707 | inet_ntop(AF_INET, &on->drouter, drouter, sizeof(drouter)); | |
708 | inet_ntop(AF_INET, &on->bdrouter, bdrouter, sizeof(bdrouter)); | |
709 | ||
710 | monotime(&now); | |
711 | timersub(&now, &on->last_changed, &res); | |
712 | timerstring(&res, duration, sizeof(duration)); | |
713 | ||
714 | vty_out(vty, " Neighbor %s\n", on->name); | |
715 | vty_out(vty, " Area %s via interface %s (ifindex %d)\n", | |
716 | on->ospf6_if->area->name, on->ospf6_if->interface->name, | |
717 | on->ospf6_if->interface->ifindex); | |
718 | vty_out(vty, " His IfIndex: %d Link-local address: %s\n", | |
719 | on->ifindex, linklocal_addr); | |
720 | vty_out(vty, " State %s for a duration of %s\n", | |
721 | ospf6_neighbor_state_str[on->state], duration); | |
722 | vty_out(vty, " His choice of DR/BDR %s/%s, Priority %d\n", drouter, | |
723 | bdrouter, on->priority); | |
724 | vty_out(vty, " DbDesc status: %s%s%s SeqNum: %#lx\n", | |
725 | (CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_IBIT) ? "Initial " | |
726 | : ""), | |
727 | (CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MBIT) ? "More " : ""), | |
728 | (CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MSBIT) ? "Master" | |
729 | : "Slave"), | |
d7c0a89a | 730 | (unsigned long)ntohl(on->dbdesc_seqnum)); |
d62a17ae | 731 | |
732 | vty_out(vty, " Summary-List: %d LSAs\n", on->summary_list->count); | |
733 | for (ALL_LSDB(on->summary_list, lsa)) | |
734 | vty_out(vty, " %s\n", lsa->name); | |
735 | ||
736 | vty_out(vty, " Request-List: %d LSAs\n", on->request_list->count); | |
737 | for (ALL_LSDB(on->request_list, lsa)) | |
738 | vty_out(vty, " %s\n", lsa->name); | |
739 | ||
740 | vty_out(vty, " Retrans-List: %d LSAs\n", on->retrans_list->count); | |
741 | for (ALL_LSDB(on->retrans_list, lsa)) | |
742 | vty_out(vty, " %s\n", lsa->name); | |
743 | ||
744 | timerclear(&res); | |
745 | if (on->thread_send_dbdesc) | |
746 | timersub(&on->thread_send_dbdesc->u.sands, &now, &res); | |
747 | timerstring(&res, duration, sizeof(duration)); | |
748 | vty_out(vty, " %d Pending LSAs for DbDesc in Time %s [thread %s]\n", | |
749 | on->dbdesc_list->count, duration, | |
750 | (on->thread_send_dbdesc ? "on" : "off")); | |
751 | for (ALL_LSDB(on->dbdesc_list, lsa)) | |
752 | vty_out(vty, " %s\n", lsa->name); | |
753 | ||
754 | timerclear(&res); | |
755 | if (on->thread_send_lsreq) | |
756 | timersub(&on->thread_send_lsreq->u.sands, &now, &res); | |
757 | timerstring(&res, duration, sizeof(duration)); | |
758 | vty_out(vty, " %d Pending LSAs for LSReq in Time %s [thread %s]\n", | |
759 | on->request_list->count, duration, | |
760 | (on->thread_send_lsreq ? "on" : "off")); | |
761 | for (ALL_LSDB(on->request_list, lsa)) | |
762 | vty_out(vty, " %s\n", lsa->name); | |
763 | ||
764 | timerclear(&res); | |
765 | if (on->thread_send_lsupdate) | |
766 | timersub(&on->thread_send_lsupdate->u.sands, &now, &res); | |
767 | timerstring(&res, duration, sizeof(duration)); | |
768 | vty_out(vty, | |
769 | " %d Pending LSAs for LSUpdate in Time %s [thread %s]\n", | |
770 | on->lsupdate_list->count, duration, | |
771 | (on->thread_send_lsupdate ? "on" : "off")); | |
772 | for (ALL_LSDB(on->lsupdate_list, lsa)) | |
773 | vty_out(vty, " %s\n", lsa->name); | |
774 | ||
775 | timerclear(&res); | |
776 | if (on->thread_send_lsack) | |
777 | timersub(&on->thread_send_lsack->u.sands, &now, &res); | |
778 | timerstring(&res, duration, sizeof(duration)); | |
779 | vty_out(vty, " %d Pending LSAs for LSAck in Time %s [thread %s]\n", | |
780 | on->lsack_list->count, duration, | |
781 | (on->thread_send_lsack ? "on" : "off")); | |
782 | for (ALL_LSDB(on->lsack_list, lsa)) | |
783 | vty_out(vty, " %s\n", lsa->name); | |
784 | ||
785 | ospf6_bfd_show_info(vty, on->bfd_info, 0); | |
718e3744 | 786 | } |
787 | ||
508e53e2 | 788 | DEFUN (show_ipv6_ospf6_neighbor, |
789 | show_ipv6_ospf6_neighbor_cmd, | |
6de69f83 | 790 | "show ipv6 ospf6 neighbor [<detail|drchoice>]", |
718e3744 | 791 | SHOW_STR |
792 | IP6_STR | |
793 | OSPF6_STR | |
794 | "Neighbor list\n" | |
1d68dbfe DW |
795 | "Display details\n" |
796 | "Display DR choices\n") | |
718e3744 | 797 | { |
d62a17ae | 798 | int idx_type = 4; |
799 | struct ospf6_neighbor *on; | |
800 | struct ospf6_interface *oi; | |
801 | struct ospf6_area *oa; | |
802 | struct listnode *i, *j, *k; | |
803 | void (*showfunc)(struct vty *, struct ospf6_neighbor *); | |
804 | ||
805 | OSPF6_CMD_CHECK_RUNNING(); | |
806 | showfunc = ospf6_neighbor_show; | |
807 | ||
808 | if (argc == 5) { | |
809 | if (!strncmp(argv[idx_type]->arg, "de", 2)) | |
810 | showfunc = ospf6_neighbor_show_detail; | |
811 | else if (!strncmp(argv[idx_type]->arg, "dr", 2)) | |
812 | showfunc = ospf6_neighbor_show_drchoice; | |
813 | } | |
814 | ||
815 | if (showfunc == ospf6_neighbor_show) | |
816 | vty_out(vty, "%-15s %3s %11s %8s/%-12s %11s %s[%s]\n", | |
817 | "Neighbor ID", "Pri", "DeadTime", "State", "IfState", | |
818 | "Duration", "I/F", "State"); | |
819 | else if (showfunc == ospf6_neighbor_show_drchoice) | |
820 | vty_out(vty, "%-15s %8s/%-11s %-15s %-15s %s[%s]\n", "RouterID", | |
821 | "State", "Duration", "DR", "BDR", "I/F", "State"); | |
822 | ||
823 | for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, i, oa)) | |
824 | for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi)) | |
825 | for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, k, on)) | |
826 | (*showfunc)(vty, on); | |
827 | ||
828 | return CMD_SUCCESS; | |
718e3744 | 829 | } |
830 | ||
718e3744 | 831 | |
508e53e2 | 832 | DEFUN (show_ipv6_ospf6_neighbor_one, |
833 | show_ipv6_ospf6_neighbor_one_cmd, | |
834 | "show ipv6 ospf6 neighbor A.B.C.D", | |
718e3744 | 835 | SHOW_STR |
836 | IP6_STR | |
837 | OSPF6_STR | |
508e53e2 | 838 | "Neighbor list\n" |
839 | "Specify Router-ID as IPv4 address notation\n" | |
840 | ) | |
718e3744 | 841 | { |
d62a17ae | 842 | int idx_ipv4 = 4; |
843 | struct ospf6_neighbor *on; | |
844 | struct ospf6_interface *oi; | |
845 | struct ospf6_area *oa; | |
846 | struct listnode *i, *j, *k; | |
847 | void (*showfunc)(struct vty *, struct ospf6_neighbor *); | |
d7c0a89a | 848 | uint32_t router_id; |
d62a17ae | 849 | |
850 | OSPF6_CMD_CHECK_RUNNING(); | |
851 | showfunc = ospf6_neighbor_show_detail; | |
852 | ||
853 | if ((inet_pton(AF_INET, argv[idx_ipv4]->arg, &router_id)) != 1) { | |
854 | vty_out(vty, "Router-ID is not parsable: %s\n", | |
855 | argv[idx_ipv4]->arg); | |
856 | return CMD_SUCCESS; | |
857 | } | |
858 | ||
859 | for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, i, oa)) | |
860 | for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi)) | |
861 | for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, k, on)) | |
862 | (*showfunc)(vty, on); | |
863 | ||
864 | return CMD_SUCCESS; | |
718e3744 | 865 | } |
866 | ||
d62a17ae | 867 | void ospf6_neighbor_init(void) |
718e3744 | 868 | { |
d62a17ae | 869 | install_element(VIEW_NODE, &show_ipv6_ospf6_neighbor_cmd); |
870 | install_element(VIEW_NODE, &show_ipv6_ospf6_neighbor_one_cmd); | |
508e53e2 | 871 | } |
872 | ||
873 | DEFUN (debug_ospf6_neighbor, | |
874 | debug_ospf6_neighbor_cmd, | |
6de69f83 | 875 | "debug ospf6 neighbor [<state|event>]", |
508e53e2 | 876 | DEBUG_STR |
877 | OSPF6_STR | |
878 | "Debug OSPFv3 Neighbor\n" | |
1d68dbfe DW |
879 | "Debug OSPFv3 Neighbor State Change\n" |
880 | "Debug OSPFv3 Neighbor Event\n") | |
508e53e2 | 881 | { |
d62a17ae | 882 | int idx_type = 3; |
883 | unsigned char level = 0; | |
884 | ||
885 | if (argc == 4) { | |
886 | if (!strncmp(argv[idx_type]->arg, "s", 1)) | |
887 | level = OSPF6_DEBUG_NEIGHBOR_STATE; | |
888 | else if (!strncmp(argv[idx_type]->arg, "e", 1)) | |
889 | level = OSPF6_DEBUG_NEIGHBOR_EVENT; | |
890 | } else | |
891 | level = OSPF6_DEBUG_NEIGHBOR_STATE | OSPF6_DEBUG_NEIGHBOR_EVENT; | |
892 | ||
893 | OSPF6_DEBUG_NEIGHBOR_ON(level); | |
894 | return CMD_SUCCESS; | |
718e3744 | 895 | } |
896 | ||
508e53e2 | 897 | |
898 | DEFUN (no_debug_ospf6_neighbor, | |
899 | no_debug_ospf6_neighbor_cmd, | |
6de69f83 | 900 | "no debug ospf6 neighbor [<state|event>]", |
508e53e2 | 901 | NO_STR |
902 | DEBUG_STR | |
903 | OSPF6_STR | |
904 | "Debug OSPFv3 Neighbor\n" | |
1d68dbfe DW |
905 | "Debug OSPFv3 Neighbor State Change\n" |
906 | "Debug OSPFv3 Neighbor Event\n") | |
508e53e2 | 907 | { |
d62a17ae | 908 | int idx_type = 4; |
909 | unsigned char level = 0; | |
910 | ||
911 | if (argc == 5) { | |
912 | if (!strncmp(argv[idx_type]->arg, "s", 1)) | |
913 | level = OSPF6_DEBUG_NEIGHBOR_STATE; | |
914 | if (!strncmp(argv[idx_type]->arg, "e", 1)) | |
915 | level = OSPF6_DEBUG_NEIGHBOR_EVENT; | |
916 | } else | |
917 | level = OSPF6_DEBUG_NEIGHBOR_STATE | OSPF6_DEBUG_NEIGHBOR_EVENT; | |
918 | ||
919 | OSPF6_DEBUG_NEIGHBOR_OFF(level); | |
920 | return CMD_SUCCESS; | |
508e53e2 | 921 | } |
922 | ||
508e53e2 | 923 | |
4dfd8aff DW |
924 | DEFUN (no_debug_ospf6, |
925 | no_debug_ospf6_cmd, | |
926 | "no debug ospf6", | |
927 | NO_STR | |
928 | DEBUG_STR | |
929 | OSPF6_STR) | |
930 | { | |
d7c0a89a | 931 | unsigned int i; |
d62a17ae | 932 | struct ospf6_lsa_handler *handler = NULL; |
933 | ||
934 | OSPF6_DEBUG_ABR_OFF(); | |
935 | OSPF6_DEBUG_ASBR_OFF(); | |
936 | OSPF6_DEBUG_BROUTER_OFF(); | |
937 | OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_OFF(); | |
938 | OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_OFF(); | |
939 | OSPF6_DEBUG_FLOODING_OFF(); | |
940 | OSPF6_DEBUG_INTERFACE_OFF(); | |
941 | ||
942 | for (i = 0; i < vector_active(ospf6_lsa_handler_vector); i++) { | |
943 | handler = vector_slot(ospf6_lsa_handler_vector, i); | |
944 | ||
945 | if (handler != NULL) { | |
01db90cd | 946 | UNSET_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG); |
d62a17ae | 947 | } |
948 | } | |
949 | ||
950 | for (i = 0; i < 6; i++) | |
951 | OSPF6_DEBUG_MESSAGE_OFF(i, | |
952 | OSPF6_DEBUG_NEIGHBOR_STATE | |
953 | | OSPF6_DEBUG_NEIGHBOR_EVENT); | |
954 | ||
955 | OSPF6_DEBUG_NEIGHBOR_OFF(OSPF6_DEBUG_NEIGHBOR_STATE | |
956 | | OSPF6_DEBUG_NEIGHBOR_EVENT); | |
957 | OSPF6_DEBUG_ROUTE_OFF(OSPF6_DEBUG_ROUTE_TABLE); | |
958 | OSPF6_DEBUG_ROUTE_OFF(OSPF6_DEBUG_ROUTE_INTRA); | |
959 | OSPF6_DEBUG_ROUTE_OFF(OSPF6_DEBUG_ROUTE_INTER); | |
960 | OSPF6_DEBUG_ROUTE_OFF(OSPF6_DEBUG_ROUTE_MEMORY); | |
961 | OSPF6_DEBUG_SPF_OFF(OSPF6_DEBUG_SPF_PROCESS); | |
962 | OSPF6_DEBUG_SPF_OFF(OSPF6_DEBUG_SPF_TIME); | |
963 | OSPF6_DEBUG_SPF_OFF(OSPF6_DEBUG_SPF_DATABASE); | |
964 | OSPF6_DEBUG_ZEBRA_OFF(OSPF6_DEBUG_ZEBRA_SEND | OSPF6_DEBUG_ZEBRA_RECV); | |
965 | ||
966 | return CMD_SUCCESS; | |
4dfd8aff DW |
967 | } |
968 | ||
d62a17ae | 969 | int config_write_ospf6_debug_neighbor(struct vty *vty) |
508e53e2 | 970 | { |
d62a17ae | 971 | if (IS_OSPF6_DEBUG_NEIGHBOR(STATE) && IS_OSPF6_DEBUG_NEIGHBOR(EVENT)) |
972 | vty_out(vty, "debug ospf6 neighbor\n"); | |
973 | else if (IS_OSPF6_DEBUG_NEIGHBOR(STATE)) | |
974 | vty_out(vty, "debug ospf6 neighbor state\n"); | |
975 | else if (IS_OSPF6_DEBUG_NEIGHBOR(EVENT)) | |
976 | vty_out(vty, "debug ospf6 neighbor event\n"); | |
977 | return 0; | |
508e53e2 | 978 | } |
979 | ||
d62a17ae | 980 | void install_element_ospf6_debug_neighbor(void) |
508e53e2 | 981 | { |
d62a17ae | 982 | install_element(ENABLE_NODE, &debug_ospf6_neighbor_cmd); |
983 | install_element(ENABLE_NODE, &no_debug_ospf6_neighbor_cmd); | |
984 | install_element(ENABLE_NODE, &no_debug_ospf6_cmd); | |
985 | install_element(CONFIG_NODE, &debug_ospf6_neighbor_cmd); | |
986 | install_element(CONFIG_NODE, &no_debug_ospf6_neighbor_cmd); | |
987 | install_element(CONFIG_NODE, &no_debug_ospf6_cmd); | |
508e53e2 | 988 | } |