📄 spfarea.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 implementing OSPF area support. * Includes adding interfaces to areas, adding area border * routers to areas, and the area constructor and destructor. */#include "ospfinc.h"#include "ifcfsm.h"#include "system.h"#include "nbrfsm.h"/* Constructor for an OSPF area. */SpfArea::SpfArea(aid_t area_no) : a_id(area_no){ a_stub = false; a_dfcst = 1; a_import = true; next = ospf->areas; ospf->areas = this; db_xsum = 0; wo_donotage = 0; dna_indications = 0; self_indicating = false; dna_change = false; mylsa = 0; a_ifcs = 0; n_active_if = 0; n_routers = 0; n_VLs = 0; a_transit = false; was_transit = false; ifmap = 0; ifmap_valid = true; sz_ifmap = 0; n_ifmap = 0; size_mospf_incoming = 0; mospf_in_phys = 0; mospf_in_count = 0; a_helping = 0; cancel_help_sessions = false;}/* Find an area data structure, given its Area ID. */SpfArea *OSPF::FindArea(aid_t id) const{ SpfArea *a; for (a = areas; a; a = a->next) if (a->a_id == id) break; return(a);}/* Find the area whose ID is next greatest. */SpfArea *OSPF::NextArea(aid_t & id) const{ SpfArea *a; SpfArea *best; for (a = areas, best = 0; a; a = a->next) { if (a->a_id <= id) continue; if (!best) best = a; else if (best->a_id > a->a_id) best = a; } if (best) id = best->a_id; return(best);}/* Add or modify a given area. * We don't bother to delete areas, as they are esentially * deleted when they lose all interfaces. * If an area's stub status has changed, then: * a) the area database must be deleted * b) all the interfaces to the area must be disabled. * The second action will automatically cause a new * router-LSA to be originated. * It may be that you shouldn't have any AS-externals in * your database anymore either, but these won't be used * in a stub area and will eventually age out. * When "import summaries" status changes, a Dijkstra is * forced in order to cause all summaries to be reexamined. */void OSPF::cfgArea(CfgArea *msg, int status){ SpfArea *ap; if (!(ap = ospf->FindArea(msg->area_id))) { ap = new SpfArea(msg->area_id); if (spflog(CFG_ADD_AREA, 5)) log(ap); } if (status == DELETE_ITEM) { delete ap; return; } if ((msg->stub != 0) != ap->a_stub) { ap->a_stub = (msg->stub != 0); ap->a_dfcst = msg->dflt_cost; ap->a_import = (msg->import_summs != 0); ap->reinitialize(); } else if (msg->stub != 0) { if ((msg->import_summs != 0) != ap->a_import) { ap->a_import = (msg->import_summs != 0); ap->a_dfcst = msg->dflt_cost; ap->generate_summaries(); } else if (msg->dflt_cost != ap->a_dfcst) { ap->a_dfcst = msg->dflt_cost; ap->sl_orig(default_route); } } ap->updated = true;}/* Transfer area parameters */static void area_to_cfg(const SpfArea& sa, struct CfgArea& msg){ msg.area_id = sa.id(); msg.stub = sa.is_stub(); msg.dflt_cost = sa.default_cost(); msg.import_summs = sa.import();}/* Query Area */bool OSPF::qryArea(struct CfgArea& msg, aid_t area_id) const{ SpfArea *ap; if (!(ap = ospf->FindArea(area_id))) { return false; } area_to_cfg(*ap, msg); return true;}/* Get all areas */void OSPF::getAreas(std::list<CfgArea>& l) const{ AreaIterator a_iter(ospf); SpfArea *ap; while ((ap = a_iter.get_next())) { CfgArea msg; area_to_cfg(*ap, msg); l.push_back(msg); }}/* Delete an area. */SpfArea::~SpfArea(){ IfcIterator if_iter(this); AVLsearch abr_iter(&abr_tbl); AVLsearch aggr_iter(&ranges); SpfIfc *ip; RTRrte *abr; Range *aggr; SpfArea *ptr; SpfArea **app; if (ospf->spflog(CFG_DEL_AREA, 5)) ospf->log(this); // Delete component interfaces while ((ip = if_iter.get_next())) delete ip; // Delete database delete_lsdb(); // Remove ABRs while ((abr = (RTRrte *) abr_iter.next())) { abr_tbl.remove(abr); delete abr; } // Remove area aggregates while ((aggr = (Range *) aggr_iter.next())) { ranges.remove(aggr); delete aggr; } // Delete iterface map delete [] ifmap; // Free associated packets ospf->ospf_freepkt(&a_update); ospf->ospf_freepkt(&a_demand_upd); // Delete area from global list for (app = &ospf->areas; (ptr = *app); app = &ptr->next) { if (ptr == this) { *app = next; break; } }}/* Area not mentioned explicitly in a reconfig. Delete (virtual * link simulates configuration). */void SpfArea::clear_config(){ delete this;}/* Remove an interface from an area. It is assumed that * the interface is already down, so that we don't have to adjust * the count of active interfaces to the area. */void SpfArea::RemoveIfc(class SpfIfc *ip){ SpfIfc **ipp; SpfIfc *ptr; if (ip->state() != IFS_DOWN) sys->halt(HALT_IFCRM, "Remove operational interface"); for (ipp = &a_ifcs; (ptr = *ipp) != 0; ipp = &ptr->anext) { if (ip == ptr) { *ipp = ptr->anext; break; } } // Delete from interface map ospf->delete_from_ifmap(ip);}/* An interface to the area has gone up or down. Adjust the * count of active interfaces, reoriginating summary-LSAs if * this is the first interface. If this is the last interface, * flush the entire area database. * * Also, recalculate the MTU values used for the area and * globally for OSPF, when flooding packets out all interfaces. */void SpfArea::IfcChange(int increment){ int oldifcs; SpfIfc *ip; IfcIterator *iiter; oldifcs = n_active_if; n_active_if += increment; ospf->calc_my_addr(); if (oldifcs == 0) ospf->n_area++; else if (n_active_if == 0) ospf->n_area--; // Area MTU calculation // and Global MTU calculation // and summary area assignment iiter = new IfcIterator(ospf); a_mtu = 0xffff; ospf->ospf_mtu = 0xffff; ospf->summary_area = 0; ospf->first_area = 0; while ((ip = iiter->get_next())) { if (ip->state() == IFS_DOWN) continue; if (ip->area() == this && ip->if_mtu < a_mtu) a_mtu = ip->if_mtu; if (ip->if_mtu < ospf->ospf_mtu) ospf->ospf_mtu = ip->if_mtu; if (ip->area()->id() == BACKBONE || ospf->n_area == 1) ospf->summary_area = ip->area(); if (ip->area()->n_active_if != 0 && ospf->first_area == 0) ospf->first_area = ip->area(); } delete iiter; if (oldifcs == 0) { ospf->rl_orig(); generate_summaries(); } else if (n_active_if == 0) { ospf->rl_orig(); delete_lsdb(); }}/* Generate all summary-LSAs into a given area. Either the * area has become newly attached, or the import policies * for the area have changed. */void SpfArea::generate_summaries(){ INrte *rte; INiterator iter(inrttbl); ASBRrte *rrte; while ((rte = iter.nextrte())) { if (rte->intra_AS()) sl_orig(rte); else if (rte->is_range()) sl_orig(rte); } // Originate ASBR-summary-LSAs for (rrte = ospf->ASBRs; rrte; rrte = rrte->next()) asbr_orig(rrte); // Originate default route into stub areas. if (a_stub) sl_orig(default_route);}/* Reinitialize OSPF support in a given area. * Disable all interfaces to the area. * Then flush all the area's LSAs. * Finally, reenable all interfaces that are physically * operational. */void SpfArea::reinitialize(){ SpfIfc *ip; IfcIterator iter(this); // Take down interfaces to area while ((ip = iter.get_next())) ip->run_fsm(IFE_DOWN); // Delete entire link-state database delete_lsdb(); // Bring up interfaces that are physically operational // This will re-create the area's link-state database iter.reset(); while ((ip = iter.get_next())) { if (sys->phy_operational(ip->if_phyint)) ip->run_fsm(IFE_UP); }}/* Add and area border router to the area. If * one exists, simply return it. Otherwise, allocate one * and add it to the area class. * * Always add the area border routers to an ASBR entry, even * if the router is NOT and ASBR. */RTRrte *SpfArea::add_abr(uns32 rtrid){ RTRrte *rte; ASBRrte *asbr; if ((rte = (RTRrte *) abr_tbl.find(rtrid))) return(rte); rte = new RTRrte(rtrid, this); abr_tbl.add(rte); // Add to ASBR entry asbr = ospf->add_asbr(rtrid); rte->asbr_link = asbr->parts; asbr->parts = rte; rte->asbr = asbr; return(rte);}/* Constructor for the area border router class. */RTRrte::RTRrte(uns32 id, SpfArea *a) : RTE(id, 0)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -