/* Restore an interface to its pre UP state Used from ism_interface_down only */ void ospf_if_cleanup (struct ospf_interface *oi) { struct route_node *rn; struct listnode *node, *nnode; struct ospf_neighbor *nbr; struct ospf_nbr_nbma *nbr_nbma; struct ospf_lsa *lsa; /* oi->nbrs and oi->nbr_nbma should be deleted on InterfaceDown event */ /* delete all static neighbors attached to this interface */ for (ALL_LIST_ELEMENTS (oi->nbr_nbma, node, nnode, nbr_nbma)) { OSPF_POLL_TIMER_OFF (nbr_nbma->t_poll); if (nbr_nbma->nbr) { nbr_nbma->nbr->nbr_nbma = NULL; nbr_nbma->nbr = NULL; } nbr_nbma->oi = NULL; listnode_delete (oi->nbr_nbma, nbr_nbma); } /* send Neighbor event KillNbr to all associated neighbors. */ for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) if ((nbr = rn->info) != NULL) if (nbr != oi->nbr_self) OSPF_NSM_EVENT_EXECUTE (nbr, NSM_KillNbr); /* Cleanup Link State Acknowlegdment list. */ for (ALL_LIST_ELEMENTS (oi->ls_ack, node, nnode, lsa)) ospf_lsa_unlock (&lsa); /* oi->ls_ack */ list_delete_all_node (oi->ls_ack); oi->crypt_seqnum = 0; /* Empty link state update queue */ ospf_ls_upd_queue_empty (oi); /* Reset pseudo neighbor. */ ospf_nbr_delete (oi->nbr_self); oi->nbr_self = ospf_nbr_new (oi); ospf_nbr_add_self (oi); ospf_lsa_unlock (&oi->network_lsa_self); oi->network_lsa_self = NULL; OSPF_TIMER_OFF (oi->t_network_lsa_self); #ifdef HAVE_GRACEFUL_RESTART THREAD_TIMER_OFF(oi->t_opaque_lsa_refresh); oi->v_opaque_lsa_count = 0 ; #endif }
struct ospf_neighbor * ospf_nbr_get (struct ospf_interface *oi, struct ospf_header *ospfh, struct ip *iph, struct prefix *p) { struct route_node *rn; struct prefix key; struct ospf_neighbor *nbr; key.family = AF_INET; key.prefixlen = IPV4_MAX_BITLEN; if (oi->type == OSPF_IFTYPE_VIRTUALLINK) { key.u.prefix4 = ospfh->router_id; /* index vlink nbrs by router-id */ } else { key.u.prefix4 = iph->ip_src; } rn = route_node_get (oi->nbrs, &key); if (rn->info) { route_unlock_node (rn); nbr = rn->info; if (oi->type == OSPF_IFTYPE_NBMA && nbr->state == NSM_Attempt) { nbr->src = iph->ip_src; memcpy (&nbr->address, p, sizeof (struct prefix)); } /*add by bill 20091224. if the nbr's router id is changed, then the nbr's state is transit to ExStart, to refresh the adjacency*/ if(IPV4_ADDR_CMP(&nbr->router_id, &ospfh->router_id)) { nbr->router_id = ospfh->router_id; OSPF_NSM_EVENT_EXECUTE (nbr, NSM_AdjOK); } } else { rn->info = nbr = ospf_nbr_add (oi, ospfh, p); nbr->router_id = ospfh->router_id; } return nbr; }
/* Restore an interface to its pre UP state Used from ism_interface_down only */ void ospf_if_cleanup (struct ospf_interface *oi) { struct route_node *rn; struct listnode *node; struct ospf_neighbor *nbr; /* oi->nbrs and oi->nbr_nbma should be deletete on InterafceDown event */ /* delete all static neighbors attached to this interface */ for (node = listhead (oi->nbr_nbma); node; ) { struct ospf_nbr_nbma *nbr_nbma = getdata (node); nextnode (node); OSPF_POLL_TIMER_OFF (nbr_nbma->t_poll); if (nbr_nbma->nbr) { nbr_nbma->nbr->nbr_nbma = NULL; nbr_nbma->nbr = NULL; } nbr_nbma->oi = NULL; listnode_delete (oi->nbr_nbma, nbr_nbma); } /* send Neighbor event KillNbr to all associated neighbors. */ for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) if ((nbr = rn->info) != NULL) if (nbr != oi->nbr_self) OSPF_NSM_EVENT_EXECUTE (nbr, NSM_KillNbr); /* Cleanup Link State Acknowlegdment list. */ for (node = listhead (oi->ls_ack); node; nextnode (node)) ospf_lsa_unlock (node->data); list_delete_all_node (oi->ls_ack); oi->crypt_seqnum = 0; /* Empty link state update queue */ ospf_ls_upd_queue_empty (oi); /* Handle pseudo neighbor. */ ospf_nbr_delete (oi->nbr_self); oi->nbr_self = ospf_nbr_new (oi); oi->nbr_self->state = NSM_TwoWay; oi->nbr_self->priority = OSPF_IF_PARAM (oi, priority); switch (oi->area->external_routing) { case OSPF_AREA_DEFAULT: SET_FLAG (oi->nbr_self->options, OSPF_OPTION_E); break; case OSPF_AREA_STUB: UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E); break; case OSPF_AREA_NSSA: UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E); SET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP); break; } ospf_lsa_unlock (oi->network_lsa_self); oi->network_lsa_self = NULL; OSPF_TIMER_OFF (oi->t_network_lsa_self); }