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

📄 ospf6_spf.c

📁 linux 路由软件 可支持RIP OSPF BGP等
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * 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.   *//* Shortest Path First calculation for OSPFv3 */#include <zebra.h>#include "log.h"#include "memory.h"#include "command.h"#include "vty.h"#include "prefix.h"#include "pqueue.h"#include "linklist.h"#include "thread.h"#include "ospf6_lsa.h"#include "ospf6_lsdb.h"#include "ospf6_route.h"#include "ospf6_area.h"#include "ospf6_spf.h"#include "ospf6_intra.h"#include "ospf6_interface.h"#include "ospf6d.h"unsigned char conf_debug_ospf6_spf = 0;intospf6_vertex_cmp (void *a, void *b){  struct ospf6_vertex *va = (struct ospf6_vertex *) a;  struct ospf6_vertex *vb = (struct ospf6_vertex *) b;  /* ascending order */  return (va->cost - vb->cost);}intospf6_vertex_id_cmp (void *a, void *b){  struct ospf6_vertex *va = (struct ospf6_vertex *) a;  struct ospf6_vertex *vb = (struct ospf6_vertex *) b;  int ret = 0;  ret = ntohl (ospf6_linkstate_prefix_adv_router (&va->vertex_id)) -        ntohl (ospf6_linkstate_prefix_adv_router (&vb->vertex_id));  if (ret)    return ret;  ret = ntohl (ospf6_linkstate_prefix_id (&va->vertex_id)) -        ntohl (ospf6_linkstate_prefix_id (&vb->vertex_id));  return ret;}struct ospf6_vertex *ospf6_vertex_create (struct ospf6_lsa *lsa){  struct ospf6_vertex *v;  int i;  v = (struct ospf6_vertex *)    XMALLOC (MTYPE_OSPF6_VERTEX, sizeof (struct ospf6_vertex));  /* type */  if (ntohs (lsa->header->type) == OSPF6_LSTYPE_ROUTER)    v->type = OSPF6_VERTEX_TYPE_ROUTER;  else if (ntohs (lsa->header->type) == OSPF6_LSTYPE_NETWORK)    v->type = OSPF6_VERTEX_TYPE_NETWORK;  else    assert (0);  /* vertex_id */  ospf6_linkstate_prefix (lsa->header->adv_router, lsa->header->id,                          &v->vertex_id);  /* name */  ospf6_linkstate_prefix2str (&v->vertex_id, v->name, sizeof (v->name));  /* Associated LSA */  v->lsa = lsa;  /* capability bits + options */  v->capability = *(u_char *)(OSPF6_LSA_HEADER_END (lsa->header));  v->options[0] = *(u_char *)(OSPF6_LSA_HEADER_END (lsa->header) + 1);  v->options[1] = *(u_char *)(OSPF6_LSA_HEADER_END (lsa->header) + 2);  v->options[2] = *(u_char *)(OSPF6_LSA_HEADER_END (lsa->header) + 3);  for (i = 0; i < OSPF6_MULTI_PATH_LIMIT; i++)    ospf6_nexthop_clear (&v->nexthop[i]);  v->parent = NULL;  v->child_list = list_new ();  v->child_list->cmp = ospf6_vertex_id_cmp;  return v;}voidospf6_vertex_delete (struct ospf6_vertex *v){  list_delete (v->child_list);  XFREE (MTYPE_OSPF6_VERTEX, v);}struct ospf6_lsa *ospf6_lsdesc_lsa (caddr_t lsdesc, struct ospf6_vertex *v){  struct ospf6_lsa *lsa;  u_int16_t type = 0;  u_int32_t id = 0, adv_router = 0;  if (VERTEX_IS_TYPE (NETWORK, v))    {      type = htons (OSPF6_LSTYPE_ROUTER);      id = htonl (0);      adv_router = NETWORK_LSDESC_GET_NBR_ROUTERID (lsdesc);    }  else    {      if (ROUTER_LSDESC_IS_TYPE (POINTTOPOINT, lsdesc))        {          type = htons (OSPF6_LSTYPE_ROUTER);          id = htonl (0);          adv_router = ROUTER_LSDESC_GET_NBR_ROUTERID (lsdesc);        }      else if (ROUTER_LSDESC_IS_TYPE (TRANSIT_NETWORK, lsdesc))        {          type = htons (OSPF6_LSTYPE_NETWORK);          id = htonl (ROUTER_LSDESC_GET_NBR_IFID (lsdesc));          adv_router = ROUTER_LSDESC_GET_NBR_ROUTERID (lsdesc);        }    }  lsa = ospf6_lsdb_lookup (type, id, adv_router, v->area->lsdb);  if (IS_OSPF6_DEBUG_SPF (PROCESS))    {      char ibuf[16], abuf[16];      inet_ntop (AF_INET, &id, ibuf, sizeof (ibuf));      inet_ntop (AF_INET, &adv_router, abuf, sizeof (abuf));      if (lsa)        zlog_info ("  Link to: %s", lsa->name);      else        zlog_info ("  Link to: [%s Id:%s Adv:%s] No LSA",                   ospf6_lstype_name (type), ibuf, abuf);    }  return lsa;}char *ospf6_lsdesc_backlink (struct ospf6_lsa *lsa,                       caddr_t lsdesc, struct ospf6_vertex *v){  caddr_t backlink, found = NULL;  int size;  size = (OSPF6_LSA_IS_TYPE (ROUTER, lsa) ?          sizeof (struct ospf6_router_lsdesc) :          sizeof (struct ospf6_network_lsdesc));  for (backlink = OSPF6_LSA_HEADER_END (lsa->header) + 4;       backlink + size <= OSPF6_LSA_END (lsa->header); backlink += size)    {      assert (! (OSPF6_LSA_IS_TYPE (NETWORK, lsa) &&                 VERTEX_IS_TYPE (NETWORK, v)));      if (OSPF6_LSA_IS_TYPE (NETWORK, lsa) &&          NETWORK_LSDESC_GET_NBR_ROUTERID (backlink)            == v->lsa->header->adv_router)        found = backlink;      else if (VERTEX_IS_TYPE (NETWORK, v) &&          ROUTER_LSDESC_IS_TYPE (TRANSIT_NETWORK, backlink) &&          ROUTER_LSDESC_GET_NBR_ROUTERID (backlink)            == v->lsa->header->adv_router &&          ROUTER_LSDESC_GET_NBR_IFID (backlink)            == ntohl (v->lsa->header->id))        found = backlink;      else        {          if (! ROUTER_LSDESC_IS_TYPE (POINTTOPOINT, backlink) ||              ! ROUTER_LSDESC_IS_TYPE (POINTTOPOINT, lsdesc))            continue;          if (ROUTER_LSDESC_GET_NBR_IFID (backlink) !=              ROUTER_LSDESC_GET_IFID (lsdesc) ||              ROUTER_LSDESC_GET_NBR_IFID (lsdesc) !=              ROUTER_LSDESC_GET_IFID (backlink))            continue;          if (ROUTER_LSDESC_GET_NBR_ROUTERID (backlink) !=              v->lsa->header->adv_router ||              ROUTER_LSDESC_GET_NBR_ROUTERID (lsdesc) !=              lsa->header->adv_router)            continue;          found = backlink;        }    }  if (IS_OSPF6_DEBUG_SPF (PROCESS))    zlog_info ("  Backlink %s", (found ? "OK" : "FAIL"));  return found;}voidospf6_nexthop_calc (struct ospf6_vertex *w, struct ospf6_vertex *v,                    caddr_t lsdesc){  int i, ifindex;  struct ospf6_interface *oi;  u_int16_t type;  u_int32_t adv_router;  struct ospf6_lsa *lsa;  struct ospf6_link_lsa *link_lsa;  char buf[64];  assert (VERTEX_IS_TYPE (ROUTER, w));  ifindex = (VERTEX_IS_TYPE (NETWORK, v) ? v->nexthop[0].ifindex :             ROUTER_LSDESC_GET_IFID (lsdesc));  oi = ospf6_interface_lookup_by_ifindex (ifindex);  if (oi == NULL)    {      if (IS_OSPF6_DEBUG_SPF (PROCESS))        zlog_warn ("Can't find interface in SPF: ifindex %d", ifindex);      return;    }  type = htons (OSPF6_LSTYPE_LINK);  adv_router = (VERTEX_IS_TYPE (NETWORK, v) ?                NETWORK_LSDESC_GET_NBR_ROUTERID (lsdesc) :                ROUTER_LSDESC_GET_NBR_ROUTERID (lsdesc));  i = 0;  for (lsa = ospf6_lsdb_type_router_head (type, adv_router, oi->lsdb); lsa;       lsa = ospf6_lsdb_type_router_next (type, adv_router, lsa))    {      if (VERTEX_IS_TYPE (ROUTER, v) &&          htonl (ROUTER_LSDESC_GET_NBR_IFID (lsdesc)) != lsa->header->id)        continue;      link_lsa = (struct ospf6_link_lsa *) OSPF6_LSA_HEADER_END (lsa->header);      if (IS_OSPF6_DEBUG_SPF (PROCESS))        {          inet_ntop (AF_INET6, &link_lsa->linklocal_addr, buf, sizeof (buf));          zlog_info ("  nexthop %s from %s", buf, lsa->name);        }      if (i < OSPF6_MULTI_PATH_LIMIT)        {          memcpy (&w->nexthop[i].address, &link_lsa->linklocal_addr,                  sizeof (struct in6_addr));          w->nexthop[i].ifindex = ifindex;          i++;        }    }  if (i == 0 && IS_OSPF6_DEBUG_SPF (PROCESS))    zlog_info ("No nexthop for %s found", w->name);}intospf6_spf_install (struct ospf6_vertex *v,                   struct ospf6_route_table *result_table){  struct ospf6_route *route;  int i, j;  struct ospf6_vertex *prev, *w;  listnode node;  if (IS_OSPF6_DEBUG_SPF (PROCESS))    zlog_info ("SPF install %s hops %d cost %d",               v->name, v->hops, v->cost);  route = ospf6_route_lookup (&v->vertex_id, result_table);  if (route && route->path.cost < v->cost)    {      if (IS_OSPF6_DEBUG_SPF (PROCESS))        zlog_info ("  already installed with lower cost (%d), ignore",                   route->path.cost);      ospf6_vertex_delete (v);      return -1;    }  else if (route && route->path.cost == v->cost)    {      if (IS_OSPF6_DEBUG_SPF (PROCESS))        zlog_info ("  another path found, merge");      for (i = 0; ospf6_nexthop_is_set (&v->nexthop[i]) &&           i < OSPF6_MULTI_PATH_LIMIT; i++)        {          for (j = 0; j < OSPF6_MULTI_PATH_LIMIT; j++)            {              if (ospf6_nexthop_is_set (&route->nexthop[j]))                {                  if (ospf6_nexthop_is_same (&route->nexthop[j],                                             &v->nexthop[i]))                    break;                  else                    continue;                }              ospf6_nexthop_copy (&route->nexthop[j], &v->nexthop[i]);              break;            }        }      prev = (struct ospf6_vertex *) route->route_option;      if (prev->hops > v->hops)        {          LIST_LOOP (prev->child_list, w, node)            {              assert (w->parent == prev);              w->parent = v;              listnode_add_sort (v->child_list, w);            }          listnode_delete (prev->parent->child_list, prev);          listnode_add_sort (v->parent->child_list, v);          ospf6_vertex_delete (prev);          route->route_option = v;        }      else        ospf6_vertex_delete (v);      return -1;    }  /* There should be no case where candidate being installed (variable     "v") is closer than the one in the SPF tree (variable "route").     In the case something has gone wrong with the behavior of     Priority-Queue. */  /* the case where the route exists already is handled and returned     up to here. */  assert (route == NULL);  route = ospf6_route_create ();  memcpy (&route->prefix, &v->vertex_id, sizeof (struct prefix));  route->type = OSPF6_DEST_TYPE_LINKSTATE;  route->path.type = OSPF6_PATH_TYPE_INTRA;  route->path.origin.type = v->lsa->header->type;  route->path.origin.id = v->lsa->header->id;  route->path.origin.adv_router = v->lsa->header->adv_router;

⌨️ 快捷键说明

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