⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dbage.c

📁 BCAST Implementation for NS2
💻 C
字号:
/* *   OSPFD routing daemon *   Copyright (C) 1998 by John T. Moy *    *   This program is free software; you can redistribute it and/or *   modify it under the terms of the GNU General Public License *   as published by the Free Software Foundation; either version 2 *   of the License, or (at your option) any later version. *    *   This program is distributed in the hope that it will be useful, *   but WITHOUT ANY WARRANTY; without even the implied warranty of *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *   GNU General Public License for more details. *    *   You should have received a copy of the GNU General Public License *   along with this program; if not, write to the Free Software *   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *//* Aging of the link state database. */#include "ospfinc.h"#include "nbrfsm.h"#include "system.h"// Declarations of staticsLSA *LSA::AgeBins[MaxAge+1];	// Aging Binsint LSA::Bin0;			// Current age 0 binint32 LSA::RefreshBins[MaxAgeDiff];// Refresh binsint LSA::RefreshBin0;		// Current refresh bin/* Start aging an LSA. Remove it from an existing bin, if necessary. * MaxAge LSAs are not installed in any age bin; however, "lsa_agebin" * is set so that "since_received()" returns the correct answer. * MaxAge LSAs are instead installed on the "MaxAge_list", so that * they will be removed from the database as soon as they are * acknowledged. * * DoNotAge LSAs are always installed in the age 0 bin. Otherwise, * install in the bin currently corresponding to the LSA's * received age. */void LSA::start_aging(){    uns16 bin;    if (in_agebin)	stop_aging();    if (lsa_rcvage == MaxAge) {	lsa_agebin = Age2Bin((age_t) 0);	ospf->MaxAge_list.addEntry(this);	return;    }    else if ((lsa_rcvage & DoNotAge) != 0)	bin = Age2Bin((age_t) 0);    else	bin = Age2Bin(lsa_rcvage);    in_agebin = true;    lsa_agebin = bin;    lsa_agefwd = AgeBins[bin];    lsa_agerv = 0;    if (AgeBins[bin])	AgeBins[bin]->lsa_agerv = this;    AgeBins[bin] = this;}/* Stop aging an LSA. Simply remove it from its current bin, and * reset the "aging" bit. */void LSA::stop_aging(){    if (!in_agebin)	return;    if (lsa_agerv)	lsa_agerv->lsa_agefwd = lsa_agefwd;    else	AgeBins[lsa_agebin] = lsa_agefwd;    if (lsa_agefwd)	lsa_agefwd->lsa_agerv = lsa_agerv;    in_agebin = false;    lsa_agefwd = 0;    lsa_agerv = 0;}/* Database aging timer. Called once a second. Besides * perfoming database functions, also perfoms other * functions that need to be done periodically, like * rerunning the routing table calculation. */void DBageTimer::action(){    LSA *lsap;    LsaListIterator iter(&ospf->replied_list);    // Age the link-state database    ospf->dbage();    // Exit helper mode?    if (ospf->topology_change)	ospf->htl_topology_change();    // Delete down neighbors    ospf->delete_down_neighbors();    // Establish more adjacencies?    while (ospf->n_lcl_inits < ospf->max_dds) {	SpfNbr *np;	if (!(np = GetNextAdj()))	    break;	np->nbr_fsm(NBE_EVAL);    }    // Clear reply flags in any LSAs    while ((lsap = iter.get_next())) {	lsap->sent_reply = false;	iter.remove_current();    }    // Run routing calculations    if (ospf->full_sched)	ospf->full_calculation();    if (ospf->ase_sched)	ospf->do_all_ases();    if (ospf->clear_mospf == true)        ospf->mospf_clear_cache();    // Process any pending LSA activity (flooding, origination)    // Synchronize with kernel    ospf->krt_sync();    // Upload remnants of routing table installed by previous instances    if (ospf->need_remnants) {        ospf->need_remnants = false;	sys->upload_remnants();    }    // Perform hitless restart processing    if (ospf->in_hitless_restart()) {        if (ospf->check_htl_termination)	    ospf->htl_exit_criteria();        if (ospf->start_htl_exit)	    ospf->exit_hitless_restart(ospf->htl_exit_reason);    }}/* Main aging routine called once a second. Increment the current * "Bin0", which effectively ages all bins by one second. Then, * perform processing on the bins whose age values have * special meaning in the OSPF specification: * *	Check for deferred originations (5 second bin) *	Refresh self-originated LSAs (30 minute bin) *	CheckAge processing (15,30,45 minute bins) *	Flush (by reflooding) MaxAge advertisements (60 minute bin) * * After this is done, go through the list of the LSAs that are being * flushed to see which ones can be removed from the database * (i.e., when no neighbors in Database Exchange, and LSA has been * acked by all adjacent neighbors). As a special case, those * LSAs that indicate "LSA::rollover" will be refreshed with the * initial sequence number, instead of being removed. */void OSPF::dbage(){    // Increment age by one second    LSA::Bin0++;    if (LSA::Bin0 > MaxAge)	LSA::Bin0 = 0;    // Process LSAs of certain ages    deferred_lsas();    checkages();    refresh_lsas();    maxage_lsas();    refresh_donotages();    do_refreshes();    // Finish any flooding that was caused by age routines    send_updates();    // Check to see whether any MaxAge can be deleted    free_maxage_lsas();    // Check to see whether we need to flush DoNotAge LSAs    donotage_changes();    // If shutting down, see if we can go to next phase    if (shutting_down() &&	(--countdown <= 0 || MaxAge_list.is_empty()))	shutdown_continue();    }/* Go through the LSAs of age MinLSInterval, reoriginating * those that have been deferred. * We firest put them on a list, so that the act of reoriginating * doesn't corrupt the singly linked list within t he age bins (in * some cases, reoriginating one LSA causes others to be reoriginated, * so it is not enough to simply remember the next LSA in the * age bin). */void OSPF::deferred_lsas(){    uns16 bin;    LSA	*lsap;    LsaList defer_list;    bin = Age2Bin(MinLSInterval);    for (lsap = LSA::AgeBins[bin]; lsap; lsap = lsap->lsa_agefwd) {	if (!lsap->deferring)	    continue;	if (lsap->adv_rtr() == myid) {	    lsap->deferring = false;	    defer_list.addEntry(lsap);	}    }    LsaListIterator *iter;    iter = new LsaListIterator(&defer_list);    while((lsap = iter->get_next())) {        if (lsap->valid() && lsap->lsa_agebin == bin)	    lsap->reoriginate(false);	iter->remove_current();    }    delete iter;}/* Verify LSA checksums every 15 minutes, on the average. * Even out the checksum calculations so that we're doing * the same number every second. */void OSPF::checkages(){    age_t age;    int limit;    LSA *lsap;    for (age = CheckAge; age < MaxAge; age += CheckAge) {	uns16 bin;	bin = Age2Bin(age);	for (lsap = LSA::AgeBins[bin]; lsap; lsap = lsap->lsa_agefwd) {	    if (!lsap->checkage) {	        lsap->checkage = true;		dbcheck_list.addEntry(lsap);	    }	}    }    LsaListIterator iter(&dbcheck_list);    limit = total_lsas/CheckAge + 1;    for (int i = 0; (lsap = iter.get_next()) && i < limit; i++) {	if (lsap->valid()) {	  	    LShdr *hdr;	    int xlen;	    hdr = BuildLSA(lsap);	    xlen = ntoh16(hdr->ls_length) - sizeof(uns16);	    if (!hdr->verify_cksum())		sys->halt(HALT_DBCORRUPT, "Corrupted LS database");	}	lsap->checkage = false;	iter.remove_current();    }    // Get rid of any invlide entries    dbcheck_list.garbage_collect();}/* Reoriginate all self-originated LSAs of age LSRefreshTime. */void OSPF::refresh_lsas(){    uns16 bin;    LSA	*lsap;    LSA	*next_lsa;    bin = Age2Bin(LSRefreshTime);    for (lsap = LSA::AgeBins[bin]; lsap; lsap = next_lsa) {	next_lsa = lsap->lsa_agefwd;	if (lsap->do_not_age())	    continue;	if (lsap->adv_rtr() == myid)	    schedule_refresh(lsap);    }}/* Flush all MaxAge LSAs by reflooding them. Remove from * aging bins and keep on separate list which will be * periodically scanned to see whether we can garbage collect * them. */void OSPF::maxage_lsas(){    uns16 bin;    LSA	*lsap;    LSA	*next_lsa;    bin = Age2Bin(MaxAge);    for (lsap = LSA::AgeBins[bin]; lsap; lsap = next_lsa) {	next_lsa = lsap->lsa_agefwd;	if (lsap->do_not_age()) {	    if (lsap->adv_rtr() == myid) {	        lsap->lsa_hour++;		continue;	    }	    else if (lsap->source->valid())	        continue;	}	age_prematurely(lsap);    }}/* Reoriginate all self-originated DoNotAge LSAs, according to * OSPF::refresh_rate. */void OSPF::refresh_donotages(){    uns16 age;    uns32 hour;    uns16 bin;    LSA	*lsap;    LSA	*next_lsa;    if (refresh_rate <= LSRefreshTime)        return;    hour = refresh_rate/3600;    age = refresh_rate%3600;    bin = Age2Bin(age);    for (lsap = LSA::AgeBins[bin]; lsap; lsap = next_lsa) {	next_lsa = lsap->lsa_agefwd;	if (lsap->adv_rtr() != myid)	    continue;	if (!lsap->do_not_age())	    continue;	if (lsap->lsa_hour >= hour)	    schedule_refresh(lsap);    }}/* Go through the list of LSAs that are being flushed and see * whether they can be returned to the heap. */void OSPF::free_maxage_lsas(){    LSA *lsap;    LsaListIterator iter(&MaxAge_list);    while ((lsap = iter.get_next())) {	if (!lsap->valid()) {	  	    iter.remove_current();	    continue;	}	if (lsap->lsa_rxmt != 0)	    continue;	if (!maxage_free(lsap->ls_type()))	    continue;	// OK to free. Remove from database	// List processing will then return	// to heap when appropriate	iter.remove_current();	if (lsap->rollover) {	    lsap->rollover = false;	    lsap->refresh(InvalidLSSeq);	}	else	    ospf->DeleteLSA(lsap);    }}/* Process changes in the DoNotAge capability of the network. */void OSPF::donotage_changes(){    AreaIterator iter(this);    SpfArea *a;    // Reoriginate indication-LSAs?    // Also flush AS-external-LSAs, if necessary    if (dna_change) {        AreaIterator *oiter;        oiter = new AreaIterator(this);	dna_flushq.clear();	while ((a = oiter->get_next())) {	    ASBRrte *rrte;	    if (a->is_stub())	        continue;	    // (Re)originate indication-LSAs	    rrte = add_asbr(myid);	    a->asbr_orig(rrte);	}	if (!donotage())	    flush_donotage();	delete oiter;	dna_change = false;    }    // Now do areas whose DoNotAge capability has changed    while ((a = iter.get_next())) {        if (!a->dna_change)	    continue;	a->a_dna_flushq.clear();	if (!a->donotage())	    a->a_flush_donotage();	a->dna_change = false;    }}/* Go through and flush all DoNotAge AS-external-LSAs. * Locally originated ones are simply refreshed without * the DoNotAge bit set. */void OSPF::flush_donotage(){    AVLsearch iter(&extLSAs);    ASextLSA *lsap;    while ((lsap = (ASextLSA *)iter.next())) {        ExRtData *exdata = 0;        if (!lsap->do_not_age())	    continue;	if (lsap->adv_rtr() == my_id() &&	    lsap->orig_rte != 0 &&	    (exdata = lsap->orig_rte->exdata)) {	    ase_schedule(exdata);	}	else {	    dna_flushq.addEntry(lsap);	    if (!origtim.is_running())	        origtim.start(Timer::SECOND/10);	}    }}/* Flush all the DoNotAge LSAs from an area. Our locally-originated * LSAs are simply refreshed. */void SpfArea::a_flush_donotage(){    byte lstype;    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())) {	    if (!lsap->do_not_age())	        continue;	    if (lsap->adv_rtr() == ospf->my_id())	        lsap->reoriginate(false);	    else {	        a_dna_flushq.addEntry(lsap);		if (!ospf->origtim.is_running())	            ospf->origtim.start(Timer::SECOND/10);	    }	}	delete iter;    }}/* The official time to refresh a given LSA has arrived. * If configured to randomly refresh, delay the refresh * randomly up to MaxAgeDiff seconds. Otherwise (the default) * refresh the LSA immediately by forcing a reorigination. */void OSPF::schedule_refresh(LSA *lsap){    int slot;    /* If random_refresh,      * we are going to randomly delay reorigination     * until some time in the next MaxAgeDiff     * seconds. Note: we don't care where the current     * refresh bin is.     */    slot = Timer::random_period(MaxAgeDiff);    if (!random_refresh || slot < 0 || slot >= MaxAgeDiff)        slot = LSA::RefreshBin0;    LSA::RefreshBins[slot]++;    pending_refresh.addEntry(lsap);}/* Go through the list of scheduled originations, and refresh * the number that have been scheduled for this  * timeslot (width one second). LSAs that have already * been overwritten or deleted still count against the tally, * but are of course not refreshed. */void OSPF::do_refreshes(){    int count;    LSA *lsap;    LsaListIterator iter(&pending_refresh);    count = LSA::RefreshBins[LSA::RefreshBin0];    LSA::RefreshBins[LSA::RefreshBin0] = 0;    // Refresh up to count LSAs    for (; count > 0 && (lsap = iter.get_next()); count--) {        int msgno;	if (!lsap->valid() || lsap->lsa_age() == MaxAge) {	    iter.remove_current();	    continue;	}	msgno = lsap->do_not_age() ? LOG_DNAREFR : LOG_LSAREFR;	if (spflog(msgno, 1))	    log(lsap);	iter.remove_current();        lsap->reoriginate(true);    }    LSA::RefreshBin0++;    if (LSA::RefreshBin0 >= MaxAgeDiff)        LSA::RefreshBin0 = 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -