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

📄 summlsa.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. *//* Routines dealing with summary-LSAs. * This includes originating, parsing, unparsing and * running routing calculations. */#include "ospfinc.h"#include "system.h"/* Constructor for a summary-LSA. */summLSA::summLSA(SpfArea *ap, LShdr *hdr, int blen) : rteLSA(ap, hdr, blen){    link = 0;}/* Reoriginate a summary-LSA. Unlike build_summ_ls(), we * don't need to select a Link State ID. Since we are called * from the aging routines, we're only allowed to originate * a single LSA at once. */void summLSA::reoriginate(int forced){    uns32 cost;    summLSA *nlsap;    if (!orig_rte) {        lsa_flush(this);        return;    }    cost = lsa_ap->sl_cost(orig_rte);    nlsap = lsa_ap->sl_reorig(this, ls_id(), cost, orig_rte, forced);    if (nlsap)	nlsap->orig_rte = orig_rte;}/* Originate a new summary-LSA, for all areas * at once. * Performed when a routing table entry changes, * these updates are never forced. */void OSPF::sl_orig(INrte *rte, bool transit_changes_only){    SpfArea *ap;    AreaIterator aiter(ospf);    while ((ap = aiter.get_next())) {	if (transit_changes_only &&	    ap->was_transit == ap->a_transit)	    continue;	if (ap->n_active_if != 0)	    ap->sl_orig(rte);    }}/* Originate a new summary-LSA, for a given area. */void SpfArea::sl_orig(INrte *rte, int forced){    uns32 cost;    summLSA *olsap;    lsid_t ls_id;    INrte *o_rte;    summLSA *nlsap;    o_rte = 0;    // Determine whether to originate,    // and if so, the cost to use    cost = sl_cost(rte);    // Select Link State ID    if ((olsap = rte->my_summary_lsa()))	ls_id = olsap->ls_id();    else if (cost == LSInfinity)	return;    else if (!ospf->get_lsid(rte, LST_SUMM, this, ls_id))	return;    // Find current LSA, if any    if ((olsap = (summLSA *)ospf->myLSA(0, this, LST_SUMM, ls_id))) {	o_rte = olsap->orig_rte;	olsap->orig_rte = rte;    }    // Originate LSA    nlsap = sl_reorig(olsap, ls_id, cost, rte, forced);    if (nlsap)	nlsap->orig_rte = rte;    // If bumped another LSA, reoriginate    if (o_rte && (o_rte != rte)) {	// Print log message	sl_orig(o_rte, 0);    }}/* Determine the cost with which a particular route should be * be advertised into an area. */uns32 SpfArea::sl_cost(INrte *rte){    aid_t home;    uns32 cost;    // Stub area processing    if (a_stub) {	if (rte == default_route)	    return((ospf->n_area > 1) ? a_dfcst : LSInfinity);	else if (!a_import)	    return(LSInfinity);    }    // Aggregation    if (rte->is_range()) {	Range	*rp;	if ((rp = ospf->GetBestRange(rte)) &&	    (rp->r_active) &&	    (!a_transit || rp->r_area != BACKBONE)) {	    if (rp->r_suppress)		return(LSInfinity);	    else if (rp->r_area == a_id)		return(LSInfinity);	    else		return(rp->r_cost);	}    }    // Non-aggregated routes    if (rte->type() == RT_SPFIA) {	home = rte->area();	cost = rte->cost;    }    else if (rte->type() != RT_SPF)	return(LSInfinity);    else if (rte->r_mpath->all_in_area(this))	return(LSInfinity);    else if ((!a_transit || rte->area() != BACKBONE) &&	     rte->within_range())	return(LSInfinity);    else {	home = rte->area();	cost = rte->cost;    }    // Don't originate into same area    if (a_id == home)	return(LSInfinity);    return(cost);}/* After the cost and link state ID of the LSA has been decided, * build the summary-LSA and flood it. */summLSA *SpfArea::sl_reorig(summLSA *olsap, lsid_t lsid, uns32 cost,			    INrte *rte, int forced){    uns16 length;    LShdr *hdr;    SummHdr *summ;    LSA *nlsap;    seq_t seqno;    length = sizeof(LShdr) + sizeof(SummHdr);    // Originate, reoriginate or flush the LSA    if (cost == LSInfinity) {	lsa_flush(olsap);	return(0);    }    else if ((seqno = ospf->ospf_get_seqno(LST_SUMM, olsap, forced))	     == InvalidLSSeq)	return(0);    // Fill in LSA contents    // Header    hdr = ospf->orig_buffer(length);    hdr->ls_opts = SPO_DC;    if (!a_stub)	hdr->ls_opts |= SPO_EXT;    if (ospf->mc_abr())	hdr->ls_opts |= SPO_MC;    hdr->ls_type = LST_SUMM;    hdr->ls_id = hton32(lsid);    hdr->ls_org = hton32(ospf->my_id());    hdr->ls_seqno = hton32(seqno);    hdr->ls_length = hton16(length);    // Body    summ = (SummHdr *) (hdr + 1);    summ->mask = hton32(rte->mask());    summ->metric = hton32(cost);    nlsap = ospf->lsa_reorig(0, this, olsap, hdr, forced);    ospf->free_orig_buffer(hdr);    return((summLSA *)nlsap);}/* Of all the AS-external-LSAs linked off a routing table * entry, find the one (if any) that I have originated. */summLSA *INrte::my_summary_lsa(){    summLSA *lsap;    for (lsap = summs; lsap; lsap = (summLSA *) lsap->link) {        if (lsap->orig_rte != this)	    continue;	if (lsap->adv_rtr() == ospf->my_id())	    return(lsap);    }    return(0);}/* Parse a summary-LSA. * Figure out the matching routing table entry, and enqueue * the summary onto the routing table's list of summaries. * Make sure that the LSA isn't already parsed, so that we * don't attempt to add it to the routing entry's list twice. * * Don't add to the routing table entry's list if the cost is * LSInfinity, or if the LSA is self-originated. This are not used * in the routing calculations. */void summLSA::parse(LShdr *hdr){    SummHdr *summ;    uns32 netno;    uns32 mask;    summ = (SummHdr *) (hdr + 1);    mask = ntoh32(summ->mask);    netno = ls_id() & mask;    if (!(rte = inrttbl->add(netno, mask))) {	exception = true;	return;    }    if ((ntoh32(summ->metric) & ~LSInfinity) != 0)	exception = true;    else if (lsa_length != sizeof(LShdr) + sizeof(SummHdr))	exception = true;    adv_cost = ntoh32(summ->metric) & LSInfinity;    link = rte->summs;    rte->summs = this;}/* Unparse the summary-LSA. * Remove from the list in the routing table entry. */void summLSA::unparse(){    summLSA *ptr;    summLSA **prev;    if (!rte)	return;    // Unlink from list in routing table    for (prev = &rte->summs; (ptr = *prev); prev = (summLSA **)&ptr->link)	if (*prev == this) {	    *prev = (summLSA *)link;	    break;	}}/* Build a summary-LSA ready for flooding, from an * internally parsed version. */void summLSA::build(LShdr *hdr){    SummHdr *summ;    summ = (SummHdr *) (hdr + 1);    summ->mask = hton32(rte->mask());    summ->metric = hton32(adv_cost);}/* Go through the list of summary-LSAs for a routing table * entry, attempting to calculate an inter-area route. * The routing table entry's list doesn't conatin LSAs whose cost is * LSInfinity, if they are self-originated. This should not used * in the routing calculations, but we don't have to check here. */void INrte::run_inter_area(){    summLSA *lsap;    MPath *best_path;    SpfArea *summ_ap;    byte new_type;    if (r_type == RT_SPF || r_type == RT_DIRECT)	return;    // Saved state checked later in OSPF::rt_scan()    if (r_type == RT_SPFIA)	save_state();    new_type = RT_NONE;    best_path = 0;    cost = LSInfinity;    summ_ap = ospf->SummaryArea();    // Go through list of summary-LSAs    for (lsap = summs; lsap; lsap = (summLSA *)lsap->link) {	RTRrte *rtr;	uns32 new_cost;	if (lsap->area() != summ_ap)	    continue;	// Install reject route if self advertising	if (lsap->adv_rtr() == ospf->my_id()) {	    new_type = RT_REJECT;	    cost = LSInfinity;	    best_path = 0;	    break;	}	// Check that router is reachable	rtr = (RTRrte *) lsap->source;	if (!rtr || rtr->type() != RT_SPF)	    continue;	// And that a reachable cost is being advertised	if (lsap->adv_cost == LSInfinity)	    continue;	// Compare cost to current best	new_cost = lsap->adv_cost + rtr->cost;	if (new_type != RT_NONE ) {	    if (cost < new_cost)		continue;	    if (new_cost < cost)		best_path = 0;	}	// Install as current best cost	cost = new_cost;	new_type = RT_SPFIA;	best_path = MPath::merge(best_path, rtr->r_mpath);    }    // Delete old inter-area route?    if (new_type == RT_NONE &&	(r_type == RT_SPFIA || r_type == RT_REJECT)) {	declare_unreachable();	changed = true;	return;    }    else if (new_type == RT_NONE)	return;    else if (r_type != new_type)	changed = true;    else if (summ_ap->id() != area())	changed = true;    // Install inter-area route    // Maybe be overriden by "resolving virtual next hops"    update(best_path);    r_type = new_type;    tag = 0;    set_area(summ_ap->id());}/* Adjust existing backbone intra-area and inter-area routes to * compensate for the existence of transit areas (virtual * links). * Called after the Dijsktra and examination of the backbone's * summary-LSA, this routine finds any shorter routes through * transit areas, without changing the route's type or validity. * It is assumed that the caller has verified that * the route is an intra- or inter-area route associated with * the backbone area before even calling this routine. * Routine used for both type-3 and type 4 summary-LSAs. Given * the head of a singly linked list of LSAs pertaining * to the routing table entry. */void RTE::run_transit_areas(rteLSA *lsap){    // Go through list of summary-LSAs    for (; lsap; lsap = lsap->link) {	RTRrte *rtr;	uns32 new_cost;	if (!lsap->area()->is_transit())	    continue;	if (lsap->adv_rtr() == ospf->my_id())	    continue;	// Check that router is reachable	rtr = (RTRrte *) lsap->source;	if (!rtr || rtr->type() != RT_SPF)	    continue;	new_cost = lsap->adv_cost + rtr->cost;	if (cost < new_cost)	    continue;	else if (new_cost < cost)	    r_mpath = 0;	// Update routing table if better	// Install as current best cost	r_mpath = MPath::merge(r_mpath, rtr->r_mpath);	cost = new_cost;    }}

⌨️ 快捷键说明

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