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

📄 bgp_nexthop.c

📁 大名鼎鼎的路由器源码。程序分ZEBRA、OSPFRIP等3个包。程序框架采用一个路由协议一个进程的方式
💻 C
📖 第 1 页 / 共 3 页
字号:
/* BGP nexthop scan   Copyright (C) 2000 Kunihiro IshiguroThis file is part of GNU Zebra.GNU Zebra is free software; you can redistribute it and/or modify itunder the terms of the GNU General Public License as published by theFree Software Foundation; either version 2, or (at your option) anylater version.GNU Zebra is distributed in the hope that it will be useful, butWITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNUGeneral Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU Zebra; see the file COPYING.  If not, write to the FreeSoftware Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA02111-1307, USA.  */#include <zebra.h>#include "command.h"#include "thread.h"#include "prefix.h"#include "zclient.h"#include "stream.h"#include "network.h"#include "log.h"#include "memory.h"#include "bgpd/bgpd.h"#include "bgpd/bgp_table.h"#include "bgpd/bgp_route.h"#include "bgpd/bgp_attr.h"#include "bgpd/bgp_nexthop.h"#include "bgpd/bgp_debug.h"#include "bgpd/bgp_damp.h"#include "zebra/rib.h"#include "zebra/zserv.h"	/* For ZEBRA_SERV_PATH. */struct bgp_nexthop_cache *zlookup_query (struct in_addr);#ifdef HAVE_IPV6struct bgp_nexthop_cache *zlookup_query_ipv6 (struct in6_addr *);#endif /* HAVE_IPV6 *//* Only one BGP scan thread are activated at the same time. */struct thread *bgp_scan_thread = NULL;/* BGP import thread */struct thread *bgp_import_thread = NULL;/* BGP scan interval. */int bgp_scan_interval;/* BGP import interval. */int bgp_import_interval;/* Route table for next-hop lookup cache. */struct bgp_table *bgp_nexthop_cache_ipv4;struct bgp_table *cache1;struct bgp_table *cache2;/* Route table for next-hop lookup cache. */struct bgp_table *bgp_nexthop_cache_ipv6;struct bgp_table *cache6_1;struct bgp_table *cache6_2;/* Route table for connected route. */struct bgp_table *bgp_connected_ipv4;/* Route table for connected route. */struct bgp_table *bgp_connected_ipv6;/* BGP nexthop lookup query client. */static struct zclient *zlookup = NULL;/* BGP process function. */int bgp_process (struct bgp *, struct bgp_node *, afi_t, safi_t);/* Add nexthop to the end of the list.  */voidbnc_nexthop_add (struct bgp_nexthop_cache *bnc, struct nexthop *nexthop){  struct nexthop *last;  for (last = bnc->nexthop; last && last->next; last = last->next)    ;  if (last)    last->next = nexthop;  else    bnc->nexthop = nexthop;  nexthop->prev = last;}voidbnc_nexthop_free (struct bgp_nexthop_cache *bnc){  struct nexthop *nexthop;  struct nexthop *next = NULL;  for (nexthop = bnc->nexthop; nexthop; nexthop = next)    {      next = nexthop->next;      XFREE (MTYPE_NEXTHOP, nexthop);    }}struct bgp_nexthop_cache *bnc_new (){  struct bgp_nexthop_cache *new;  new = XMALLOC (MTYPE_BGP_NEXTHOP_CACHE, sizeof (struct bgp_nexthop_cache));  memset (new, 0, sizeof (struct bgp_nexthop_cache));  return new;}voidbnc_free (struct bgp_nexthop_cache *bnc){  bnc_nexthop_free (bnc);  XFREE (MTYPE_BGP_NEXTHOP_CACHE, bnc);}intbgp_nexthop_same (struct nexthop *next1, struct nexthop *next2){  if (next1->type != next2->type)    return 0;  switch (next1->type)    {    case ZEBRA_NEXTHOP_IPV4:      if (! IPV4_ADDR_SAME (&next1->gate.ipv4, &next2->gate.ipv4))	return 0;      break;    case ZEBRA_NEXTHOP_IFINDEX:    case ZEBRA_NEXTHOP_IFNAME:      if (next1->ifindex != next2->ifindex)	return 0;      break;#ifdef HAVE_IPV6    case ZEBRA_NEXTHOP_IPV6:      if (! IPV6_ADDR_SAME (&next1->gate.ipv6, &next2->gate.ipv6))	return 0;      break;    case ZEBRA_NEXTHOP_IPV6_IFINDEX:    case ZEBRA_NEXTHOP_IPV6_IFNAME:      if (! IPV6_ADDR_SAME (&next1->gate.ipv6, &next2->gate.ipv6))	return 0;      if (next1->ifindex != next2->ifindex)	return 0;      break;#endif /* HAVE_IPV6 */    }  return 1;}intbgp_nexthop_cache_changed (struct bgp_nexthop_cache *bnc1,			   struct bgp_nexthop_cache *bnc2){  int i;  struct nexthop *next1, *next2;  if (bnc1->nexthop_num != bnc2->nexthop_num)    return 1;  next1 = bnc1->nexthop;  next2 = bnc2->nexthop;  for (i = 0; i < bnc1->nexthop_num; i++)    {      if (! bgp_nexthop_same (next1, next2))	return 1;      next1 = next1->next;      next2 = next2->next;    }  return 0;}/* If nexthop exists on connected network return 1. */intbgp_nexthop_check_ebgp (afi_t afi, struct attr *attr){  struct bgp_node *rn;  /* If zebra is not enabled return */  if (zlookup->sock < 0)    return 1;  /* Lookup the address is onlink or not. */  if (afi == AFI_IP)    {      rn = bgp_node_match_ipv4 (bgp_connected_ipv4, &attr->nexthop);      if (rn)	{	  bgp_unlock_node (rn);	  return 1;	}    }#ifdef HAVE_IPV6  else if (afi == AFI_IP6)    {      if (attr->mp_nexthop_len == 32)	return 1;      else if (attr->mp_nexthop_len == 16)	{	  if (IN6_IS_ADDR_LINKLOCAL (&attr->mp_nexthop_global))	    return 1;	  rn = bgp_node_match_ipv6 (bgp_connected_ipv6,				      &attr->mp_nexthop_global);	  if (rn)	    {	      bgp_unlock_node (rn);	      return 1;	    }	}    }#endif /* HAVE_IPV6 */  return 0;}#ifdef HAVE_IPV6/* Check specified next-hop is reachable or not. */intbgp_nexthop_lookup_ipv6 (struct peer *peer, struct bgp_info *ri, int *changed,			 int *metricchanged){  struct bgp_node *rn;  struct prefix p;  struct bgp_nexthop_cache *bnc;  struct attr *attr;  /* If lookup is not enabled, return valid. */  if (zlookup->sock < 0)    {      ri->igpmetric = 0;      return 1;    }  /* Only check IPv6 global address only nexthop. */  attr = ri->attr;  if (attr->mp_nexthop_len != 16       || IN6_IS_ADDR_LINKLOCAL (&attr->mp_nexthop_global))    return 1;  memset (&p, 0, sizeof (struct prefix));  p.family = AF_INET6;  p.prefixlen = IPV6_MAX_BITLEN;  p.u.prefix6 = attr->mp_nexthop_global;  /* IBGP or ebgp-multihop */  rn = bgp_node_get (bgp_nexthop_cache_ipv6, &p);  if (rn->info)    {      bnc = rn->info;      bgp_unlock_node (rn);    }  else    {      bnc = zlookup_query_ipv6 (&attr->mp_nexthop_global);      if (bnc)	{	  struct bgp_table *old;	  struct bgp_node *oldrn;	  struct bgp_nexthop_cache *oldbnc;	  if (changed)	    {	      if (bgp_nexthop_cache_ipv6 == cache6_1)		old = cache6_2;	      else		old = cache6_1;	      oldrn = bgp_node_lookup (old, &p);	      if (oldrn)		{		  oldbnc = oldrn->info;		  bnc->changed = bgp_nexthop_cache_changed (bnc, oldbnc);		  if (bnc->metric != oldbnc->metric)		    bnc->metricchanged = 1;		}	    }	}      else	{	  bnc = bnc_new ();	  bnc->valid = 0;	}      rn->info = bnc;    }  if (changed)    *changed = bnc->changed;  if (metricchanged)    *metricchanged = bnc->metricchanged;  if (bnc->valid)    ri->igpmetric = bnc->metric;  else    ri->igpmetric = 0;  return bnc->valid;}#endif /* HAVE_IPV6 *//* Check specified next-hop is reachable or not. */intbgp_nexthop_lookup (afi_t afi, struct peer *peer, struct bgp_info *ri,		    int *changed, int *metricchanged){  struct bgp_node *rn;  struct prefix p;  struct bgp_nexthop_cache *bnc;  struct in_addr addr;  /* If lookup is not enabled, return valid. */  if (zlookup->sock < 0)    {      ri->igpmetric = 0;      return 1;    }#ifdef HAVE_IPV6  if (afi == AFI_IP6)    return bgp_nexthop_lookup_ipv6 (peer, ri, changed, metricchanged);#endif /* HAVE_IPV6 */  addr = ri->attr->nexthop;  memset (&p, 0, sizeof (struct prefix));  p.family = AF_INET;  p.prefixlen = IPV4_MAX_BITLEN;  p.u.prefix4 = addr;  /* IBGP or ebgp-multihop */  rn = bgp_node_get (bgp_nexthop_cache_ipv4, &p);  if (rn->info)    {      bnc = rn->info;      bgp_unlock_node (rn);    }  else    {      bnc = zlookup_query (addr);      if (bnc)	{	  struct bgp_table *old;	  struct bgp_node *oldrn;	  struct bgp_nexthop_cache *oldbnc;	  if (changed)	    {	      if (bgp_nexthop_cache_ipv4 == cache1)		old = cache2;	      else		old = cache1;	      oldrn = bgp_node_lookup (old, &p);	      if (oldrn)		{		  oldbnc = oldrn->info;		  bnc->changed = bgp_nexthop_cache_changed (bnc, oldbnc);		  if (bnc->metric != oldbnc->metric)		    bnc->metricchanged = 1;		}	    }	}      else	{	  bnc = bnc_new ();	  bnc->valid = 0;	}      rn->info = bnc;    }  if (changed)    *changed = bnc->changed;  if (metricchanged)    *metricchanged = bnc->metricchanged;  if (bnc->valid)    ri->igpmetric = bnc->metric;  else    ri->igpmetric = 0;  return bnc->valid;}/* Reset and free all BGP nexthop cache. */voidbgp_nexthop_cache_reset (struct bgp_table *table){  struct bgp_node *rn;  struct bgp_nexthop_cache *bnc;  for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))    if ((bnc = rn->info) != NULL)      {	bnc_free (bnc);	rn->info = NULL;	bgp_unlock_node (rn);      }}voidbgp_scan_ipv4 (){  struct bgp_node *rn;  struct bgp *bgp;  struct bgp_info *bi;  struct bgp_info *next;  struct peer *peer;  struct listnode *nn;  int valid;  int current;  int changed;  int metricchanged;  /* Change cache. */  if (bgp_nexthop_cache_ipv4 == cache1)    bgp_nexthop_cache_ipv4 = cache2;  else    bgp_nexthop_cache_ipv4 = cache1;  /* Get default bgp. */  bgp = bgp_get_default ();  if (bgp == NULL)    return;  /* Maximum prefix check */  LIST_LOOP (bgp->peer, peer, nn)    {      if (peer->status != Established)	continue;      if (peer->afc[AFI_IP][SAFI_UNICAST])	bgp_maximum_prefix_overflow (peer, AFI_IP, SAFI_UNICAST, 1);      if (peer->afc[AFI_IP][SAFI_MULTICAST])	bgp_maximum_prefix_overflow (peer, AFI_IP, SAFI_MULTICAST, 1);      if (peer->afc[AFI_IP][SAFI_MPLS_VPN])	bgp_maximum_prefix_overflow (peer, AFI_IP, SAFI_MPLS_VPN, 1);    }  for (rn = bgp_table_top (bgp->rib[AFI_IP][SAFI_UNICAST]); rn;       rn = bgp_route_next (rn))    {      for (bi = rn->info; bi; bi = next)	{	  next = bi->next;	  if (bi->type == ZEBRA_ROUTE_BGP && bi->sub_type == BGP_ROUTE_NORMAL)	    {	      changed = 0;	      metricchanged = 0;	      if (peer_sort (bi->peer) == BGP_PEER_EBGP && bi->peer->ttl == 1)

⌨️ 快捷键说明

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