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

📄 ospf_ism.c

📁 router source code for the ospdf.
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * OSPF version 2  Interface State Machine *   From RFC2328 [OSPF Version 2]  * Copyright (C) 1999, 2000 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 "linklist.h"#include "prefix.h"#include "if.h"#include "table.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_network.h"#include "ospfd/ospf_dump.h"#include "ospfd/ospf_packet.h"#include "ospfd/ospf_flood.h"#include "ospfd/ospf_abr.h"/* elect DR and BDR. Refer to RFC2319 section 9.4 */struct ospf_neighbor *ospf_dr_election_sub (list routers){  listnode node;  struct ospf_neighbor *nbr, *max = NULL;  /* Choose highest router priority.     In case of tie, choose highest Router ID. */  for (node = listhead (routers); node; nextnode (node))    {      nbr = getdata (node);      if (max == NULL)	max = nbr;      else	{	  if (max->priority < nbr->priority)	    max = nbr;	  else if (max->priority == nbr->priority)	    if (IPV4_ADDR_CMP (&max->router_id, &nbr->router_id) < 0)	      max = nbr;	}    }  return max;}struct ospf_neighbor *ospf_elect_dr (struct ospf_interface *oi, list el_list){  list dr_list;  listnode node;  struct ospf_neighbor *nbr, *dr = NULL, *bdr = NULL;  dr_list = list_new ();  /* Add neighbors to the list. */  for (node = listhead (el_list); node; nextnode (node))    {      nbr = getdata (node);      /* neighbor declared to be DR. */      if (NBR_IS_DR (nbr))	listnode_add (dr_list, nbr);      /* Preserve neighbor BDR. */      if (IPV4_ADDR_SAME (&BDR (oi), &nbr->address.u.prefix4))	bdr = nbr;    }  /* Elect Designated Router. */  if (listcount (dr_list) > 0)    dr = ospf_dr_election_sub (dr_list);  else    dr = bdr;  /* Set DR to interface. */  if (dr)    {      DR (oi) = dr->address.u.prefix4;      dr->d_router = dr->address.u.prefix4;    }  else      DR (oi).s_addr = 0;  list_delete (dr_list);  return dr;}struct ospf_neighbor *ospf_elect_bdr (struct ospf_interface *oi, list el_list){  list bdr_list, no_dr_list;  listnode node;  struct ospf_neighbor *nbr, *bdr = NULL;  bdr_list = list_new ();  no_dr_list = list_new ();  /* Add neighbors to the list. */  for (node = listhead (el_list); node; nextnode (node))    {      nbr = getdata (node);      /* neighbor declared to be DR. */      if (NBR_IS_DR (nbr))	continue;      /* neighbor declared to be BDR. */      if (NBR_IS_BDR (nbr))	listnode_add (bdr_list, nbr);      listnode_add (no_dr_list, nbr);    }  /* Elect Backup Designated Router. */  if (listcount (bdr_list) > 0)    bdr = ospf_dr_election_sub (bdr_list);  else    bdr = ospf_dr_election_sub (no_dr_list);  /* Set BDR to interface. */  if (bdr)    {      BDR (oi) = bdr->address.u.prefix4;      bdr->bd_router = bdr->address.u.prefix4;    }  else    BDR (oi).s_addr = 0;  list_delete (bdr_list);  list_delete (no_dr_list);  return bdr;}intospf_ism_state (struct ospf_interface *oi){  if (IPV4_ADDR_SAME (&DR (oi), &oi->address->u.prefix4))    return ISM_DR;  else if (IPV4_ADDR_SAME (&BDR (oi), &oi->address->u.prefix4))    return ISM_Backup;  else    return ISM_DROther;}voidospf_dr_eligible_routers (struct route_table *nbrs, list el_list){  struct route_node *rn;  struct ospf_neighbor *nbr;  for (rn = route_top (nbrs); rn; rn = route_next (rn))    if ((nbr = rn->info) != NULL)      /* Ignore 0.0.0.0 node*/      if (nbr->router_id.s_addr != 0)	/* Is neighbor eligible? */	if (nbr->priority != 0)	  /* Is neighbor upper 2-Way? */	  if (nbr->state >= NSM_TwoWay)	    listnode_add (el_list, nbr);}/* Generate AdjOK? NSM event. */voidospf_dr_change (struct ospf *ospf, struct route_table *nbrs){  struct route_node *rn;  struct ospf_neighbor *nbr;  for (rn = route_top (nbrs); rn; rn = route_next (rn))    if ((nbr = rn->info) != NULL)      /* Ignore 0.0.0.0 node*/      if (nbr->router_id.s_addr != 0)	/* Is neighbor upper 2-Way? */	if (nbr->state >= NSM_TwoWay)	  /* Ignore myself. */	  if (!IPV4_ADDR_SAME (&nbr->router_id, &ospf->router_id))	    OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_AdjOK);}intospf_dr_election (struct ospf_interface *oi){  struct in_addr old_dr, old_bdr;  int old_state, new_state;  list el_list;  struct ospf_neighbor *dr, *bdr;  /* backup current values. */  old_dr = DR (oi);  old_bdr = BDR (oi);  old_state = oi->state;  el_list = list_new ();  /* List eligible routers. */  ospf_dr_eligible_routers (oi->nbrs, el_list);  /* First election of DR and BDR. */  bdr = ospf_elect_bdr (oi, el_list);  dr = ospf_elect_dr (oi, el_list);  new_state = ospf_ism_state (oi);  zlog_info ("DR-Election[1st]: Backup %s", inet_ntoa (BDR (oi)));  zlog_info ("DR-Election[1st]: DR     %s", inet_ntoa (DR (oi)));  if (new_state != old_state &&      !(new_state == ISM_DROther && old_state < ISM_DROther))    {      ospf_elect_bdr (oi, el_list);      ospf_elect_dr (oi, el_list);       new_state = ospf_ism_state (oi);      zlog_info ("DR-Election[2nd]: Backup %s", inet_ntoa (BDR (oi)));      zlog_info ("DR-Election[2nd]: DR     %s", inet_ntoa (DR (oi)));    }  list_delete (el_list);  /* if DR or BDR changes, cause AdjOK? neighbor event. */  if (!IPV4_ADDR_SAME (&old_dr, &DR (oi)) ||      !IPV4_ADDR_SAME (&old_bdr, &BDR (oi)))    ospf_dr_change (oi->ospf, oi->nbrs);  if (oi->type == OSPF_IFTYPE_BROADCAST || oi->type == OSPF_IFTYPE_POINTOPOINT)    {      /* Multicast group change. */      if ((old_state != ISM_DR && old_state != ISM_Backup) &&	  (new_state == ISM_DR || new_state == ISM_Backup))	ospf_if_add_alldrouters (oi->ospf, oi->address, oi->ifp->ifindex);      else if ((old_state == ISM_DR || old_state == ISM_Backup) &&	       (new_state != ISM_DR && new_state != ISM_Backup))	ospf_if_drop_alldrouters (oi->ospf, oi->address, oi->ifp->ifindex);    }  return new_state;}intospf_hello_timer (struct thread *thread){  struct ospf_interface *oi;  oi = THREAD_ARG (thread);  oi->t_hello = NULL;  if (IS_DEBUG_OSPF (ism, ISM_TIMERS))    zlog (NULL, LOG_DEBUG, "ISM[%s]: Timer (Hello timer expire)",	  IF_NAME (oi));  /* Sending hello packet. */  ospf_hello_send (oi);  /* Hello timer set. */  OSPF_ISM_TIMER_ON (oi->t_hello, ospf_hello_timer,		     OSPF_IF_PARAM (oi, v_hello));  return 0;}intospf_wait_timer (struct thread *thread){  struct ospf_interface *oi;  oi = THREAD_ARG (thread);  oi->t_wait = NULL;  if (IS_DEBUG_OSPF (ism, ISM_TIMERS))    zlog (NULL, LOG_DEBUG, "ISM[%s]: Timer (Wait timer expire)",	  IF_NAME (oi));  OSPF_ISM_EVENT_SCHEDULE (oi, ISM_WaitTimer);  return 0;}/* Hook function called after ospf ISM event is occured. And vty's   network command invoke this function after making interface   structure. */voidism_timer_set (struct ospf_interface *oi){  switch (oi->state)    {    case ISM_Down:      /* First entry point of ospf interface state machine. In this state	 interface parameters must be set to initial values, and timers are	 reset also. */      OSPF_ISM_TIMER_OFF (oi->t_hello);      OSPF_ISM_TIMER_OFF (oi->t_wait);      OSPF_ISM_TIMER_OFF (oi->t_ls_ack);      break;    case ISM_Loopback:      /* In this state, the interface may be looped back and will be	 unavailable for regular data traffic. */      OSPF_ISM_TIMER_OFF (oi->t_hello);

⌨️ 快捷键说明

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