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