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 24static int 25nbs_full_change (struct ospf6_interface *ospf6_interface) 26{ 27 CALL_FOREACH_LSA_HOOK (hook_interface, hook_change, ospf6_interface); 28 return 0; 29} 30 31static int 32nbs_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 */ 78int 79need_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 96int 97hello_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 117int 118twoway_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 156int 157negotiation_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 176int 177exchange_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 209int 210loading_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 230int 231adj_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 276int 277seqnumber_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 308int 309bad_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 340int 341oneway_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 366int 367inactivity_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 392