Beispiel #1
0
s32 bgp_fec_announce_6pe(struct zclient *zc, struct prefix *p, struct bgp_info *info, struct bgp *bgp)
{
    u32 flags = 0;
    struct stream * s  = zc->obuf ;
    struct peer * peer = info->peer ;
    u32 gateway ,label ;
    struct rtm_fec_info_key key;
    struct in6_addr *nexthop = NULL;

    if( !info || !info->attr || !info->attr->extra ) 
        return -1 ;
        
    if (info->attr->extra->mp_nexthop_len == 16)
    {
    	nexthop = &info->attr->extra->mp_nexthop_global;
    }  
    /* If both global and link-local address present. */
    else if (info->attr->extra->mp_nexthop_len == 32)
	{
	    /* Workaround for Cisco's nexthop bug.  */
	    if (IN6_IS_ADDR_UNSPECIFIED (&info->attr->extra->mp_nexthop_global)
	        && peer->su_remote->sa.sa_family == AF_INET6)
	    	nexthop = &peer->su_remote->sin6.sin6_addr;
	    else
	    	nexthop = &info->attr->extra->mp_nexthop_local;
	}
	if(NULL == nexthop || !IN6_IS_ADDR_V4MAPPED(nexthop))
	{
	    return -1;
	}
	memcpy (&gateway , ((s8 *)nexthop) + 12, 4);
    label  = decode_label ( bgp_info_extra_get(info)->tag) ;

    SET_FLAG(flags, ZAPI_FEC_GATEWAY);
    stream_reset(s);
    zclient_create_header(s,ZEBRA_MPLS_FEC6_INFO_ADD);
    stream_put_prefix(s,p);
	stream_putl(s, flags);
    stream_putl(s, ZEBRA_FEC_TYPE_6PE);
    if( peer )
        stream_putl(s,peer->nexthop.v4.s_addr);
    else
        stream_putl(s,0); // lsr_id = 0 
    stream_putl(s,label);
    stream_putl(s,gateway);

    stream_putw_at (s, 0, stream_get_endp (s));
    key.peer_addr = gateway;

    return rtm_fec_send(ZEBRA_MPLS_FEC6_INFO_ADD, zc, p, s, &key) ;
}
Beispiel #2
0
s32 bgp_fec_announce_6vpe(bgp_litevrf_config_t *litevrf, struct prefix *p, struct bgp_info *info)
{
    u32 flags = 0;
    struct stream * s  = zclient->obuf ;
    struct peer * peer = info->peer ;
    u32 gateway ,label ;
    struct rtm_fec_info_key key;
    struct in6_addr *nexthop = NULL;

    if( !info || !info->attr || !info->attr->extra ) 
        return -1 ;
        
    nexthop = &info->attr->extra->mp_nexthop_global;

    
	if(NULL == nexthop || !IN6_IS_ADDR_V4MAPPED(nexthop))
	{
	    return -1;
	}
	memcpy (&gateway , ((s8 *)nexthop) + 12, 4);
    label  = decode_label ( bgp_info_extra_get(info)->tag) ;

    SET_FLAG(flags, ZAPI_FEC_GATEWAY|ZAPI_FEC_LITEVRF);
    stream_reset(s);
    zclient_create_header(s,ZEBRA_MPLS_FEC6_INFO_ADD);
    stream_put_prefix(s,p);
	stream_putl(s, flags);
	stream_putl(s,litevrf->id);
    stream_putl(s, ZEBRA_FEC_TYPE_6VPE);
    if( peer )
        stream_putl(s,peer->nexthop.v4.s_addr);
    else
        stream_putl(s,0); // lsr_id = 0 
    stream_putl(s,label);
    stream_putl(s,gateway);

    stream_putw_at (s, 0, stream_get_endp (s));
    key.peer_addr = gateway;

    return rtm_fec_send(ZEBRA_MPLS_FEC6_INFO_ADD, zclient, p, s, &key) ;
}
Beispiel #3
0
/* A route becomes unreachable (RFC2439 Section 4.8.2).  */
int
bgp_damp_withdraw (struct bgp_info *binfo, struct bgp_node *rn,
		   afi_t afi, safi_t safi, int attr_change)
{
  time_t t_now;
  struct bgp_damp_info *bdi = NULL;
  double last_penalty = 0;
  
  t_now = bgp_clock ();

  /* Processing Unreachable Messages.  */
  if (binfo->extra)
    bdi = binfo->extra->damp_info;
  
  if (bdi == NULL)
    {
      /* If there is no previous stability history. */

      /* RFC2439 said:
	 1. allocate a damping structure.
         2. set figure-of-merit = 1.
         3. withdraw the route.  */

      bdi =  XCALLOC (MTYPE_BGP_DAMP_INFO, sizeof (struct bgp_damp_info));
      bdi->binfo = binfo;
      bdi->rn = rn;
      bdi->penalty = (attr_change ? DEFAULT_PENALTY / 2 : DEFAULT_PENALTY);
      bdi->flap = 1;
      bdi->start_time = t_now;
      bdi->suppress_time = 0;
      bdi->index = -1;
      bdi->afi = afi;
      bdi->safi = safi;
      (bgp_info_extra_get (binfo))->damp_info = bdi;
      BGP_DAMP_LIST_ADD (damp, bdi);
    }
  else
    {
      last_penalty = bdi->penalty;

      /* 1. Set t-diff = t-now - t-updated.  */
      bdi->penalty = 
	(bgp_damp_decay (t_now - bdi->t_updated, bdi->penalty) 
	 + (attr_change ? DEFAULT_PENALTY / 2 : DEFAULT_PENALTY));

      if (bdi->penalty > damp->ceiling)
	bdi->penalty = damp->ceiling;

      bdi->flap++;
    }
  
  assert ((rn == bdi->rn) && (binfo == bdi->binfo));
  
  bdi->lastrecord = BGP_RECORD_WITHDRAW;
  bdi->t_updated = t_now;

  /* Make this route as historical status.  */
  bgp_info_set_flag (rn, binfo, BGP_INFO_HISTORY);

  /* Remove the route from a reuse list if it is on one.  */
  if (CHECK_FLAG (bdi->binfo->flags, BGP_INFO_DAMPED))
    {
      /* If decay rate isn't equal to 0, reinsert brn. */  
      if (bdi->penalty != last_penalty)
	{
	  bgp_reuse_list_delete (bdi);
	  bgp_reuse_list_add (bdi);  
	}
      return BGP_DAMP_SUPPRESSED; 
    }

  /* If not suppressed before, do annonunce this withdraw and
     insert into reuse_list.  */
  if (bdi->penalty >= damp->suppress_value)
    {
      bgp_info_set_flag (rn, binfo, BGP_INFO_DAMPED);
      bdi->suppress_time = t_now;
      BGP_DAMP_LIST_DEL (damp, bdi);
      bgp_reuse_list_add (bdi);
    }

  return BGP_DAMP_USED;
}
Beispiel #4
0
/* Check specified next-hop is reachable or not. */
int
bgp_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)
    {
      if (ri->extra)
        ri->extra->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_table[AFI_IP], &p);

  if (rn->info)
    {
      bnc = rn->info;
      bgp_unlock_node (rn);
    }
  else
    {
      if (NULL == (bnc = zlookup_query (addr)))
	bnc = bnc_new ();
      else
	{
	  if (changed)
	    {
	      struct bgp_table *old;
	      struct bgp_node *oldrn;

	      if (bgp_nexthop_cache_table[AFI_IP] == cache1_table[AFI_IP])
		old = cache2_table[AFI_IP];
	      else
		old = cache1_table[AFI_IP];

	      oldrn = bgp_node_lookup (old, &p);
	      if (oldrn)
		{
		  struct bgp_nexthop_cache *oldbnc = oldrn->info;

		  bnc->changed = bgp_nexthop_cache_different (bnc, oldbnc);

		  if (bnc->metric != oldbnc->metric)
		    bnc->metricchanged = 1;

                  bgp_unlock_node (oldrn);
		}
	    }
	}
      rn->info = bnc;
    }

  if (changed)
    *changed = bnc->changed;

  if (metricchanged)
    *metricchanged = bnc->metricchanged;

  if (bnc->valid && bnc->metric)
    (bgp_info_extra_get(ri))->igpmetric = bnc->metric;
  else if (ri->extra)
    ri->extra->igpmetric = 0;

  return bnc->valid;
}
Beispiel #5
0
/* Check specified next-hop is reachable or not. */
static int
bgp_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)
    {
      if (ri->extra)
        ri->extra->igpmetric = 0;
      return 1;
    }
  
  /* Only check IPv6 global address only nexthop. */
  attr = ri->attr;

  if (attr->extra->mp_nexthop_len != 16 
      || IN6_IS_ADDR_LINKLOCAL (&attr->extra->mp_nexthop_global))
    return 1;

  memset (&p, 0, sizeof (struct prefix));
  p.family = AF_INET6;
  p.prefixlen = IPV6_MAX_BITLEN;
  p.u.prefix6 = attr->extra->mp_nexthop_global;

  /* IBGP or ebgp-multihop */
  rn = bgp_node_get (bgp_nexthop_cache_table[AFI_IP6], &p);

  if (rn->info)
    {
      bnc = rn->info;
      bgp_unlock_node (rn);
    }
  else
    {
      if (NULL == (bnc = zlookup_query_ipv6 (&attr->extra->mp_nexthop_global)))
	bnc = bnc_new ();
      else
	{
	  if (changed)
	    {
	      struct bgp_table *old;
	      struct bgp_node *oldrn;

	      if (bgp_nexthop_cache_table[AFI_IP6] == cache1_table[AFI_IP6])
		old = cache2_table[AFI_IP6];
	      else
		old = cache1_table[AFI_IP6];

	      oldrn = bgp_node_lookup (old, &p);
	      if (oldrn)
		{
		  struct bgp_nexthop_cache *oldbnc = oldrn->info;

		  bnc->changed = bgp_nexthop_cache_different (bnc, oldbnc);

		  if (bnc->metric != oldbnc->metric)
		    bnc->metricchanged = 1;

                  bgp_unlock_node (oldrn);
		}
	    }
	}
      rn->info = bnc;
    }

  if (changed)
    *changed = bnc->changed;

  if (metricchanged)
    *metricchanged = bnc->metricchanged;

  if (bnc->valid && bnc->metric)
    (bgp_info_extra_get (ri))->igpmetric = bnc->metric;
  else if (ri->extra)
    ri->extra->igpmetric = 0;

  return bnc->valid;
}