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

📄 bgp_route.c

📁 大名鼎鼎的路由器源码。程序分ZEBRA、OSPFRIP等3个包。程序框架采用一个路由协议一个进程的方式
💻 C
📖 第 1 页 / 共 5 页
字号:
/* BGP routing information   Copyright (C) 1996, 97, 98, 99 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 "prefix.h"#include "linklist.h"#include "memory.h"#include "command.h"#include "stream.h"#include "filter.h"#include "str.h"#include "log.h"#include "routemap.h"#include "buffer.h"#include "sockunion.h"#include "plist.h"#include "thread.h"#include "bgpd/bgpd.h"#include "bgpd/bgp_table.h"#include "bgpd/bgp_route.h"#include "bgpd/bgp_attr.h"#include "bgpd/bgp_debug.h"#include "bgpd/bgp_aspath.h"#include "bgpd/bgp_regex.h"#include "bgpd/bgp_community.h"#include "bgpd/bgp_ecommunity.h"#include "bgpd/bgp_clist.h"#include "bgpd/bgp_packet.h"#include "bgpd/bgp_filter.h"#include "bgpd/bgp_fsm.h"#include "bgpd/bgp_mplsvpn.h"#include "bgpd/bgp_nexthop.h"#include "bgpd/bgp_damp.h"#include "bgpd/bgp_advertise.h"#include "bgpd/bgp_zebra.h"/* Extern from bgp_dump.c */extern char *bgp_origin_str[];extern char *bgp_origin_long_str[];struct bgp_node *bgp_afi_node_get (struct bgp *bgp, afi_t afi, safi_t safi, struct prefix *p,		  struct prefix_rd *prd){  struct bgp_node *rn;  struct bgp_node *prn = NULL;  struct bgp_table *table;  if (safi == SAFI_MPLS_VPN)    {      prn = bgp_node_get (bgp->rib[afi][safi], (struct prefix *) prd);      if (prn->info == NULL)	prn->info = bgp_table_init ();      else	bgp_unlock_node (prn);      table = prn->info;    }  else    table = bgp->rib[afi][safi];  rn = bgp_node_get (table, p);  if (safi == SAFI_MPLS_VPN)    rn->prn = prn;  return rn;}/* Allocate new bgp info structure. */struct bgp_info *bgp_info_new (){  struct bgp_info *new;  new = XMALLOC (MTYPE_BGP_ROUTE, sizeof (struct bgp_info));  memset (new, 0, sizeof (struct bgp_info));  return new;}/* Free bgp route information. */voidbgp_info_free (struct bgp_info *binfo){  if (binfo->attr)    bgp_attr_unintern (binfo->attr);  if (binfo->damp_info)    bgp_damp_info_free (binfo->damp_info, 0);  XFREE (MTYPE_BGP_ROUTE, binfo);}voidbgp_info_add (struct bgp_node *rn, struct bgp_info *ri){  struct bgp_info *top;  top = rn->info;  ri->next = rn->info;  ri->prev = NULL;  if (top)    top->prev = ri;  rn->info = ri;}voidbgp_info_delete (struct bgp_node *rn, struct bgp_info *ri){  if (ri->next)    ri->next->prev = ri->prev;  if (ri->prev)    ri->prev->next = ri->next;  else    rn->info = ri->next;}/* Get MED value.  If MED value is missing and "bgp bestpath   missing-as-worst" is specified, treat it as the worst value. */u_int32_tbgp_med_value (struct attr *attr, struct bgp *bgp){  if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))    return attr->med;  else    {      if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))	return 4294967295ul;      else	return 0;    }}/* Compare two bgp route entity.  br is preferable then return 1. */intbgp_info_cmp (struct bgp *bgp, struct bgp_info *new, struct bgp_info *exist){  u_int32_t new_pref;  u_int32_t exist_pref;  u_int32_t new_med;  u_int32_t exist_med;  struct in_addr new_id;  struct in_addr exist_id;  int new_cluster;  int exist_cluster;  int internal_as_route = 0;  int confed_as_route = 0;  int ret;  /* 0. Null check. */  if (new == NULL)    return 0;  if (exist == NULL)    return 1;  /* 1. Weight check. */  if (new->attr->weight > exist->attr->weight)    return 1;  if (new->attr->weight < exist->attr->weight)    return 0;  /* 2. Local preference check. */  if (new->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF))    new_pref = new->attr->local_pref;  else    new_pref = bgp->default_local_pref;  if (exist->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF))    exist_pref = exist->attr->local_pref;  else    exist_pref = bgp->default_local_pref;      if (new_pref > exist_pref)    return 1;  if (new_pref < exist_pref)    return 0;  /* 3. Local route check. */  if (new->sub_type == BGP_ROUTE_STATIC)    return 1;  if (exist->sub_type == BGP_ROUTE_STATIC)    return 0;  if (new->sub_type == BGP_ROUTE_REDISTRIBUTE)    return 1;  if (exist->sub_type == BGP_ROUTE_REDISTRIBUTE)    return 0;  if (new->sub_type == BGP_ROUTE_AGGREGATE)    return 1;  if (exist->sub_type == BGP_ROUTE_AGGREGATE)    return 0;  /* 4. AS path length check. */  if (! bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))    {      if (new->attr->aspath->count < exist->attr->aspath->count)	return 1;      if (new->attr->aspath->count > exist->attr->aspath->count)	return 0;    }  /* 5. Origin check. */  if (new->attr->origin < exist->attr->origin)    return 1;  if (new->attr->origin > exist->attr->origin)    return 0;  /* 6. MED check. */  internal_as_route = (new->attr->aspath->length == 0		      && exist->attr->aspath->length == 0);  confed_as_route = (new->attr->aspath->length > 0		    && exist->attr->aspath->length > 0		    && new->attr->aspath->count == 0		    && exist->attr->aspath->count == 0);    if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED)      || (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)	 && confed_as_route)      || aspath_cmp_left (new->attr->aspath, exist->attr->aspath)      || aspath_cmp_left_confed (new->attr->aspath, exist->attr->aspath)      || internal_as_route)    {      new_med = bgp_med_value (new->attr, bgp);      exist_med = bgp_med_value (exist->attr, bgp);      if (new_med < exist_med)	return 1;      if (new_med > exist_med)	return 0;    }  /* 7. Peer type check. */  if (peer_sort (new->peer) == BGP_PEER_EBGP       && peer_sort (exist->peer) == BGP_PEER_IBGP)    return 1;  if (peer_sort (new->peer) == BGP_PEER_EBGP       && peer_sort (exist->peer) == BGP_PEER_CONFED)    return 1;  if (peer_sort (new->peer) == BGP_PEER_IBGP       && peer_sort (exist->peer) == BGP_PEER_EBGP)    return 0;  if (peer_sort (new->peer) == BGP_PEER_CONFED       && peer_sort (exist->peer) == BGP_PEER_EBGP)    return 0;  /* 8. IGP metric check. */  if (new->igpmetric < exist->igpmetric)    return 1;  if (new->igpmetric > exist->igpmetric)    return 0;  /* 9. Maximum path check. */  /* 10. If both paths are external, prefer the path that was received     first (the oldest one).  This step minimizes route-flap, since a     newer path won't displace an older one, even if it was the     preferred route based on the additional decision criteria below.  */  if (! bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID)      && peer_sort (new->peer) == BGP_PEER_EBGP      && peer_sort (exist->peer) == BGP_PEER_EBGP)    {      if (CHECK_FLAG (new->flags, BGP_INFO_SELECTED))	return 1;      if (CHECK_FLAG (exist->flags, BGP_INFO_SELECTED))	return 0;    }  /* 11. Rourter-ID comparision. */  if (new->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))    new_id.s_addr = new->attr->originator_id.s_addr;  else    new_id.s_addr = new->peer->remote_id.s_addr;  if (exist->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))    exist_id.s_addr = exist->attr->originator_id.s_addr;  else    exist_id.s_addr = exist->peer->remote_id.s_addr;  if (ntohl (new_id.s_addr) < ntohl (exist_id.s_addr))    return 1;  if (ntohl (new_id.s_addr) > ntohl (exist_id.s_addr))    return 0;  /* 12. Cluster length comparision. */  if (new->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))    new_cluster = new->attr->cluster->length;  else    new_cluster = 0;  if (exist->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))    exist_cluster = exist->attr->cluster->length;  else    exist_cluster = 0;  if (new_cluster < exist_cluster)    return 1;  if (new_cluster > exist_cluster)    return 0;  /* 13. Neighbor address comparision. */  ret = sockunion_cmp (new->peer->su_remote, exist->peer->su_remote);  if (ret == 1)    return 0;  if (ret == -1)    return 1;  return 1;}enum filter_typebgp_input_filter (struct peer *peer, struct prefix *p, struct attr *attr,		  afi_t afi, safi_t safi){  struct bgp_filter *filter;  filter = &peer->filter[afi][safi];  if (DISTRIBUTE_IN_NAME (filter))    if (access_list_apply (DISTRIBUTE_IN (filter), p) == FILTER_DENY)      return FILTER_DENY;  if (PREFIX_LIST_IN_NAME (filter))    if (prefix_list_apply (PREFIX_LIST_IN (filter), p) == PREFIX_DENY)      return FILTER_DENY;    if (FILTER_LIST_IN_NAME (filter))    if (as_list_apply (FILTER_LIST_IN (filter), attr->aspath)== AS_FILTER_DENY)      return FILTER_DENY;  return FILTER_PERMIT;}enum filter_typebgp_output_filter (struct peer *peer, struct prefix *p, struct attr *attr,		   afi_t afi, safi_t safi){  struct bgp_filter *filter;  filter = &peer->filter[afi][safi];  if (DISTRIBUTE_OUT_NAME (filter))    if (access_list_apply (DISTRIBUTE_OUT (filter), p) == FILTER_DENY)      return FILTER_DENY;  if (PREFIX_LIST_OUT_NAME (filter))    if (prefix_list_apply (PREFIX_LIST_OUT (filter), p) == PREFIX_DENY)      return FILTER_DENY;  if (FILTER_LIST_OUT_NAME (filter))    if (as_list_apply (FILTER_LIST_OUT (filter), attr->aspath) == AS_FILTER_DENY)      return FILTER_DENY;  return FILTER_PERMIT;}/* If community attribute includes no_export then return 1. */intbgp_community_filter (struct peer *peer, struct attr *attr){  if (attr->community)    {      /* NO_ADVERTISE check. */      if (community_include (attr->community, COMMUNITY_NO_ADVERTISE))	return 1;      /* NO_EXPORT check. */      if (peer_sort (peer) == BGP_PEER_EBGP &&	  community_include (attr->community, COMMUNITY_NO_EXPORT))	return 1;      /* NO_EXPORT_SUBCONFED check. */      if (peer_sort (peer) == BGP_PEER_EBGP 	  || peer_sort (peer) == BGP_PEER_CONFED)	if (community_include (attr->community, COMMUNITY_NO_EXPORT_SUBCONFED))	  return 1;    }  return 0;}/* Route reflection loop check.  */static intbgp_cluster_filter (struct peer *peer, struct attr *attr){  struct in_addr cluster_id;  if (attr->cluster)    {      if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID)	cluster_id = peer->bgp->cluster_id;      else	cluster_id = peer->bgp->router_id;            if (cluster_loop_check (attr->cluster, cluster_id))	return 1;    }  return 0;}intbgp_input_modifier (struct peer *peer, struct prefix *p, struct attr *attr,		    afi_t afi, safi_t safi){  struct bgp_filter *filter;  struct bgp_info info;  route_map_result_t ret;  filter = &peer->filter[afi][safi];  /* Apply default weight value. */  attr->weight = peer->weight;  /* Route map apply. */  if (ROUTE_MAP_IN_NAME (filter))    {      /* Duplicate current value to new strucutre for modification. */      info.peer = peer;      info.attr = attr;      SET_FLAG (peer->rmap_type, PEER_RMAP_TYPE_IN);       /* Apply BGP route map to the attribute. */      ret = route_map_apply (ROUTE_MAP_IN (filter), p, RMAP_BGP, &info);      peer->rmap_type = 0;      if (ret == RMAP_DENYMATCH)	{	  /* Free newly generated AS path and community by route-map. */	  bgp_attr_flush (attr);	  return RMAP_DENY;	}    }  return RMAP_PERMIT;}intbgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p,		    struct attr *attr, afi_t afi, safi_t safi){  int ret;  char buf[SU_ADDRSTRLEN];  struct bgp_filter *filter;  struct bgp_info info;  struct peer *from;  struct bgp *bgp;  struct attr dummy_attr;  int transparent;  int reflect;  from = ri->peer;  filter = &peer->filter[afi][safi];  bgp = peer->bgp;  #ifdef DISABLE_BGP_ANNOUNCE  return 0;#endif  /* Do not send back route to sender. */  if (from == peer)    return 0;  /* Aggregate-address suppress check. */  if (ri->suppress)    if (! UNSUPPRESS_MAP_NAME (filter))      return 0;  /* Default route check.  */  if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_DEFAULT_ORIGINATE))    {      if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)	return 0;#ifdef HAVE_IPV6      else if (p->family == AF_INET6 && p->prefixlen == 0)	return 0;#endif /* HAVE_IPV6 */    }  /* Transparency check. */  if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)      && CHECK_FLAG (from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))    transparent = 1;  else    transparent = 0;

⌨️ 快捷键说明

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