📄 lsdb.c
字号:
* areas. Link-local-LSAs are deleted in SpfIfc::delete_lsdb(). */void SpfArea::delete_lsdb(){ byte lstype; SpfArea *bb; bb = ospf->FindArea(BACKBONE); for (lstype = 0; lstype <= MAX_LST; lstype++) { AVLtree *tree; AVLsearch *iter; LSA *lsap; if (flooding_scope(lstype) != AreaScope) continue; if (!(tree = ospf->FindLSdb(0, this, lstype))) continue; iter = new AVLsearch(tree); while ((lsap = (LSA *)iter->next())) { lsap->stop_aging(); ospf->UnParseLSA(lsap); switch(lstype) { case LST_AREA_OPQ: // Notify applications of Opaque-LSA deletion? if (lsap->lsa_rcvage != MaxAge) { lsap->lsa_rcvage = MaxAge; ospf->upload_opq(lsap); } break; case LST_GM: if (bb && bb->n_active_if != 0) bb->grp_orig(lsap->ls_id(), 0); break; default: break; } } delete iter; // This frees the LSAs, unless they are on some list tree->clear(); } // Reset database checksum db_xsum = 0;}/* Silently delete all link-local Opaque-LSAs. Analogue to * SpfArea::delete_lsdb(), this is only called when the * interface becomes inoperational. */void SpfIfc::delete_lsdb(){ AVLtree *tree; AVLsearch *iter; LSA *lsap; tree = ospf->FindLSdb(this, if_area, LST_LINK_OPQ); iter = new AVLsearch(tree); while ((lsap = (LSA *)iter->next())) { lsap->stop_aging(); ospf->UnParseLSA(lsap); // Notify applications of Opaque-LSA deletion? if (lsap->lsa_rcvage != MaxAge) { lsap->lsa_rcvage = MaxAge; ospf->upload_opq(lsap); } } delete iter; // This frees the LSAs, unless they are on some list tree->clear(); // Reset database checksum db_xsum = 0;}/* Parse an LSA. Call the LSA-specific parse routine. If that * routine indicates an exception, then must store the entire * body of the LSA in order to rebuild it later. */void OSPF::ParseLSA(LSA *lsap, LShdr *hdr){ int blen; if (lsap->parsed) return; blen = ntoh16(hdr->ls_length) - sizeof(LShdr); if (lsap->lsa_age() != MaxAge) { bool o_dna = donotage(); bool o_a_dna = (lsap->lsa_ap ? lsap->lsa_ap->donotage() : false); lsap->exception = false; lsap->parsed = true; lsap->parse(hdr); lsap->process_donotage(true); total_lsas++; if (o_dna != donotage()) dna_change = true; if (lsap->lsa_ap && o_a_dna != lsap->lsa_ap->donotage()) lsap->lsa_ap->dna_change = true; } else lsap->exception = true; delete [] lsap->lsa_body; lsap->lsa_body = 0; if (lsap->exception) { lsap->lsa_body = new byte[blen]; memcpy(lsap->lsa_body, (hdr + 1), blen); }}/* Process the DC-bit, to tell whether all routers * support DoNotAge. Argument indicates whether we * are parsing or unparsing. * Overriden for ASBR-summary-LSAs, which do special * indication-LSA processing. */void LSA::process_donotage(bool parse){ int increment; increment = parse ? 1 : -1; // Update global DoNotAge provcessing capabilities if ((lsa_opts & SPO_DC) != 0) return; // Area scoped? if (lsa_ap) { lsa_ap->wo_donotage += increment; if (!lsa_ap->is_stub()) ospf->wo_donotage += increment; } else { AreaIterator a_iter(ospf); SpfArea *ap; ospf->wo_donotage += increment; while ((ap = a_iter.get_next())) { if (!ap->is_stub()) ap->wo_donotage += increment; } }}/* Unparse the LSA */void OSPF::UnParseLSA(LSA *lsap){ if (lsap->parsed) { bool o_dna = donotage(); bool o_a_dna = (lsap->lsa_ap ? lsap->lsa_ap->donotage() : false); lsap->parsed = false; lsap->process_donotage(false); // Type-specific unparse lsap->unparse(); total_lsas--; if (o_dna != donotage()) dna_change = true; if (lsap->lsa_ap && o_a_dna != lsap->lsa_ap->donotage()) lsap->lsa_ap->dna_change = true; }}/* Delete an LSA from the link-state database. Remove from * the AVL tree last, as that may cause the LSA to be returned to * the heap (and therefore become inaccessible). UnParseLSA() is called, */void OSPF::DeleteLSA(LSA *lsap){ AVLtree *btree; if (spflog(LOG_LSAFREE, 3)) log(lsap); update_lsdb_xsum(lsap, false); lsap->stop_aging(); UnParseLSA(lsap); btree = FindLSdb(lsap->lsa_ifp, lsap->lsa_ap, lsap->lsa_type); btree->remove((AVLitem *) lsap); lsap->delete_actions(); lsap->chkref();}/* Update the checksum of the whole database. One checksum * is kept for AS-external-LSAs, one for each area's * link-state database, and one for each interface (link-scoped * LSAs). */void OSPF::update_lsdb_xsum(LSA *lsap, bool add){ uns32 *db_xsum; int scope; scope = flooding_scope(lsap->ls_type()); if (scope == LocalScope) db_xsum = &lsap->lsa_ifp->db_xsum; else if (scope == AreaScope) db_xsum = &lsap->lsa_ap->db_xsum; else db_xsum = &ase_xsum; if (add) (*db_xsum) += lsap->lsa_xsum; else (*db_xsum) -= lsap->lsa_xsum;}/* Get the next LSA from the link-state database. Organized * first by OSPF area (AS-external-LSAs are considered part * of Area 0), then LS type, Link State ID, and Advertising * Router. * * Currently the next LSA function ignores link-scoped LSAs. * You can get these by using the API routine OSPF::get_next_opq(). */LSA *OSPF::NextLSA(aid_t a_id, byte ls_type, lsid_t id, rtid_t advrtr){ LSA *lsap; SpfArea *ap; AVLtree *tree; // Iterate over all areas lsap = 0; ap = FindArea(a_id); do { // Iterate over LS types for (; ls_type <= MAX_LST; id = advrtr = 0, ++ls_type) { if (flooding_scope(ls_type) == LocalScope) continue; if (a_id != 0 && flooding_scope(ls_type) == GlobalScope) continue; tree = FindLSdb(0, ap, ls_type); if (tree) { AVLsearch iter(tree); iter.seek(id, advrtr); if ((lsap = (LSA *) iter.next())) return(lsap); } } ls_type = 0; } while ((ap = NextArea(a_id))); return(lsap);}/* This version of Next LSA can be used to get Link-local LSAs. * For link-local LSAs associated with virtual links, the * taid is the virtual link's Transit Area (non-zero) * and if_addr is the Router ID of the other endpoint of the * virtual link. */LSA *OSPF::NextLSA(InAddr if_addr, int phyint, aid_t taid, byte ls_type, lsid_t id, rtid_t advrtr){ LSA *lsap; SpfIfc *ip; AVLtree *tree; // Iterate over all areas lsap = 0; ip = (taid ? find_vl(taid, if_addr) : find_ifc(if_addr, phyint)); do { // Iterate over LS types for (; ls_type <= MAX_LST; id = advrtr = 0, ++ls_type) { if (flooding_scope(ls_type) != LocalScope) continue; tree = FindLSdb(ip, 0, ls_type); if (tree) { AVLsearch iter(tree); iter.seek(id, advrtr); if ((lsap = (LSA *) iter.next())) return(lsap); } } ls_type = 0; if (ip && ip->is_virtual()) { taid = ip->transit_area()->a_id; if_addr = *ip->vl_endpt(); } else if (ip) { if_addr = ip->if_addr; phyint = ip->if_phyint; } // Get next interface if (taid) ip = next_vl(taid, if_addr); else if (!(ip = next_ifc(if_addr,phyint))) ip = next_vl(0, 0); } while (ip); return(lsap);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -