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

📄 bgp_route.c

📁 大名鼎鼎的路由器源码。程序分ZEBRA、OSPFRIP等3个包。程序框架采用一个路由协议一个进程的方式
💻 C
📖 第 1 页 / 共 5 页
字号:
  /* If community is not disabled check the no-export and local. */  if (! transparent && bgp_community_filter (peer, ri->attr))     return 0;  /* If the attribute has originator-id and it is same as remote     peer's id. */  if (ri->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID))    {      if (IPV4_ADDR_SAME (&peer->remote_id, &ri->attr->originator_id))	{	  if (BGP_DEBUG (filter, FILTER))  	    zlog (peer->log, LOG_INFO,		  "%s [Update:SEND] %s/%d originator-id is same as remote router-id",		  peer->host,		  inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),		  p->prefixlen);	  return 0;	}    }   /* ORF prefix-list filter check */  if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)      && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)	  || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))    if (peer->orf_plist[afi][safi])      {	if (prefix_list_apply (peer->orf_plist[afi][safi], p) == PREFIX_DENY)          return 0;      }  /* Output filter check. */  if (bgp_output_filter (peer, p, ri->attr, afi, safi) == FILTER_DENY)    {      if (BGP_DEBUG (filter, FILTER))	zlog (peer->log, LOG_INFO,	      "%s [Update:SEND] %s/%d is filtered",	      peer->host,	      inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),	      p->prefixlen);      return 0;    }#ifdef BGP_SEND_ASPATH_CHECK  /* AS path loop check. */  if (aspath_loop_check (ri->attr->aspath, peer->as))    {      if (BGP_DEBUG (filter, FILTER))          zlog (peer->log, LOG_INFO, 	      "%s [Update:SEND] suppress announcement to peer AS %d is AS path.",	      peer->host, peer->as);      return 0;    }#endif /* BGP_SEND_ASPATH_CHECK */  /* If we're a CONFED we need to loop check the CONFED ID too */  if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION))    {      if (aspath_loop_check(ri->attr->aspath, bgp->confed_id))	{	  if (BGP_DEBUG (filter, FILTER))  	    zlog (peer->log, LOG_INFO, 		  "%s [Update:SEND] suppress announcement to peer AS %d is AS path.",		  peer->host,		  bgp->confed_id);	  return 0;	}          }  /* Route-Reflect check. */  if (peer_sort (from) == BGP_PEER_IBGP && peer_sort (peer) == BGP_PEER_IBGP)    reflect = 1;  else    reflect = 0;  /* IBGP reflection check. */  if (reflect)    {      /* A route from a Client peer. */      if (CHECK_FLAG (from->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT))	{	  /* Reflect to all the Non-Client peers and also to the             Client peers other than the originator.  Originator check             is already done.  So there is noting to do. */	  /* no bgp client-to-client reflection check. */	  if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))	    if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT))	      return 0;	}      else	{	  /* A route from a Non-client peer. Reflect to all other	     clients. */	  if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT))	    return 0;	}    }  /* For modify attribute, copy it to temporary structure. */  *attr = *ri->attr;  /* If local-preference is not set. */  if ((peer_sort (peer) == BGP_PEER_IBGP        || peer_sort (peer) == BGP_PEER_CONFED)       && (! (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF))))    {      attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF);      attr->local_pref = bgp->default_local_pref;    }  /* Remove MED if its an EBGP peer - will get overwritten by route-maps */  if (peer_sort (peer) == BGP_PEER_EBGP       && attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))    {      if (ri->peer != bgp->peer_self && ! transparent	  && ! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))	attr->flag &= ~(ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC));    }  /* next-hop-set */  if (transparent || reflect      || (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)	  && ((p->family == AF_INET && attr->nexthop.s_addr)#ifdef HAVE_IPV6	      || (p->family == AF_INET6 && ri->peer != bgp->peer_self)#endif /* HAVE_IPV6 */	      )))    {      /* NEXT-HOP Unchanged. */    }  else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_SELF)	   || (p->family == AF_INET && attr->nexthop.s_addr == 0)#ifdef HAVE_IPV6	   || (p->family == AF_INET6 && ri->peer == bgp->peer_self)#endif /* HAVE_IPV6 */	   || (peer_sort (peer) == BGP_PEER_EBGP	       && bgp_multiaccess_check_v4 (attr->nexthop, peer->host) == 0))    {      /* Set IPv4 nexthop. */      if (p->family == AF_INET)	{	  if (safi == SAFI_MPLS_VPN)	    memcpy (&attr->mp_nexthop_global_in, &peer->nexthop.v4, IPV4_MAX_BYTELEN);	  else	    memcpy (&attr->nexthop, &peer->nexthop.v4, IPV4_MAX_BYTELEN);	}#ifdef HAVE_IPV6      /* Set IPv6 nexthop. */      if (p->family == AF_INET6)	{	  /* IPv6 global nexthop must be included. */	  memcpy (&attr->mp_nexthop_global, &peer->nexthop.v6_global, 		  IPV6_MAX_BYTELEN);	  attr->mp_nexthop_len = 16;	}#endif /* HAVE_IPV6 */    }#ifdef HAVE_IPV6  if (p->family == AF_INET6)    {      /* Link-local address should not be transit to different peer. */      attr->mp_nexthop_len = 16;      /* Set link-local address for shared network peer. */      if (peer->shared_network 	  && ! IN6_IS_ADDR_UNSPECIFIED (&peer->nexthop.v6_local))	{	  memcpy (&attr->mp_nexthop_local, &peer->nexthop.v6_local, 		  IPV6_MAX_BYTELEN);	  attr->mp_nexthop_len = 32;	}      /* If bgpd act as BGP-4+ route-reflector, do not send link-local	 address.*/      if (reflect)	attr->mp_nexthop_len = 16;      /* If BGP-4+ link-local nexthop is not link-local nexthop. */      if (! IN6_IS_ADDR_LINKLOCAL (&peer->nexthop.v6_local))	attr->mp_nexthop_len = 16;    }#endif /* HAVE_IPV6 */  /* If this is EBGP peer and remove-private-AS is set.  */  if (peer_sort (peer) == BGP_PEER_EBGP      && peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)      && aspath_private_as_check (attr->aspath))    attr->aspath = aspath_empty_get ();  /* Route map & unsuppress-map apply. */  if (ROUTE_MAP_OUT_NAME (filter)      || ri->suppress)    {      info.peer = peer;      info.attr = attr;      /* The route reflector is not allowed to modify the attributes	 of the reflected IBGP routes. */      if (peer_sort (from) == BGP_PEER_IBGP 	  && peer_sort (peer) == BGP_PEER_IBGP)	{	  dummy_attr = *attr;	  info.attr = &dummy_attr;	}      SET_FLAG (peer->rmap_type, PEER_RMAP_TYPE_OUT);       if (ri->suppress)	ret = route_map_apply (UNSUPPRESS_MAP (filter), p, RMAP_BGP, &info);      else	ret = route_map_apply (ROUTE_MAP_OUT (filter), p, RMAP_BGP, &info);      peer->rmap_type = 0;      if (ret == RMAP_DENYMATCH)	{	  bgp_attr_flush (attr);	  return 0;	}    }  return 1;}intbgp_process (struct bgp *bgp, struct bgp_node *rn, afi_t afi, safi_t safi){  struct prefix *p;  struct bgp_info *ri;  struct bgp_info *new_select;  struct bgp_info *old_select;  struct listnode *nn;  struct peer *peer;  struct attr attr;  struct bgp_info *ri1;  struct bgp_info *ri2;  p = &rn->p;  /* bgp deterministic-med */  new_select = NULL;  if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))    for (ri1 = rn->info; ri1; ri1 = ri1->next)      {	if (CHECK_FLAG (ri1->flags, BGP_INFO_DMED_CHECK))	  continue;	if (BGP_INFO_HOLDDOWN (ri1))	  continue;	new_select = ri1;	if (ri1->next)	  for (ri2 = ri1->next; ri2; ri2 = ri2->next)	    {	      if (CHECK_FLAG (ri2->flags, BGP_INFO_DMED_CHECK))		continue;	      if (BGP_INFO_HOLDDOWN (ri2))		continue;	      if (aspath_cmp_left (ri1->attr->aspath, ri2->attr->aspath)		  || aspath_cmp_left_confed (ri1->attr->aspath,					     ri2->attr->aspath))		{		  if (bgp_info_cmp (bgp, ri2, new_select))		    {		      UNSET_FLAG (new_select->flags, BGP_INFO_DMED_SELECTED);		      new_select = ri2;		    }		  SET_FLAG (ri2->flags, BGP_INFO_DMED_CHECK);		}	    }	SET_FLAG (new_select->flags, BGP_INFO_DMED_CHECK);	SET_FLAG (new_select->flags, BGP_INFO_DMED_SELECTED);      }  /* Check old selected route and new selected route. */  old_select = NULL;  new_select = NULL;  for (ri = rn->info; ri; ri = ri->next)    {      if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED))	old_select = ri;      if (BGP_INFO_HOLDDOWN (ri))	continue;      if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED)          && (! CHECK_FLAG (ri->flags, BGP_INFO_DMED_SELECTED)))	{	  UNSET_FLAG (ri->flags, BGP_INFO_DMED_CHECK);	  continue;        }      UNSET_FLAG (ri->flags, BGP_INFO_DMED_CHECK);      UNSET_FLAG (ri->flags, BGP_INFO_DMED_SELECTED);      if (bgp_info_cmp (bgp, ri, new_select))	new_select = ri;    }  /* Nothing to do. */  if (old_select && old_select == new_select)    {      if (! CHECK_FLAG (old_select->flags, BGP_INFO_ATTR_CHANGED))	{	  if (CHECK_FLAG (old_select->flags, BGP_INFO_IGP_CHANGED))	    bgp_zebra_announce (p, old_select, bgp);	  return 0;	}    }  if (old_select)    UNSET_FLAG (old_select->flags, BGP_INFO_SELECTED);  if (new_select)    {      SET_FLAG (new_select->flags, BGP_INFO_SELECTED);      UNSET_FLAG (new_select->flags, BGP_INFO_ATTR_CHANGED);    }  /* Check each BGP peer. */  LIST_LOOP (bgp->peer, peer, nn)    {      /* Announce route to Established peer. */      if (peer->status != Established)	continue;      /* Address family configuration check. */      if (! peer->afc_nego[afi][safi])	continue;      /* First update is deferred until ORF or ROUTE-REFRESH is received */      if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_WAIT_REFRESH))	continue;      /* Announcement to peer->conf.  If the route is filtered,         withdraw it. */      if (new_select 	  && bgp_announce_check (new_select, peer, p, &attr, afi, safi))	bgp_adj_out_set (rn, peer, p, &attr, afi, safi, new_select);      else	bgp_adj_out_unset (rn, peer, p, afi, safi);    }  /* FIB update. */  if (safi == SAFI_UNICAST && ! bgp->name &&      ! bgp_option_check (BGP_OPT_NO_FIB))    {      if (new_select 	  && new_select->type == ZEBRA_ROUTE_BGP 	  && new_select->sub_type == BGP_ROUTE_NORMAL)	bgp_zebra_announce (p, new_select, bgp);      else	{	  /* Withdraw the route from the kernel. */	  if (old_select 	      && old_select->type == ZEBRA_ROUTE_BGP	      && old_select->sub_type == BGP_ROUTE_NORMAL)	    bgp_zebra_withdraw (p, old_select);	}    }  return 0;}intbgp_maximum_prefix_overflow (struct peer *peer, afi_t afi, safi_t safi, int always){  if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))    return 0;  if (peer->pcount[afi][safi] > peer->pmax[afi][safi])    {      if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT)	  && ! always)	return 0;      zlog (peer->log, LOG_INFO,	    "%%MAXPFXEXCEED: No. of prefix received from %s (afi %d): %ld exceed limit %ld",	    peer->host, afi, peer->pcount[afi][safi], peer->pmax[afi][safi]);      SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);      if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))	return 0;      {	char ndata[7];	ndata[0] = (u_char)(afi >>  8);	ndata[1] = (u_char) afi;	ndata[3] = (u_char)(peer->pmax[afi][safi] >> 24);	ndata[4] = (u_char)(peer->pmax[afi][safi] >> 16);	ndata[5] = (u_char)(peer->pmax[afi][safi] >> 8);	ndata[6] = (u_char)(peer->pmax[afi][safi]);	if (safi == SAFI_MPLS_VPN)	  safi = BGP_SAFI_VPNV4;	ndata[2] = (u_char) safi;	SET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);	bgp_notify_send_with_data (peer, BGP_NOTIFY_CEASE,				   BGP_NOTIFY_CEASE_MAX_PREFIX, ndata, 7);      }      return 1;    }  else    UNSET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);  if (peer->pcount[afi][safi] > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100))    {      if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_THRESHOLD)	  && ! always)	return 0;      zlog (peer->log, LOG_INFO,	    "%%MAXPFX: No. of prefix received from %s (afi %d) reaches %ld, max %ld",	    peer->host, afi, peer->pcount[afi][safi], peer->pmax[afi][safi]);      SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_THRESHOLD);    }  else    UNSET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_THRESHOLD);  return 0;}voidbgp_rib_remove (struct bgp_node *rn, struct bgp_info *ri, struct peer *peer,		afi_t afi, safi_t safi){  if (! CHECK_FLAG (ri->flags, BGP_INFO_HISTORY))    {      peer->pcount[afi][safi]--;      bgp_aggregate_decrement (peer->bgp, &rn->p, ri, afi, safi);      UNSET_FLAG (ri->flags, BGP_INFO_VALID);      bgp_process (peer->bgp, rn, afi, safi);    }  bgp_info_delete (rn, ri);  bgp_info_free (ri);  bgp_unlock_node (rn);}voidbgp_rib_withdraw (struct bgp_node *rn, struct bgp_info *ri, struct peer *peer,		  afi_t afi, safi_t safi, int force){  int valid;  int status = BGP_DAMP_NONE;  if (! CHECK_FLAG (ri->flags, BGP_INFO_HISTORY))    {      peer->pcount[afi][safi]--;      bgp_aggregate_decrement (peer->bgp, &rn->p, ri, afi, safi);    }  if (! force)    {      if (CHECK_FLAG (peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)	  && peer_sort (peer) == BGP_PEER_EBGP)	status = bgp_damp_withdraw (ri, rn, afi, safi, 0);      if (status == BGP_DAMP_SUPPRESSED)	return;    }  valid = CHECK_FLAG (ri->flags, BGP_INFO_VALID);  UNSET_FLAG (ri->flags, BGP_INFO_VALID);  bgp_process (peer->bgp, rn, afi, safi);  if (valid)    SET_FLAG (ri->flags, BGP_INFO_VALID);  if (status != BGP_DAMP_USED)    {      bgp_info_delete (rn, ri);      bgp_info_free (ri);      bgp_unlock_node (rn);    }}intbgp_update (struct peer *peer, struct prefix *p, struct attr *attr, 	    afi_t afi, safi_t safi, int type, int sub_type,	    struct prefix_rd *prd, u_char *tag, int soft_reconfig){  int ret;  int aspath_loop_count = 0;  struct bgp_node *rn;  struct bgp *bgp;  struct attr new_attr;  struct attr *attr_new;  struct bgp_info *ri;  struct bgp_info *new;  char *reason;  char buf[SU_ADDRSTRLEN];  bgp = peer->bgp;  rn = bgp_afi_node_get (bgp, afi, safi, p, prd);  /* When peer's soft reconfiguration enabled.  Record input packet in     Adj-RIBs-In.  */  if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)      && peer != bgp->peer_self && ! soft_reconfig)    bgp_adj_in_set (rn, peer, attr);  /* Check previously received route. */  for (ri = rn->info; ri; ri = ri->next)    if (ri->peer == peer && ri->type == type && ri->sub_type == sub_type)

⌨️ 快捷键说明

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