int bad_lsreq(struct thread * thread) { struct ospf6_neighbor * on; struct ospf6_lsa * lsa; on = (struct ospf6_neighbor *) THREAD_ARG(thread); assert(on); if(on->state < OSPF6_NEIGHBOR_EXCHANGE) return 0; if(IS_OSPF6_SIBLING_DEBUG_NEIGHBOR) zlog_debug("Neighbor Event %s: *BadLSReq*", on->name); ospf6_neighbor_state_change(OSPF6_NEIGHBOR_EXSTART, on); SET_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MSBIT); SET_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MBIT); SET_FLAG(on->dbdesc_bits, OSPF6_DBDESC_IBIT); ospf6_lsdb_remove_all(on->summary_list); ospf6_lsdb_remove_all(on->request_list); for(lsa = ospf6_lsdb_head(on->retrans_list); lsa; lsa = ospf6_lsdb_next(lsa)) { ospf6_decrement_retrans_count(lsa); ospf6_lsdb_remove(lsa, on->retrans_list); } THREAD_OFF(on->thread_send_dbdesc); on->thread_send_dbdesc = thread_add_event(master, ospf6_dbdesc_send, on, 0); return 0; }
int oneway_received (struct thread *thread) { struct ospf6_neighbor *on; struct ospf6_lsa *lsa; on = (struct ospf6_neighbor *) THREAD_ARG (thread); assert (on); if (on->state < OSPF6_NEIGHBOR_TWOWAY) return 0; if (IS_OSPF6_DEBUG_NEIGHBOR (EVENT)) zlog_info ("Neighbor Event %s: *1Way-Received*", on->name); ospf6_neighbor_state_change (OSPF6_NEIGHBOR_INIT, on); thread_add_event (master, neighbor_change, on->ospf6_if, 0); ospf6_lsdb_remove_all (on->summary_list); ospf6_lsdb_remove_all (on->request_list); for (lsa = ospf6_lsdb_head (on->retrans_list); lsa; lsa = ospf6_lsdb_next (lsa)) { ospf6_decrement_retrans_count (lsa); ospf6_lsdb_remove (lsa, on->retrans_list); } THREAD_OFF (on->thread_send_dbdesc); THREAD_OFF (on->thread_send_lsreq); THREAD_OFF (on->thread_send_lsupdate); THREAD_OFF (on->thread_send_lsack); return 0; }
void ospf6_lsdb_remove_all (struct ospf6_lsdb *lsdb) { struct ospf6_lsa *lsa; for (lsa = ospf6_lsdb_head (lsdb); lsa; lsa = ospf6_lsdb_next (lsa)) ospf6_lsdb_remove (lsa, lsdb); }
void ospf6_neighbor_delete (struct ospf6_neighbor *on) { struct ospf6_lsa *lsa; ospf6_lsdb_remove_all (on->summary_list); ospf6_lsdb_remove_all (on->request_list); for (lsa = ospf6_lsdb_head (on->retrans_list); lsa; lsa = ospf6_lsdb_next (lsa)) { ospf6_decrement_retrans_count (lsa); ospf6_lsdb_remove (lsa, on->retrans_list); } ospf6_lsdb_remove_all (on->dbdesc_list); ospf6_lsdb_remove_all (on->lsreq_list); ospf6_lsdb_remove_all (on->lsupdate_list); ospf6_lsdb_remove_all (on->lsack_list); ospf6_lsdb_delete (on->summary_list); ospf6_lsdb_delete (on->request_list); ospf6_lsdb_delete (on->retrans_list); ospf6_lsdb_delete (on->dbdesc_list); ospf6_lsdb_delete (on->lsreq_list); ospf6_lsdb_delete (on->lsupdate_list); ospf6_lsdb_delete (on->lsack_list); #ifdef HAVE_KBFD if (CHECK_FLAG (on->bfd_flag, OSPF6_NBR_BFD_ENABLE)) ospf6_bfd_peer_delete (on); #endif /*HAVE_KBFD*/ THREAD_OFF (on->inactivity_timer); THREAD_OFF (on->thread_send_dbdesc); THREAD_OFF (on->thread_send_lsreq); THREAD_OFF (on->thread_send_lsupdate); THREAD_OFF (on->thread_send_lsack); XFREE (MTYPE_OSPF6_NEIGHBOR, on); }
int adj_ok (struct thread *thread) { struct ospf6_neighbor *on; struct ospf6_lsa *lsa; on = (struct ospf6_neighbor *) THREAD_ARG (thread); assert (on); if (IS_OSPF6_DEBUG_NEIGHBOR (EVENT)) zlog_info ("Neighbor Event %s: *AdjOK?*", on->name); if (on->state == OSPF6_NEIGHBOR_TWOWAY && need_adjacency (on)) { ospf6_neighbor_state_change (OSPF6_NEIGHBOR_EXSTART, on); SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT); SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT); SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT); THREAD_OFF (on->thread_send_dbdesc); on->thread_send_dbdesc = thread_add_event (master, ospf6_dbdesc_send, on, 0); } else if (on->state >= OSPF6_NEIGHBOR_EXSTART && ! need_adjacency (on)) { ospf6_neighbor_state_change (OSPF6_NEIGHBOR_TWOWAY, on); ospf6_lsdb_remove_all (on->summary_list); ospf6_lsdb_remove_all (on->request_list); for (lsa = ospf6_lsdb_head (on->retrans_list); lsa; lsa = ospf6_lsdb_next (lsa)) { ospf6_decrement_retrans_count (lsa); ospf6_lsdb_remove (lsa, on->retrans_list); } } return 0; }
void ospf6_neighbor_delete(struct ospf6_neighbor * on) { struct ospf6_lsa * lsa; ospf6_lsdb_remove_all(on->summary_list); ospf6_lsdb_remove_all (on->request_list); for (lsa = ospf6_lsdb_head (on->retrans_list); lsa; lsa = ospf6_lsdb_next (lsa)) { ospf6_decrement_retrans_count (lsa); ospf6_lsdb_remove (lsa, on->retrans_list); } ospf6_lsdb_remove_all (on->dbdesc_list); ospf6_lsdb_remove_all (on->lsreq_list); ospf6_lsdb_remove_all (on->lsupdate_list); ospf6_lsdb_remove_all (on->lsack_list); ospf6_lsdb_delete (on->summary_list); ospf6_lsdb_delete (on->request_list); ospf6_lsdb_delete (on->retrans_list); ospf6_lsdb_delete (on->dbdesc_list); ospf6_lsdb_delete (on->lsreq_list); ospf6_lsdb_delete (on->lsupdate_list); ospf6_lsdb_delete (on->lsack_list); THREAD_OFF (on->inactivity_timer); THREAD_OFF (on->thread_send_dbdesc); THREAD_OFF (on->thread_send_lsreq); THREAD_OFF (on->thread_send_lsupdate); THREAD_OFF (on->thread_send_lsack); free(on); on = NULL; }
int ospf6_flood_interface_mdr (struct ospf6_neighbor *from, struct ospf6_lsa *lsa, struct ospf6_interface *oi) { struct listnode *node, *nnode; struct ospf6_neighbor *on; struct ospf6_lsa *req; int retrans_added = 0; int is_debug = 0; struct list *flood_neighbors = list_new (); bool flood_lsa = true; if (IS_OSPF6_DEBUG_FLOODING || IS_OSPF6_DEBUG_FLOOD_TYPE (lsa->header->type)) { is_debug++; zlog_debug ("Flooding on %s: %s", oi->interface->name, lsa->name); } /* (1) For each neighbor */ for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on)) { if (is_debug) zlog_debug ("To neighbor %s", on->name); /* (a) if neighbor state < Exchange, examin next */ // Consider adjacent and (backup) dependent neighbors. // Require all bidirectional neighbors to be covered if (on->state < OSPF6_NEIGHBOR_TWOWAY) { if (is_debug) zlog_debug ("Neighbor state less than TwoWay, next neighbor"); continue; } if (on->state > OSPF6_NEIGHBOR_TWOWAY && on->state < OSPF6_NEIGHBOR_FULL && !need_adjacency (on)) { if (is_debug) zlog_debug ("No longer need adjacency with neighbor %s: " "scheduling AdjOK?", on->name); ospf6_neighbor_schedule_adjok (on); continue; } /* (b) if neighbor not yet Full, check request-list */ if (on->state >= OSPF6_NEIGHBOR_EXCHANGE && on->state != OSPF6_NEIGHBOR_FULL) { if (is_debug) zlog_debug ("Neighbor not yet Full"); req = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id, lsa->header->adv_router, on->request_list); if (req == NULL) { if (is_debug) zlog_debug ("Not on request-list for this neighbor"); /* fall through */ } else { /* If new LSA less recent, examin next neighbor */ if (ospf6_lsa_compare (lsa, req) > 0) { if (is_debug) zlog_debug ("Requesting is newer, next neighbor"); continue; } /* If the same instance, delete from request-list and examin next neighbor */ if (ospf6_lsa_compare (lsa, req) == 0) { if (is_debug) zlog_debug ("Requesting the same, remove it, next neighbor"); ospf6_lsdb_remove (req, on->request_list); continue; } /* If the new LSA is more recent, delete from request-list */ if (ospf6_lsa_compare (lsa, req) < 0) { if (is_debug) zlog_debug ("Received is newer, remove requesting"); ospf6_lsdb_remove (req, on->request_list); /* fall through */ } } } /* (c) If the new LSA was received from this neighbor, examin next neighbor */ if (from == on) { if (is_debug) zlog_debug ("LSA was received from neighbor %s, next neighbor", on->name); continue; } //Ogierv3 Section 6 Par 3 /* At this point, we are not positive that the neighbor has an up-to-date instance of this new LSA */ /* However, in the MANET case, we need to: i) check whether neighbor sent a multicast ACK for it already ii) whether I am an active relay for this originator */ /* Has LSA been acked previously with multicast ack? */ if (ospf6_mdr_neighbor_has_acked (on, lsa)) { //Don't add LSA to neighbor's retransmission list if (is_debug) zlog_debug ("Existing multicast ACK from neighbor %s found " "for LSA, next neighbor", on->name); continue; // examine next neighbor: neighbor already acked } /* Here, checking for coverage of this neighbor on the sender's RNL. If not present, I add this to the flood_neighbors list. If LSA was received as a unicast, however, can't assume that neighbor "on" was covered by the transmission, so still need to add to flood_neighbors regardless of from->rnl */ if (from) { if (!from->mdr.Report2Hop || (!CHECK_FLAG (lsa->flag, OSPF6_LSA_RECVMCAST)) || !ospf6_mdr_lookup_neighbor (from->mdr.rnl, on->router_id)) { listnode_add (flood_neighbors, on); } } // Retransmit only to adjacent neighbors. if (on->state < OSPF6_NEIGHBOR_EXCHANGE) continue; /* (d) add retrans-list, schedule retransmission */ if (is_debug) zlog_debug ("Add retrans-list of this neighbor"); ospf6_increment_retrans_count (lsa); quagga_gettime (QUAGGA_CLK_MONOTONIC, &lsa->rxmt_time); ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->retrans_list); on->thread_send_lsupdate = ospf6_send_lsupdate_delayed_msec (master, ospf6_lsupdate_send_neighbor, on, oi->rxmt_interval * 1000, on->thread_send_lsupdate); retrans_added++; } /* (2) examin next interface if not added to retrans-list */ // MDRs can flood an LSA without adding it to the retrans-list if (!from && retrans_added == 0) { /* this LSA is self-originated but there are no adjacent neighbors */ flood_lsa = false; if (is_debug) zlog_debug ("Self-originated LSA and no adjacent neighbors"); } //Ogierv3 Section 6 - Remove (3) and (4) //Ogierv3 Section 6 - Replace (5) //Ogierv3 Forwarding Procedure bullet(a) if (from && oi->mdr.mdr_level == OSPF6_MDR) { //Flood the LSA unless all neighbors are already covered if (flood_neighbors->count == 0) { flood_lsa = false; if (is_debug) zlog_debug ("All neighbors covered"); } else if (oi->mdr.nonflooding_mdr) { // Non-flooding MDR acts like a BMDR. for (ALL_LIST_ELEMENTS (flood_neighbors, node, nnode, on)) ospf6_backupwait_lsa_add (lsa, on); flood_lsa = false; if (is_debug) zlog_debug ("Router is a non-flooding MDR"); } } //Ogierv3 Forwarding Procedure bullet(c) else if (from && oi->mdr.mdr_level == OSPF6_BMDR)
int negotiation_done(struct thread * thread) { struct ospf6_neighbor * on; struct ospf6_lsa * lsa; on = (struct ospf6_neighbor *) THREAD_ARG(thread); assert(on); if(on->state != OSPF6_NEIGHBOR_EXSTART) return 0; if(IS_OSPF6_SIBLING_DEBUG_NEIGHBOR) zlog_debug("Neighbor Event %s: *NegotiationDone*", on->name); /* clear ls-list */ ospf6_lsdb_remove_all(on->summary_list); ospf6_lsdb_remove_all(on->request_list); for(lsa = ospf6_lsdb_head(on->retrans_list); lsa; lsa = ospf6_lsdb_next(lsa)) { ospf6_decrement_retrans_count(lsa); ospf6_lsdb_remove(lsa, on->retrans_list); } /* Interface scoped LSAs */ for(lsa = ospf6_lsdb_head(on->ospf6_if->lsdb); lsa; lsa = ospf6_lsdb_next(lsa)) { if (OSPF6_LSA_IS_MAXAGE (lsa)) { ospf6_increment_retrans_count(lsa); ospf6_lsdb_add(ospf6_lsa_copy(lsa), on->retrans_list); } else ospf6_lsdb_add(ospf6_lsa_copy(lsa), on->summary_list); } /* Area scoped LSAs - no area implemented yet */ // LIST_FOR_EACH(lsa, struct ospf6_lsa, node, on-> ) // { // } /* AS scoped LSAs */ for(lsa = ospf6_lsdb_head(ospf6->lsdb); lsa; lsa = ospf6_lsdb_next(lsa)) { if(OSPF6_LSA_IS_MAXAGE(lsa)) { ospf6_increment_retrans_count(lsa); ospf6_lsdb_add(ospf6_lsa_copy(lsa), on->retrans_list); } else ospf6_lsdb_add(ospf6_lsa_copy(lsa), on->summary_list); } UNSET_FLAG(on->dbdesc_bits, OSPF6_DBDESC_IBIT); ospf6_neighbor_state_change(OSPF6_NEIGHBOR_EXCHANGE, on); return 0; }