📄 rtrlsa.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 the origination, parsing and unparsing * of router-LSAs. */#include "ospfinc.h"#include "ifcfsm.h"#include "nbrfsm.h"/* Constructor for a router-LSA. */rtrLSA::rtrLSA(SpfArea *a, LShdr *hdr, int blen) : TNode(a, hdr, blen){ rtype = 0;}/* Maximum number of bytes added to a router-LSA by a * single interface. Overloaded when interface type is * point-to-point or point-to-multipoint. */int SpfIfc::rl_size(){ return(sizeof(RtrLink));}// Insert information concerning a virtual link into the// router-LSARtrLink *VLIfc::rl_insert(RTRhdr *rtrhdr, RtrLink *rlp){ SpfNbr *np; if ((np = if_nlst) && np->adv_as_full()) { rlp->link_id = hton32(np->id()); rlp->link_data = hton32(if_addr); rlp->link_type = LT_VL; rlp->n_tos = 0; rlp->metric = hton16(if_cost); if_area->add_to_ifmap(this); rlp++; rtrhdr->nlinks++; } return(rlp);}/* Insert information concerning a broadcast or NBMA interface * into a router-LSA * if_nfull includes all those neighbors that we * are currently helping through hitless restart. */RtrLink *DRIfc::rl_insert(RTRhdr *rtrhdr, RtrLink *rlp){ if ((if_state == IFS_DR && if_nfull > 0) || ((if_state == IFS_BACKUP || if_state == IFS_OTHER) && (if_dr_p && if_dr_p->adv_as_full()))) { rlp->link_id = hton32(if_dr); rlp->link_data = hton32(if_addr); rlp->link_type = LT_TNET; rlp->n_tos = 0; rlp->metric = hton16(if_cost); if_area->add_to_ifmap(this); rlp++; rtrhdr->nlinks++; } else { rlp->link_id = hton32(if_net); rlp->link_data = hton32(if_mask); rlp->link_type = LT_STUB; rlp->n_tos = 0; rlp->metric = hton16(if_cost); if_area->add_to_ifmap(this); rlp++; rtrhdr->nlinks++; } return(rlp);}// Maximum size added by point-to-point linkint PPIfc::rl_size(){ return(2 * sizeof(RtrLink));}/* How we advertise a point-to-point link's addresses depends * on the interface mask. If set to all ones (0xffffffff) or 0, we * do the traditional thing of advertising the neighbor's * address. If instead the mask is set to something else, we * advertise a route to the entire subnet. */RtrLink *PPIfc::rl_insert(RTRhdr *rtrhdr, RtrLink *rlp){ SpfNbr *np; if ((np = if_nlst) && np->adv_as_full()) { PPAdjAggr *adjaggr; uns16 adv_cost; adv_cost = if_cost; adjaggr = (PPAdjAggr *)if_area->AdjAggr.find(np->id(), 0); if (adjaggr && adjaggr->first_full) { if (adjaggr->first_full != this) goto adv_stub; adv_cost = adjaggr->nbr_cost; } rlp->link_id = hton32(np->id()); rlp->link_data = hton32(unnumbered() ? if_IfIndex : if_addr); rlp->link_type = LT_PP; rlp->n_tos = 0; rlp->metric = hton16(adv_cost); if_area->add_to_ifmap(this); rlp++; rtrhdr->nlinks++; } adv_stub: // Advertise stub link to neighbor's IP address if (state() == IFS_PP && !unnumbered() && (np || (if_mask != 0xffffffffL && if_mask != 0))) { if (if_mask != 0xffffffffL && if_mask != 0) { rlp->link_id = hton32(if_net); rlp->link_data = hton32(if_mask); } else { rlp->link_id = hton32(np->addr()); rlp->link_data = hton32(0xffffffffL); } rlp->link_type = LT_STUB; rlp->n_tos = 0; rlp->metric = hton16(if_cost); if_area->add_to_ifmap(this); rlp++; rtrhdr->nlinks++; } return(rlp);}// Maximum size added by Point-to-MultiPoint interfaceint P2mPIfc::rl_size(){ return((if_nnbrs+1) * sizeof(RtrLink));}RtrLink *P2mPIfc::rl_insert(RTRhdr *rtrhdr, RtrLink *rlp){ NbrIterator iter(this); SpfNbr *np; // Add stub link for interface address rlp->link_id = hton32(if_addr); rlp->link_data = hton32(0xffffffffL); rlp->link_type = LT_STUB; rlp->n_tos = 0; rlp->metric = hton16(0); if_area->add_to_ifmap(this); rlp++; rtrhdr->nlinks++; // Then add link for each FULL neighbor while ((np = iter.get_next())) { if (!np->adv_as_full()) continue; rlp->link_id = hton32(np->id()); rlp->link_data = hton32(if_addr); rlp->link_type = LT_PP; rlp->n_tos = 0; rlp->metric = hton16(if_cost); if_area->add_to_ifmap(this); rlp++; rtrhdr->nlinks++; } return(rlp);}/* Build the router-LSAs of all areas at once. This is * done when, for example, our area border router or * ASBR status changes. We laso check whether we now * want to originate default routes into stub areas, * as that logic also needs to be performed when area * border router status changes. */void OSPF::rl_orig(){ AreaIterator iter(this); SpfArea *ap; while ((ap = iter.get_next())) { ap->rl_orig(false); if (ap->a_stub) ap->sl_orig(default_route); }}/* Build a router LSA. First estimate how big the router-LSA * will be, to verify that we have enough space in the * temporary build area. * * Keep a map of links in our own router-LSA to interfaces (ifmap), * for later use in the Dijkstra calculation. */void SpfArea::rl_orig(int forced){ LSA *olsap; LShdr *hdr; RTRhdr *rtrhdr; int maxlen; int maxifc; int length; SpfIfc *ip; IfcIterator iiter(this); seq_t seqno; RtrLink *rlp; // If in hitless restart, queue exit check if (ospf->in_hitless_restart()) ospf->check_htl_termination = true; // Current LSA in database olsap = ospf->myLSA(0, this, LST_RTR, ospf->my_id()); // Calculate maximum size for LSA maxlen = sizeof(LShdr) + sizeof(RTRhdr); while ((ip = iiter.get_next())) maxlen += ip->rl_size(); // Add in host records maxlen += hosts.size() * sizeof(RtrLink); // If first active area, advertise orphaned hosts if (this == ospf->first_area) { AreaIterator aiter(ospf); SpfArea *ap; while ((ap = aiter.get_next())) { if (ap->n_active_if == 0) maxlen += ap->hosts.size() * sizeof(RtrLink); } } // Get sequence number to originate with seqno = ospf->ospf_get_seqno(LST_RTR, olsap, forced); if (seqno == InvalidLSSeq) return; // Convert bytes to number of links, to make sure // we have enough room to store interface map maxifc = maxlen/sizeof(RtrLink); if (maxifc > sz_ifmap) { delete [] ifmap; ifmap = new SpfIfc* [maxifc]; sz_ifmap = maxifc; } // Start with empty interface map n_ifmap = 0; ifmap_valid = true; // Build LSA header hdr = ospf->orig_buffer(maxlen); hdr->ls_opts = SPO_DC; if (!a_stub) hdr->ls_opts |= SPO_EXT; if (ospf->mospf_enabled()) hdr->ls_opts |= SPO_MC; hdr->ls_type = LST_RTR; hdr->ls_id = hton32(ospf->my_id()); hdr->ls_org = hton32(ospf->my_id()); hdr->ls_seqno = (seq_t) hton32((uns32) seqno); // Router-LSA specific portion rtrhdr = (RTRhdr *) (hdr+1); rtrhdr->rtype = 0; if (ospf->n_area > 1) rtrhdr->rtype |= RTYPE_B; if (ospf->n_extImports != 0) rtrhdr->rtype |= RTYPE_E; if (n_VLs > 0) rtrhdr->rtype |= RTYPE_V; if (ospf->mospf_enabled()) { if (a_id != 0 && ospf->mc_abr()) rtrhdr->rtype |= RTYPE_W; else if (ospf->inter_AS_mc) rtrhdr->rtype |= RTYPE_W; } rtrhdr->zero = 0; rtrhdr->nlinks = 0; // Build body of router-LSA rlp = (RtrLink *) (rtrhdr+1); iiter.reset(); while ((ip = iiter.get_next())) { if (ip->state() == IFS_DOWN) continue; else if (ip->state() == IFS_LOOP) { rlp->link_id = hton32(ip->if_addr); rlp->link_data = hton32(0xffffffffL); rlp->link_type = LT_STUB; rlp->n_tos = 0; rlp->metric = hton16(ip->cost()); add_to_ifmap(ip); rlp++; rtrhdr->nlinks++; } else rlp = ip->rl_insert(rtrhdr, rlp); } // Add area's host routes if (n_active_if != 0) rlp = rl_insert_hosts(this, rtrhdr, rlp); /* If no active interfaces to area, just flush * LSA. Host addresses will get added to other areas * automatically. */ if (rtrhdr->nlinks == 0) { lsa_flush(olsap); delete [] ifmap; ifmap = 0; sz_ifmap = 0; ospf->free_orig_buffer(hdr); return; } // If first active area, advertise orphaned hosts if (this == ospf->first_area) { AreaIterator aiter(ospf);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -