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

📄 ospf_abr.c

📁 router source code for the ospdf.
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * OSPF ABR functions. * Copyright (C) 1999, 2000 Alex Zinin, Toshiaki Takada * * This file is part of GNU Zebra. * * GNU Zebra 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, or (at your option) any * later version. *  * GNU Zebra 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 GNU Zebra; see the file COPYING.  If not, write to the Free * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. */#include <zebra.h>#include "thread.h"#include "memory.h"#include "linklist.h"#include "prefix.h"#include "if.h"#include "table.h"#include "vty.h"#include "filter.h"#include "plist.h"#include "log.h"#include "ospfd/ospfd.h"#include "ospfd/ospf_interface.h"#include "ospfd/ospf_ism.h"#include "ospfd/ospf_asbr.h"#include "ospfd/ospf_lsa.h"#include "ospfd/ospf_lsdb.h"#include "ospfd/ospf_neighbor.h"#include "ospfd/ospf_nsm.h"#include "ospfd/ospf_spf.h"#include "ospfd/ospf_route.h"#include "ospfd/ospf_ia.h"#include "ospfd/ospf_flood.h"#include "ospfd/ospf_abr.h"#include "ospfd/ospf_ase.h"#include "ospfd/ospf_zebra.h"#include "ospfd/ospf_dump.h"struct ospf_area_range *ospf_area_range_new (struct prefix_ipv4 *p){  struct ospf_area_range *range;  range = XCALLOC (MTYPE_OSPF_AREA_RANGE, sizeof (struct ospf_area_range));  range->addr = p->prefix;  range->masklen = p->prefixlen;  range->cost_config = OSPF_AREA_RANGE_COST_UNSPEC;  return range;}voidospf_area_range_free (struct ospf_area_range *range){  XFREE (MTYPE_OSPF_AREA_RANGE, range);}voidospf_area_range_add (struct ospf_area *area, struct ospf_area_range *range){  struct route_node *rn;  struct prefix_ipv4 p;  p.family = AF_INET;  p.prefixlen = range->masklen;  p.prefix = range->addr;  rn = route_node_get (area->ranges, (struct prefix *)&p);  if (rn->info)    route_unlock_node (rn);  else    rn->info = range;}voidospf_area_range_delete (struct ospf_area *area, struct ospf_area_range *range){  struct route_node *rn;  struct prefix_ipv4 p;  p.family = AF_INET;  p.prefixlen = range->masklen;  p.prefix = range->addr;  rn = route_node_lookup (area->ranges, (struct prefix *)&p);  if (rn)    {      ospf_area_range_free (rn->info);      rn->info = NULL;      route_unlock_node (rn);      route_unlock_node (rn);    }}struct ospf_area_range *ospf_area_range_lookup (struct ospf_area *area, struct prefix_ipv4 *p){  struct route_node *rn;  rn = route_node_lookup (area->ranges, (struct prefix *)p);  if (rn)    {      route_unlock_node (rn);      return rn->info;    }  return NULL;}struct ospf_area_range *ospf_area_range_lookup_next (struct ospf_area *area, struct in_addr *range_net,			     int first){  struct route_node *rn;  struct prefix_ipv4 p;  struct ospf_area_range *find;  p.family = AF_INET;  p.prefixlen = IPV4_MAX_BITLEN;  p.prefix = *range_net;  if (first)    rn = route_top (area->ranges);  else    {      rn = route_node_get (area->ranges, (struct prefix *) &p);      rn = route_next (rn);    }  for (; rn; rn = route_next (rn))    if (rn->info)      break;  if (rn && rn->info)    {      find = rn->info;      *range_net = rn->p.u.prefix4;      route_unlock_node (rn);      return find;    }  return NULL;}struct ospf_area_range *ospf_area_range_match (struct ospf_area *area, struct prefix_ipv4 *p){  struct route_node *node;  node = route_node_match (area->ranges, (struct prefix *) p);  if (node)    {      route_unlock_node (node);      return node->info;    }  return NULL;}struct ospf_area_range *ospf_area_range_match_any (struct ospf *ospf, struct prefix_ipv4 *p){  struct ospf_area_range *range;  listnode node;  for (node = listhead (ospf->areas); node; nextnode (node))    if ((range = ospf_area_range_match (node->data, p)))      return range;  return NULL;}intospf_area_range_active (struct ospf_area_range *range){  return range->specifics;}intospf_area_actively_attached (struct ospf_area *area){  return area->act_ints;}intospf_area_range_set (struct ospf *ospf, struct in_addr area_id,		     struct prefix_ipv4 *p, int advertise){  struct ospf_area *area;  struct ospf_area_range *range;  int ret = OSPF_AREA_ID_FORMAT_ADDRESS;  area = ospf_area_get (ospf, area_id, ret);  if (area == NULL)    return 0;  range = ospf_area_range_lookup (area, p);  if (range != NULL)    {      if ((CHECK_FLAG (range->flags, OSPF_AREA_RANGE_ADVERTISE)	   && !CHECK_FLAG (advertise, OSPF_AREA_RANGE_ADVERTISE))	  || (!CHECK_FLAG (range->flags, OSPF_AREA_RANGE_ADVERTISE)	      && CHECK_FLAG (advertise, OSPF_AREA_RANGE_ADVERTISE)))	ospf_schedule_abr_task (ospf);    }  else    {      range = ospf_area_range_new (p);      ospf_area_range_add (area, range);      ospf_schedule_abr_task (ospf);    }  if (CHECK_FLAG (advertise, OSPF_AREA_RANGE_ADVERTISE))    SET_FLAG (range->flags, OSPF_AREA_RANGE_ADVERTISE);  else    UNSET_FLAG (range->flags, OSPF_AREA_RANGE_ADVERTISE);  return 1;}intospf_area_range_cost_set (struct ospf *ospf, struct in_addr area_id,			  struct prefix_ipv4 *p, u_int32_t cost){  struct ospf_area *area;  struct ospf_area_range *range;  int ret = OSPF_AREA_ID_FORMAT_ADDRESS;  area = ospf_area_get (ospf, area_id, ret);  if (area == NULL)    return 0;  range = ospf_area_range_new (p);  if (range == NULL)    return 0;  if (range->cost_config != cost)    {      range->cost_config = cost;      if (ospf_area_range_active (range))	ospf_schedule_abr_task (ospf);    }  return 1;}intospf_area_range_unset (struct ospf *ospf, struct in_addr area_id,		       struct prefix_ipv4 *p){  struct ospf_area *area;  struct ospf_area_range *range;  area = ospf_area_lookup_by_area_id (ospf, area_id);  if (area == NULL)    return 0;  range = ospf_area_range_lookup (area, p);  if (range == NULL)    return 0;  if (ospf_area_range_active (range))    ospf_schedule_abr_task (ospf);  ospf_area_range_delete (area, range);  return 1;}intospf_area_range_substitute_set (struct ospf *ospf, struct in_addr area_id,				struct prefix_ipv4 *p, struct prefix_ipv4 *s){  struct ospf_area *area;  struct ospf_area_range *range;  int ret = OSPF_AREA_ID_FORMAT_ADDRESS;  area = ospf_area_get (ospf, area_id, ret);  range = ospf_area_range_lookup (area, p);  if (range != NULL)    {      if (!CHECK_FLAG (range->flags, OSPF_AREA_RANGE_ADVERTISE) ||	  !CHECK_FLAG (range->flags, OSPF_AREA_RANGE_SUBSTITUTE))	ospf_schedule_abr_task (ospf);    }  else    {      range = ospf_area_range_new (p);      ospf_area_range_add (area, range);      ospf_schedule_abr_task (ospf);    }  SET_FLAG (range->flags, OSPF_AREA_RANGE_ADVERTISE);  SET_FLAG (range->flags, OSPF_AREA_RANGE_SUBSTITUTE);  range->subst_addr = s->prefix;  range->subst_masklen = s->prefixlen;  return 1;}intospf_area_range_substitute_unset (struct ospf *ospf, struct in_addr area_id,				  struct prefix_ipv4 *p){  struct ospf_area *area;  struct ospf_area_range *range;  area = ospf_area_lookup_by_area_id (ospf, area_id);  if (area == NULL)    return 0;  range = ospf_area_range_lookup (area, p);  if (range == NULL)    return 0;  if (CHECK_FLAG (range->flags, OSPF_AREA_RANGE_SUBSTITUTE))    if (ospf_area_range_active (range))      ospf_schedule_abr_task (ospf);  UNSET_FLAG (range->flags, OSPF_AREA_RANGE_SUBSTITUTE);  range->subst_addr.s_addr = 0;  range->subst_masklen = 0;  return 1;}intospf_act_bb_connection (struct ospf *ospf){  if (ospf->backbone == NULL)    return 0;  return ospf->backbone->full_nbrs;}/* Check area border router status. */voidospf_check_abr_status (struct ospf *ospf){  struct ospf_area *area;  listnode node;  int bb_configured = 0;  int bb_act_attached = 0;  int areas_configured = 0;  int areas_act_attached = 0;  u_char new_flags = ospf->flags;  if (IS_DEBUG_OSPF_EVENT)    zlog_info ("ospf_check_abr_status(): Start");  for (node = listhead (ospf->areas); node; nextnode (node))    {      area = getdata (node);      if (listcount (area->oiflist)) 	{	  areas_configured++;	  	  if (OSPF_IS_AREA_BACKBONE (area)) 	    bb_configured = 1;	}      if (ospf_area_actively_attached (area))	{	  areas_act_attached++;	  	  if (OSPF_IS_AREA_BACKBONE (area))            bb_act_attached = 1;	}    }  if (IS_DEBUG_OSPF_EVENT)    {      zlog_info ("ospf_check_abr_status(): looked through areas");      zlog_info ("ospf_check_abr_status(): bb_configured: %d", bb_configured);      zlog_info ("ospf_check_abr_status(): bb_act_attached: %d",		 bb_act_attached);      zlog_info ("ospf_check_abr_status(): areas_configured: %d",		 areas_configured);      zlog_info ("ospf_check_abr_status(): areas_act_attached: %d",		 areas_act_attached);    }  switch (ospf->abr_type)    {    case OSPF_ABR_SHORTCUT:    case OSPF_ABR_STAND:      if (areas_act_attached > 1)	SET_FLAG (new_flags, OSPF_FLAG_ABR);      else	UNSET_FLAG (new_flags, OSPF_FLAG_ABR);      break;    case OSPF_ABR_IBM:      if ((areas_act_attached > 1) && bb_configured)	SET_FLAG (new_flags, OSPF_FLAG_ABR);      else	UNSET_FLAG (new_flags, OSPF_FLAG_ABR);      break;    case OSPF_ABR_CISCO:      if ((areas_configured > 1) && bb_act_attached)	SET_FLAG (new_flags, OSPF_FLAG_ABR);      else	UNSET_FLAG (new_flags, OSPF_FLAG_ABR);      break;    default:      break;    }  if (new_flags != ospf->flags)    {      ospf_spf_calculate_schedule (ospf);      if (IS_DEBUG_OSPF_EVENT)	zlog_info ("ospf_check_abr_status(): new router flags: %x",new_flags);      ospf->flags = new_flags;      OSPF_TIMER_ON (ospf->t_router_lsa_update,		     ospf_router_lsa_update_timer, OSPF_LSA_UPDATE_DELAY);    }}voidospf_abr_update_aggregate (struct ospf_area_range *range,			   struct ospf_route *or){  if (IS_DEBUG_OSPF_EVENT)    zlog_info ("ospf_abr_update_aggregate(): Start");  if (range->cost_config != -1)    {      if (IS_DEBUG_OSPF_EVENT)	zlog_info ("ospf_abr_update_aggregate(): use configured cost %d",		   range->cost_config);      range->cost = range->cost_config;    }  else    {      if (range->specifics == 0)	range->cost = or->cost; /* 1st time get 1st cost */      if (or->cost < range->cost)	{	  if (IS_DEBUG_OSPF_EVENT)	    zlog_info ("ospf_abr_update_aggregate(): lowest cost, update");	  range->cost = or->cost;	}    }  range->specifics++;}static voidset_metric (struct ospf_lsa *lsa, u_int32_t metric){  struct summary_lsa *header;  u_char *mp;  metric = htonl (metric);  mp = (char *) &metric;  mp++;  header = (struct summary_lsa *) lsa->data;  memcpy(header->metric, mp, 3);}#ifdef HAVE_NSSAintospf_abr_check_nssa_range (struct prefix_ipv4 *p, u_int32_t cost,			   struct ospf_area *area){  /* The Type-7 is tested against the aggregated prefix and forwarded     for lsa installation and flooding */  return 0;}/* ospf_abr_translate_nssa */intospf_abr_translate_nssa (struct ospf_area *area, struct ospf_lsa *lsa){  /* Incoming Type-7 or later aggregated Type-7   LSA is skipped if P-bit is off.  LSA is aggregated if within range.  The Type-7 is translated, Installed/Approved as a Type-5 into  global LSDB, then Flooded through AS  Later, any Unapproved Translated Type-5's are flushed/discarded */  struct ospf_lsa *dup;  if (! CHECK_FLAG (lsa->data->options, OSPF_OPTION_NP))    {      if (IS_DEBUG_OSPF_NSSA)	zlog_info ("ospf_abr_nssa(): P-bit off, NO Translation");      return 0;     }  if (IS_DEBUG_OSPF_NSSA)    zlog_info ("ospf_abr_nssa(): TRANSLATING 7 to 5");  /* No more P-bit. */  /* UNSET_FLAG (lsa->data->options, OSPF_OPTION_NP); */  /* Area where Aggregate testing will be inserted, just like summary     advertisements */  /* ospf_abr_check_nssa_range (p_arg, lsa-> cost, lsa -> area); */  /* Follow thru here means no aggregation */  dup = ospf_lsa_dup (lsa);	/* keep LSDB intact, lock = 1 */  SET_FLAG (dup->flags, OSPF_LSA_LOCAL_XLT); /* Translated from 7  */  SET_FLAG (dup->flags, OSPF_LSA_APPROVED); /* So, do not remove it */  dup->data->type = OSPF_AS_EXTERNAL_LSA;  /* make Type-5 */  ospf_lsa_checksum (dup->data);  ospf_lsa_install (area->ospf, NULL, dup);  /* Install this Type-5 into LSDB, Lock = 2. */  ospf_flood_through_as (area->ospf, NULL, dup); /* flood non-NSSA/STUB areas */    /* This translated Type-5 will go to all non-NSSA areas connected to     this ABR; The Type-5 could come from any of the NSSA's connected     to this ABR.  */  return 0;}voidospf_abr_translate_nssa_range (struct prefix_ipv4 *p, u_int32_t cost){  /* The Type-7 is created from the aggregated prefix and forwarded     for lsa installation and flooding... to be added... */}#endif /* HAVE_NSSA */voidospf_abr_announce_network_to_area (struct prefix_ipv4 *p, u_int32_t cost,				   struct ospf_area *area){  struct ospf_lsa *lsa, *old = NULL;  struct summary_lsa *sl = NULL;  if (IS_DEBUG_OSPF_EVENT)    zlog_info ("ospf_abr_announce_network_to_area(): Start");  old = ospf_lsa_lookup_by_prefix (area->lsdb, OSPF_SUMMARY_LSA, p,				   area->ospf->router_id);  if (old)    {      if (IS_DEBUG_OSPF_EVENT)	zlog_info ("ospf_abr_announce_network_to_area(): old summary found");      sl = (struct summary_lsa *) old->data;      if (IS_DEBUG_OSPF_EVENT)	zlog_info ("ospf_abr_announce_network_to_area(): "		   "old metric: %d, new metric: %d",		   GET_METRIC (sl->metric), cost);    }  if (old && (GET_METRIC (sl->metric) == cost))    {

⌨️ 快捷键说明

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