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

📄 ospf6_interface.c

📁 linux 路由软件 可支持RIP OSPF BGP等
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (C) 2003 Yasuhiro Ohara * * 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 "memory.h"#include "if.h"#include "log.h"#include "command.h"#include "thread.h"#include "prefix.h"#include "plist.h"#include "ospf6_lsa.h"#include "ospf6_lsdb.h"#include "ospf6_network.h"#include "ospf6_message.h"#include "ospf6_route.h"#include "ospf6_top.h"#include "ospf6_area.h"#include "ospf6_interface.h"#include "ospf6_neighbor.h"#include "ospf6_intra.h"#include "ospf6_spf.h"#include "ospf6d.h"unsigned char conf_debug_ospf6_interface = 0;char *ospf6_interface_state_str[] ={  "None",  "Down",  "Loopback",  "Waiting",  "PointToPoint",  "DROther",  "BDR",  "DR",  NULL};struct ospf6_interface *ospf6_interface_lookup_by_ifindex (int ifindex){  struct ospf6_interface *oi;  struct interface *ifp;  ifp = if_lookup_by_index (ifindex);  if (ifp == NULL)    return (struct ospf6_interface *) NULL;  oi = (struct ospf6_interface *) ifp->info;  return oi;}struct ospf6_interface *ospf6_interface_lookup_by_name (char *ifname){  struct ospf6_interface *oi;  struct interface *ifp;  ifp = if_lookup_by_name (ifname);  if (ifp == NULL)    return (struct ospf6_interface *) NULL;  oi = (struct ospf6_interface *) ifp->info;  return oi;}/* schedule routing table recalculation */voidospf6_interface_lsdb_hook (struct ospf6_lsa *lsa){  switch (ntohs (lsa->header->type))    {      case OSPF6_LSTYPE_LINK:        if (OSPF6_INTERFACE (lsa->lsdb->data)->state == OSPF6_INTERFACE_DR)          OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT (OSPF6_INTERFACE (lsa->lsdb->data));        ospf6_spf_schedule (OSPF6_INTERFACE (lsa->lsdb->data)->area);        break;      default:        break;    }}/* Create new ospf6 interface structure */struct ospf6_interface *ospf6_interface_create (struct interface *ifp){  struct ospf6_interface *oi;  int iobuflen;  oi = (struct ospf6_interface *)    XMALLOC (MTYPE_OSPF6_IF, sizeof (struct ospf6_interface));  if (oi)    memset (oi, 0, sizeof (struct ospf6_interface));  else    {      zlog_err ("Can't malloc ospf6_interface for ifindex %d", ifp->ifindex);      return (struct ospf6_interface *) NULL;    }  oi->area = (struct ospf6_area *) NULL;  oi->neighbor_list = list_new ();  oi->neighbor_list->cmp = ospf6_neighbor_cmp;  oi->linklocal_addr = (struct in6_addr *) NULL;  oi->instance_id = 0;  oi->transdelay = 1;  oi->priority = 1;  oi->hello_interval = 10;  oi->dead_interval = 40;  oi->rxmt_interval = 5;  oi->cost = 1;  oi->state = OSPF6_INTERFACE_DOWN;  oi->flag = 0;  /* Try to adjust I/O buffer size with IfMtu */  oi->ifmtu = ifp->mtu;  iobuflen = ospf6_iobuf_size (ifp->mtu);  if (oi->ifmtu > iobuflen)    {      if (IS_OSPF6_DEBUG_INTERFACE)        zlog_info ("Interface %s: IfMtu is adjusted to I/O buffer size: %d.",                   ifp->name, iobuflen);      oi->ifmtu = iobuflen;    }  oi->lsupdate_list = ospf6_lsdb_create (oi);  oi->lsack_list = ospf6_lsdb_create (oi);  oi->lsdb = ospf6_lsdb_create (oi);  oi->lsdb->hook_add = ospf6_interface_lsdb_hook;  oi->lsdb->hook_remove = ospf6_interface_lsdb_hook;  oi->lsdb_self = ospf6_lsdb_create (oi);  oi->route_connected = ospf6_route_table_create ();  /* link both */  oi->interface = ifp;  ifp->info = oi;  return oi;}voidospf6_interface_delete (struct ospf6_interface *oi){  listnode n;  struct ospf6_neighbor *on;  for (n = listhead (oi->neighbor_list); n; nextnode (n))    {      on = (struct ospf6_neighbor *) getdata (n);      ospf6_neighbor_delete (on);    }  list_delete (oi->neighbor_list);  THREAD_OFF (oi->thread_send_hello);  THREAD_OFF (oi->thread_send_lsupdate);  THREAD_OFF (oi->thread_send_lsack);  ospf6_lsdb_remove_all (oi->lsdb);  ospf6_lsdb_remove_all (oi->lsupdate_list);  ospf6_lsdb_remove_all (oi->lsack_list);  ospf6_lsdb_delete (oi->lsdb);  ospf6_lsdb_delete (oi->lsdb_self);  ospf6_lsdb_delete (oi->lsupdate_list);  ospf6_lsdb_delete (oi->lsack_list);  ospf6_route_table_delete (oi->route_connected);  /* cut link */  oi->interface->info = NULL;  /* plist_name */  if (oi->plist_name)    XFREE (MTYPE_PREFIX_LIST_STR, oi->plist_name);  XFREE (MTYPE_OSPF6_IF, oi);}voidospf6_interface_enable (struct ospf6_interface *oi){  UNSET_FLAG (oi->flag, OSPF6_INTERFACE_DISABLE);  oi->thread_send_hello =    thread_add_event (master, ospf6_hello_send, oi, 0);}voidospf6_interface_disable (struct ospf6_interface *oi){  listnode i;  struct ospf6_neighbor *on;  SET_FLAG (oi->flag, OSPF6_INTERFACE_DISABLE);  for (i = listhead (oi->neighbor_list); i; nextnode (i))    {      on = (struct ospf6_neighbor *) getdata (i);      ospf6_neighbor_delete (on);    }  list_delete_all_node (oi->neighbor_list);  ospf6_lsdb_remove_all (oi->lsdb);  ospf6_lsdb_remove_all (oi->lsupdate_list);  ospf6_lsdb_remove_all (oi->lsack_list);  THREAD_OFF (oi->thread_send_hello);  THREAD_OFF (oi->thread_send_lsupdate);  THREAD_OFF (oi->thread_send_lsack);}static struct in6_addr *ospf6_interface_get_linklocal_address (struct interface *ifp){  listnode n;  struct connected *c;  struct in6_addr *l = (struct in6_addr *) NULL;  /* for each connected address */  for (n = listhead (ifp->connected); n; nextnode (n))    {      c = (struct connected *) getdata (n);      /* if family not AF_INET6, ignore */      if (c->address->family != AF_INET6)        continue;      /* linklocal scope check */      if (IN6_IS_ADDR_LINKLOCAL (&c->address->u.prefix6))        l = &c->address->u.prefix6;    }  return l;}voidospf6_interface_if_add (struct interface *ifp){  struct ospf6_interface *oi;  int iobuflen;  oi = (struct ospf6_interface *) ifp->info;  if (oi == NULL)    return;  /* Try to adjust I/O buffer size with IfMtu */  if (oi->ifmtu == 0)    oi->ifmtu = ifp->mtu;  iobuflen = ospf6_iobuf_size (ifp->mtu);  if (oi->ifmtu > iobuflen)    {      if (IS_OSPF6_DEBUG_INTERFACE)        zlog_info ("Interface %s: IfMtu is adjusted to I/O buffer size: %d.",                   ifp->name, iobuflen);      oi->ifmtu = iobuflen;    }  /* interface start */  if (oi->area)    thread_add_event (master, interface_up, oi, 0);}voidospf6_interface_if_del (struct interface *ifp){  struct ospf6_interface *oi;  oi = (struct ospf6_interface *) ifp->info;  if (oi == NULL)    return;  /* interface stop */  if (oi->area)    thread_execute (master, interface_down, oi, 0);  listnode_delete (oi->area->if_list, oi);  oi->area = (struct ospf6_area *) NULL;  /* cut link */  oi->interface = NULL;  ifp->info = NULL;  ospf6_interface_delete (oi);}voidospf6_interface_state_update (struct interface *ifp){  struct ospf6_interface *oi;  oi = (struct ospf6_interface *) ifp->info;  if (oi == NULL)    return;  if (oi->area == NULL)    return;  if (if_is_up (ifp))    thread_add_event (master, interface_up, oi, 0);  else    thread_add_event (master, interface_down, oi, 0);  return;}voidospf6_interface_connected_route_update (struct interface *ifp){  struct ospf6_interface *oi;  struct ospf6_route *route;  struct connected *c;  listnode i;  oi = (struct ospf6_interface *) ifp->info;  if (oi == NULL)    return;  /* reset linklocal pointer */  oi->linklocal_addr = ospf6_interface_get_linklocal_address (ifp);  /* if area is null, do not make connected-route list */  if (oi->area == NULL)    return;  /* update "route to advertise" interface route table */  ospf6_route_remove_all (oi->route_connected);  for (i = listhead (oi->interface->connected); i; nextnode (i))    {      c = (struct connected *) getdata (i);      if (c->address->family != AF_INET6)        continue;      CONTINUE_IF_ADDRESS_LINKLOCAL (IS_OSPF6_DEBUG_INTERFACE, c->address);      CONTINUE_IF_ADDRESS_UNSPECIFIED (IS_OSPF6_DEBUG_INTERFACE, c->address);      CONTINUE_IF_ADDRESS_LOOPBACK (IS_OSPF6_DEBUG_INTERFACE, c->address);      CONTINUE_IF_ADDRESS_V4COMPAT (IS_OSPF6_DEBUG_INTERFACE, c->address);      CONTINUE_IF_ADDRESS_V4MAPPED (IS_OSPF6_DEBUG_INTERFACE, c->address);      /* apply filter */      if (oi->plist_name)        {          struct prefix_list *plist;          enum prefix_list_type ret;          char buf[128];          prefix2str (c->address, buf, sizeof (buf));          plist = prefix_list_lookup (AFI_IP6, oi->plist_name);          ret = prefix_list_apply (plist, (void *) c->address);          if (ret == PREFIX_DENY)            {              if (IS_OSPF6_DEBUG_INTERFACE)                zlog_info ("%s on %s filtered by prefix-list %s ",                           buf, oi->interface->name, oi->plist_name);              continue;            }        }      route = ospf6_route_create ();      memcpy (&route->prefix, c->address, sizeof (struct prefix));      apply_mask (&route->prefix);      route->type = OSPF6_DEST_TYPE_NETWORK;      route->path.area_id = oi->area->area_id;      route->path.type = OSPF6_PATH_TYPE_INTRA;      route->path.cost = oi->cost;      route->nexthop[0].ifindex = oi->interface->ifindex;      inet_pton (AF_INET6, "::1", &route->nexthop[0].address);      ospf6_route_add (route, oi->route_connected);    }  /* create new Link-LSA */  OSPF6_LINK_LSA_SCHEDULE (oi);  OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT (oi);  OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB (oi->area);}static voidospf6_interface_state_change (u_char next_state, struct ospf6_interface *oi){  u_char prev_state;  prev_state = oi->state;  oi->state = next_state;  if (prev_state == next_state)    return;  /* log */  if (IS_OSPF6_DEBUG_INTERFACE)    {      zlog_info ("Interface state change %s: %s -> %s", oi->interface->name,                 ospf6_interface_state_str[prev_state],                 ospf6_interface_state_str[next_state]);    }  if ((prev_state == OSPF6_INTERFACE_DR ||       prev_state == OSPF6_INTERFACE_BDR) &&      (next_state != OSPF6_INTERFACE_DR &&       next_state != OSPF6_INTERFACE_BDR))    ospf6_leave_alldrouters (oi->interface->ifindex);  if ((prev_state != OSPF6_INTERFACE_DR &&       prev_state != OSPF6_INTERFACE_BDR) &&      (next_state == OSPF6_INTERFACE_DR ||       next_state == OSPF6_INTERFACE_BDR))    ospf6_join_alldrouters (oi->interface->ifindex);  OSPF6_ROUTER_LSA_SCHEDULE (oi->area);  if (next_state == OSPF6_INTERFACE_DOWN)    {      OSPF6_NETWORK_LSA_EXECUTE (oi);      OSPF6_INTRA_PREFIX_LSA_EXECUTE_TRANSIT (oi);      OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB (oi->area);    }  else if (prev_state == OSPF6_INTERFACE_DR ||           next_state == OSPF6_INTERFACE_DR)    {      OSPF6_NETWORK_LSA_SCHEDULE (oi);      OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT (oi);      OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB (oi->area);    }}/* DR Election, RFC2328 section 9.4 */#define IS_ELIGIBLE(n) \  ((n)->state >= OSPF6_NEIGHBOR_TWOWAY && (n)->priority != 0)static struct ospf6_neighbor *better_bdrouter (struct ospf6_neighbor *a, struct ospf6_neighbor *b){  if ((a == NULL || ! IS_ELIGIBLE (a) || a->drouter == a->router_id) &&      (b == NULL || ! IS_ELIGIBLE (b) || b->drouter == b->router_id))    return NULL;  else if (a == NULL || ! IS_ELIGIBLE (a) || a->drouter == a->router_id)    return b;  else if (b == NULL || ! IS_ELIGIBLE (b) || b->drouter == b->router_id)    return a;  if (a->bdrouter == a->router_id && b->bdrouter != b->router_id)    return a;  if (a->bdrouter != a->router_id && b->bdrouter == b->router_id)    return b;  if (a->priority > b->priority)    return a;  if (a->priority < b->priority)    return b;  if (ntohl (a->router_id) > ntohl (b->router_id))    return a;  if (ntohl (a->router_id) < ntohl (b->router_id))    return b;  zlog_warn ("Router-ID duplicate ?");  return a;}static struct ospf6_neighbor *better_drouter (struct ospf6_neighbor *a, struct ospf6_neighbor *b){  if ((a == NULL || ! IS_ELIGIBLE (a) || a->drouter != a->router_id) &&      (b == NULL || ! IS_ELIGIBLE (b) || b->drouter != b->router_id))    return NULL;  else if (a == NULL || ! IS_ELIGIBLE (a) || a->drouter != a->router_id)    return b;  else if (b == NULL || ! IS_ELIGIBLE (b) || b->drouter != b->router_id)    return a;  if (a->drouter == a->router_id && b->drouter != b->router_id)    return a;  if (a->drouter != a->router_id && b->drouter == b->router_id)    return b;  if (a->priority > b->priority)    return a;  if (a->priority < b->priority)    return b;  if (ntohl (a->router_id) > ntohl (b->router_id))    return a;  if (ntohl (a->router_id) < ntohl (b->router_id))    return b;  zlog_warn ("Router-ID duplicate ?");  return a;}static u_chardr_election (struct ospf6_interface *oi){  listnode i;  struct ospf6_neighbor *on, *drouter, *bdrouter, myself;  struct ospf6_neighbor *best_drouter, *best_bdrouter;  u_char next_state = 0;  drouter = bdrouter = NULL;  best_drouter = best_bdrouter = NULL;  /* pseudo neighbor myself, including noting current DR/BDR (1) */  memset (&myself, 0, sizeof (myself));  inet_ntop (AF_INET, &oi->area->ospf6->router_id, myself.name,             sizeof (myself.name));  myself.state = OSPF6_NEIGHBOR_TWOWAY;  myself.drouter = oi->drouter;  myself.bdrouter = oi->bdrouter;  myself.priority = oi->priority;  myself.router_id = oi->area->ospf6->router_id;  /* Electing BDR (2) */  for (i = listhead (oi->neighbor_list); i; nextnode (i))    {      on = (struct ospf6_neighbor *) getdata (i);      bdrouter = better_bdrouter (bdrouter, on);    }  best_bdrouter = bdrouter;  bdrouter = better_bdrouter (best_bdrouter, &myself);  /* Electing DR (3) */  for (i = listhead (oi->neighbor_list); i; nextnode (i))    {      on = (struct ospf6_neighbor *) getdata (i);

⌨️ 快捷键说明

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