Beispiel #1
0
/* Send requests to zebra daemon for the information in a VRF. */
void
zclient_send_requests (struct zclient *zclient, vrf_id_t vrf_id)
{
  int i;

  /* zclient is disabled. */
  if (! zclient->enable)
    return;

  /* If not connected to the zebra yet. */
  if (zclient->sock < 0)
    return;

  if (zclient_debug)
    zlog_debug ("%s: send messages for VRF %u", __func__, vrf_id);

  /* We need router-id information. */
  zebra_message_send (zclient, ZEBRA_ROUTER_ID_ADD, vrf_id);

  /* We need interface information. */
  zebra_message_send (zclient, ZEBRA_INTERFACE_ADD, vrf_id);

  /* Set unwanted redistribute route. */
  vrf_bitmap_set (zclient->redist[zclient->redist_default], vrf_id);

  /* Flush all redistribute request. */
  for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
    if (i != zclient->redist_default &&
        vrf_bitmap_check (zclient->redist[i], vrf_id))
      zebra_redistribute_send (ZEBRA_REDISTRIBUTE_ADD, zclient, i, vrf_id);

  /* If default information is needed. */
  if (vrf_bitmap_check (zclient->default_information, VRF_DEFAULT))
    zebra_message_send (zclient, ZEBRA_REDISTRIBUTE_DEFAULT_ADD, vrf_id);
}
Beispiel #2
0
int eigrp_is_type_redistributed(int type)
{
	return ((DEFAULT_ROUTE_TYPE(type))
			? vrf_bitmap_check(zclient->default_information,
					   VRF_DEFAULT)
			: vrf_bitmap_check(zclient->redist[AFI_IP][type],
					   VRF_DEFAULT));
}
Beispiel #3
0
/* Check LSA is related to external info. */
struct external_info *ospf_external_info_check(struct ospf *ospf,
					       struct ospf_lsa *lsa)
{
	struct as_external_lsa *al;
	struct prefix_ipv4 p;
	struct route_node *rn;
	int type;

	al = (struct as_external_lsa *)lsa->data;

	p.family = AF_INET;
	p.prefix = lsa->data->id;
	p.prefixlen = ip_masklen(al->mask);

	for (type = 0; type < ZEBRA_ROUTE_MAX; type++) {
		int redist_on = 0;

		redist_on =
			is_prefix_default(&p)
				? vrf_bitmap_check(zclient->default_information,
						   ospf->vrf_id)
				: (zclient->mi_redist[AFI_IP][type].enabled
				   || vrf_bitmap_check(
					      zclient->redist[AFI_IP][type],
					      ospf->vrf_id));
		// Pending: check for MI above.
		if (redist_on) {
			struct list *ext_list;
			struct listnode *node;
			struct ospf_external *ext;

			ext_list = ospf->external[type];
			if (!ext_list)
				continue;

			for (ALL_LIST_ELEMENTS_RO(ext_list, node, ext)) {
				rn = NULL;
				if (ext->external_info)
					rn = route_node_lookup(
						ext->external_info,
						(struct prefix *)&p);
				if (rn) {
					route_unlock_node(rn);
					if (rn->info != NULL)
						return (struct external_info *)
							rn->info;
				}
			}
		}
	}

	return NULL;
}
Beispiel #4
0
/* Send ECMP routes to zebra. */
static void
rip_zebra_ipv4_send (struct route_node *rp, u_char cmd)
{
  static struct in_addr **nexthops = NULL;
  static unsigned int nexthops_len = 0;

  struct list *list = (struct list *)rp->info;
  struct zapi_ipv4 api;
  struct listnode *listnode = NULL;
  struct rip_info *rinfo = NULL;
  int count = 0;

  if (vrf_bitmap_check (zclient->redist[ZEBRA_ROUTE_RIP], VRF_DEFAULT))
    {
      api.vrf_id = VRF_DEFAULT;
      api.type = ZEBRA_ROUTE_RIP;
      api.flags = 0;
      api.message = 0;
      api.safi = SAFI_UNICAST;

      if (nexthops_len < listcount (list))
        {
          nexthops_len = listcount (list);
          nexthops = XREALLOC (MTYPE_TMP, nexthops,
                               nexthops_len * sizeof (struct in_addr *));
        }

      SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
      for (ALL_LIST_ELEMENTS_RO (list, listnode, rinfo))
        {
          nexthops[count++] = &rinfo->nexthop;
          if (cmd == ZEBRA_IPV4_ROUTE_ADD)
            SET_FLAG (rinfo->flags, RIP_RTF_FIB);
          else
            UNSET_FLAG (rinfo->flags, RIP_RTF_FIB);
        }

      api.nexthop = nexthops;
      api.nexthop_num = count;
      api.ifindex_num = 0;

      rinfo = listgetdata (listhead (list));

      SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
      api.metric = rinfo->metric;

      if (rinfo->distance && rinfo->distance != ZEBRA_RIP_DISTANCE_DEFAULT)
        {
          SET_FLAG (api.message, ZAPI_MESSAGE_DISTANCE);
          api.distance = rinfo->distance;
        }

      zapi_ipv4_route (cmd, zclient,
                       (struct prefix_ipv4 *)&rp->p, &api);

      rip_global_route_changes++;
    }
Beispiel #5
0
void
zclient_redistribute_default (int command, struct zclient *zclient,
    vrf_id_t vrf_id)
{

  if (command == ZEBRA_REDISTRIBUTE_DEFAULT_ADD)
    {
      if (vrf_bitmap_check (zclient->default_information, vrf_id))
        return;
      vrf_bitmap_set (zclient->default_information, vrf_id);
    }
  else 
    {
      if (!vrf_bitmap_check (zclient->default_information, vrf_id))
        return;
      vrf_bitmap_unset (zclient->default_information, vrf_id);
    }

  if (zclient->sock > 0)
    zebra_message_send (zclient, command, vrf_id);
}
Beispiel #6
0
void
zclient_redistribute (int command, struct zclient *zclient, int type,
    vrf_id_t vrf_id)
{

  if (command == ZEBRA_REDISTRIBUTE_ADD) 
    {
      if (vrf_bitmap_check (zclient->redist[type], vrf_id))
         return;
      vrf_bitmap_set (zclient->redist[type], vrf_id);
    }
  else
    {
      if (!vrf_bitmap_check (zclient->redist[type], vrf_id))
         return;
      vrf_bitmap_unset (zclient->redist[type], vrf_id);
    }

  if (zclient->sock > 0)
    zebra_redistribute_send (command, zclient, type, vrf_id);
}
Beispiel #7
0
/* Unset redistribution.  */
int
bgp_redistribute_unset (struct bgp *bgp, afi_t afi, int type)
{
  /* Unset flag from BGP instance. */
  bgp->redist[afi][type] = 0;

  /* Unset route-map. */
  if (bgp->rmap[afi][type].name)
    free (bgp->rmap[afi][type].name);
  bgp->rmap[afi][type].name = NULL;
  bgp->rmap[afi][type].map = NULL;

  /* Unset metric. */
  bgp->redist_metric_flag[afi][type] = 0;
  bgp->redist_metric[afi][type] = 0;

  /* Return if zebra connection is disabled. */
  if (! vrf_bitmap_check (zclient->redist[type], VRF_DEFAULT))
    return CMD_WARNING;
  vrf_bitmap_unset (zclient->redist[type], VRF_DEFAULT);

  if (bgp->redist[AFI_IP][type] == 0 
      && bgp->redist[AFI_IP6][type] == 0 
      && zclient->sock >= 0)
    {
      /* Send distribute delete message to zebra. */
      if (BGP_DEBUG(zebra, ZEBRA))
	zlog_debug("Zebra send: redistribute delete %s",
		   zebra_route_string(type));
      zebra_redistribute_send (ZEBRA_REDISTRIBUTE_DELETE, zclient, type,
                               VRF_DEFAULT);
    }
  
  /* Withdraw redistributed routes from current BGP's routing table. */
  bgp_redistribute_withdraw (bgp, afi, type);

  return CMD_SUCCESS;
}
Beispiel #8
0
/* Other routes redistribution into BGP. */
int
bgp_redistribute_set (struct bgp *bgp, afi_t afi, int type)
{
  /* Set flag to BGP instance. */
  bgp->redist[afi][type] = 1;

  /* Return if already redistribute flag is set. */
  if (vrf_bitmap_check (zclient->redist[type], VRF_DEFAULT))
    return CMD_WARNING;

  vrf_bitmap_set (zclient->redist[type], VRF_DEFAULT);

  /* Return if zebra connection is not established. */
  if (zclient->sock < 0)
    return CMD_WARNING;

  if (BGP_DEBUG(zebra, ZEBRA))
    zlog_debug("Zebra send: redistribute add %s", zebra_route_string(type));
    
  /* Send distribute add message to zebra. */
  zebra_redistribute_send (ZEBRA_REDISTRIBUTE_ADD, zclient, type, VRF_DEFAULT);

  return CMD_SUCCESS;
}
Beispiel #9
0
void
ospf_zebra_add (struct prefix_ipv4 *p, struct ospf_route *or)
{
  u_char message;
  u_char distance;
  u_char flags;
  int psize;
  struct stream *s;
  struct ospf_path *path;
  struct listnode *node;

  if (vrf_bitmap_check (zclient->redist[ZEBRA_ROUTE_OSPF], VRF_DEFAULT))
    {
      message = 0;
      flags = 0;

      /* OSPF pass nexthop and metric */
      SET_FLAG (message, ZAPI_MESSAGE_NEXTHOP);
      SET_FLAG (message, ZAPI_MESSAGE_METRIC);

      /* Distance value. */
      distance = ospf_distance_apply (p, or);
      if (distance)
        SET_FLAG (message, ZAPI_MESSAGE_DISTANCE);

      /* Make packet. */
      s = zclient->obuf;
      stream_reset (s);

      /* Put command, type, flags, message. */
      zclient_create_header (s, ZEBRA_IPV4_ROUTE_ADD, VRF_DEFAULT);
      stream_putc (s, ZEBRA_ROUTE_OSPF);
      stream_putc (s, flags);
      stream_putc (s, message);
      stream_putw (s, SAFI_UNICAST);

      /* Put prefix information. */
      psize = PSIZE (p->prefixlen);
      stream_putc (s, p->prefixlen);
      stream_write (s, (u_char *) & p->prefix, psize);

      /* Nexthop count. */
      stream_putc (s, or->paths->count);

      /* Nexthop, ifindex, distance and metric information. */
      for (ALL_LIST_ELEMENTS_RO (or->paths, node, path))
        {
          if (path->nexthop.s_addr != INADDR_ANY &&
	      path->ifindex != 0)
            {
              stream_putc (s, ZEBRA_NEXTHOP_IPV4_IFINDEX);
              stream_put_in_addr (s, &path->nexthop);
	      stream_putl (s, path->ifindex);
            }
          else if (path->nexthop.s_addr != INADDR_ANY)
            {
              stream_putc (s, ZEBRA_NEXTHOP_IPV4);
              stream_put_in_addr (s, &path->nexthop);
            }
          else
            {
              stream_putc (s, ZEBRA_NEXTHOP_IFINDEX);
              if (path->ifindex)
                stream_putl (s, path->ifindex);
              else
                stream_putl (s, 0);
            }

          if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
            {
	      char buf[2][INET_ADDRSTRLEN];
	      zlog_debug("Zebra: Route add %s/%d nexthop %s",
			 inet_ntop(AF_INET, &p->prefix,
				   buf[0], sizeof(buf[0])),
			 p->prefixlen,
			 inet_ntop(AF_INET, &path->nexthop,
				   buf[1], sizeof(buf[1])));
            }
        }

      if (CHECK_FLAG (message, ZAPI_MESSAGE_DISTANCE))
        stream_putc (s, distance);
      if (CHECK_FLAG (message, ZAPI_MESSAGE_METRIC))
        {
          if (or->path_type == OSPF_PATH_TYPE1_EXTERNAL)
            stream_putl (s, or->cost + or->u.ext.type2_cost);
          else if (or->path_type == OSPF_PATH_TYPE2_EXTERNAL)
            stream_putl (s, or->u.ext.type2_cost);
          else
            stream_putl (s, or->cost);
        }

      stream_putw_at (s, 0, stream_get_endp (s));

      zclient_send_message(zclient);
    }
Beispiel #10
0
static void
isis_zebra_route_add_ipv4 (struct prefix *prefix,
			   struct isis_route_info *route_info)
{
  u_char message, flags;
  int psize;
  struct stream *stream;
  struct isis_nexthop *nexthop;
  struct listnode *node;

  if (CHECK_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
    return;

  if (vrf_bitmap_check (zclient->redist[ZEBRA_ROUTE_ISIS], VRF_DEFAULT))
    {
      message = 0;
      flags = 0;

      SET_FLAG (message, ZAPI_MESSAGE_NEXTHOP);
      SET_FLAG (message, ZAPI_MESSAGE_METRIC);
#if 0
      SET_FLAG (message, ZAPI_MESSAGE_DISTANCE);
#endif

      stream = zclient->obuf;
      stream_reset (stream);
      zclient_create_header (stream, ZEBRA_IPV4_ROUTE_ADD, VRF_DEFAULT);
      /* type */
      stream_putc (stream, ZEBRA_ROUTE_ISIS);
      /* flags */
      stream_putc (stream, flags);
      /* message */
      stream_putc (stream, message);
      /* SAFI */
      stream_putw (stream, SAFI_UNICAST);
      /* prefix information */
      psize = PSIZE (prefix->prefixlen);
      stream_putc (stream, prefix->prefixlen);
      stream_write (stream, (u_char *) & prefix->u.prefix4, psize);

      stream_putc (stream, listcount (route_info->nexthops));

      /* Nexthop, ifindex, distance and metric information */
      for (ALL_LIST_ELEMENTS_RO (route_info->nexthops, node, nexthop))
	{
	  /* FIXME: can it be ? */
	  if (nexthop->ip.s_addr != INADDR_ANY)
	    {
	      stream_putc (stream, ZEBRA_NEXTHOP_IPV4);
	      stream_put_in_addr (stream, &nexthop->ip);
	    }
	  else
	    {
	      stream_putc (stream, ZEBRA_NEXTHOP_IFINDEX);
	      stream_putl (stream, nexthop->ifindex);
	    }
	}
#if 0
      if (CHECK_FLAG (message, ZAPI_MESSAGE_DISTANCE))
	stream_putc (stream, route_info->depth);
#endif
      if (CHECK_FLAG (message, ZAPI_MESSAGE_METRIC))
	stream_putl (stream, route_info->cost);

      stream_putw_at (stream, 0, stream_get_endp (stream));
      zclient_send_message(zclient);
      SET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
      UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC);
    }
Beispiel #11
0
void
bgp_zebra_withdraw (struct prefix *p, struct bgp_info *info, safi_t safi)
{
  int flags;
  struct peer *peer;

  if (zclient->sock < 0)
    return;

  if (! vrf_bitmap_check (zclient->redist[ZEBRA_ROUTE_BGP], VRF_DEFAULT))
    return;

  peer = info->peer;
  flags = 0;

  if (peer->sort == BGP_PEER_IBGP)
    {
      SET_FLAG (flags, ZEBRA_FLAG_INTERNAL);
      SET_FLAG (flags, ZEBRA_FLAG_IBGP);
    }

  if ((peer->sort == BGP_PEER_EBGP && peer_ttl (peer) != 1)
      || CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
    SET_FLAG (flags, ZEBRA_FLAG_INTERNAL);

  if (p->family == AF_INET)
    {
      struct zapi_ipv4 api;

      api.vrf_id = VRF_DEFAULT;
      api.flags = flags;

      api.type = ZEBRA_ROUTE_BGP;
      api.message = 0;
      api.safi = safi;
      api.nexthop_num = 0;
      api.ifindex_num = 0;
      SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
      api.metric = info->attr->med;

      if ((info->attr->extra) && (info->attr->extra->tag != 0))
        {
          SET_FLAG(api.message, ZAPI_MESSAGE_TAG);
          api.tag = info->attr->extra->tag;
        }

      if (BGP_DEBUG(zebra, ZEBRA))
	{
	  char buf[2][INET_ADDRSTRLEN];
	  zlog_debug("Zebra send: IPv4 route delete %s/%d metric %u tag %d",
		     inet_ntop(AF_INET, &p->u.prefix4, buf[0], sizeof(buf[0])),
		     p->prefixlen,
		     api.metric,
		     api.tag);
	}

      zapi_ipv4_route (ZEBRA_IPV4_ROUTE_DELETE, zclient, 
                       (struct prefix_ipv4 *) p, &api);
    }

  /* We have to think about a IPv6 link-local address curse. */
  if (p->family == AF_INET6)
    {
      struct zapi_ipv6 api;
      
      api.vrf_id = VRF_DEFAULT;
      api.flags = flags;
      api.type = ZEBRA_ROUTE_BGP;
      api.message = 0;
      api.safi = safi;
      api.nexthop_num = 0;
      api.ifindex_num = 0;
      SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
      api.metric = info->attr->med;

      if ((info->attr->extra) && (info->attr->extra->tag != 0))
        {
          SET_FLAG(api.message, ZAPI_MESSAGE_TAG);
          api.tag = info->attr->extra->tag;
        }

      if (BGP_DEBUG(zebra, ZEBRA))
	{
	  char buf[2][INET6_ADDRSTRLEN];
	  zlog_debug("Zebra send: IPv6 route delete %s/%d metric %u tag %d",
		     inet_ntop(AF_INET6, &p->u.prefix6, buf[0], sizeof(buf[0])),
		     p->prefixlen,
		     api.metric,
		     api.tag);
	}

      zapi_ipv6_route (ZEBRA_IPV6_ROUTE_DELETE, zclient, 
                       (struct prefix_ipv6 *) p, &api);
    }
}
Beispiel #12
0
void
bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp, safi_t safi)
{
  int flags;
  u_char distance;
  struct peer *peer;
  struct bgp_info *mpinfo;
  size_t oldsize, newsize;
  u_int32_t nhcount;
  route_tag_t tag = 0;

  if (zclient->sock < 0)
    return;

  if (! vrf_bitmap_check (zclient->redist[ZEBRA_ROUTE_BGP], VRF_DEFAULT))
    return;

  flags = 0;
  peer = info->peer;

  if ((info->attr->extra) && (info->attr->extra->tag != 0))
    tag = info->attr->extra->tag;

  if (peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
    {
      SET_FLAG (flags, ZEBRA_FLAG_IBGP);
      SET_FLAG (flags, ZEBRA_FLAG_INTERNAL);
    }

  if ((peer->sort == BGP_PEER_EBGP && peer_ttl (peer) != 1)
      || CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
    SET_FLAG (flags, ZEBRA_FLAG_INTERNAL);

  nhcount = 1 + bgp_info_mpath_count (info);

  if (p->family == AF_INET)
    {
      struct zapi_ipv4 api;
      struct in_addr *nexthop;

      /* resize nexthop buffer size if necessary */
      if ((oldsize = stream_get_size (bgp_nexthop_buf)) <
          (sizeof (struct in_addr *) * nhcount))
        {
          newsize = (sizeof (struct in_addr *) * nhcount);
          newsize = stream_resize (bgp_nexthop_buf, newsize);
          if (newsize == oldsize)
            {
	          zlog_err ("can't resize nexthop buffer");
	          return;
            }
        }
      stream_reset (bgp_nexthop_buf);

      api.vrf_id = VRF_DEFAULT;
      api.flags = flags;
      nexthop = &info->attr->nexthop;
      stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in_addr *));
      for (mpinfo = bgp_info_mpath_first (info); mpinfo;
	   mpinfo = bgp_info_mpath_next (mpinfo))
	{
	  nexthop = &mpinfo->attr->nexthop;
	  stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in_addr *));
	}

      api.type = ZEBRA_ROUTE_BGP;
      api.message = 0;
      api.safi = safi;
      SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
      api.nexthop_num = nhcount;
      api.nexthop = (struct in_addr **)STREAM_DATA (bgp_nexthop_buf);
      api.ifindex_num = 0;
      SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
      api.metric = info->attr->med;

      if (tag)
        {
          SET_FLAG (api.message, ZAPI_MESSAGE_TAG);
          api.tag = tag;
        }

      distance = bgp_distance_apply (p, info, bgp);

      if (distance)
	{
	  SET_FLAG (api.message, ZAPI_MESSAGE_DISTANCE);
	  api.distance = distance;
	}

      if (BGP_DEBUG(zebra, ZEBRA))
	{
	  int i;
	  char buf[2][INET_ADDRSTRLEN];
	  zlog_debug("Zebra send: IPv4 route add %s/%d nexthop %s metric %u"
	             " tag %u count %d",
		     inet_ntop(AF_INET, &p->u.prefix4, buf[0], sizeof(buf[0])),
		     p->prefixlen,
		     inet_ntop(AF_INET, api.nexthop[0], buf[1], sizeof(buf[1])),
		     api.metric, api.tag, api.nexthop_num);
	  for (i = 1; i < api.nexthop_num; i++)
	    zlog_debug("Zebra send: IPv4 route add [nexthop %d] %s",
		       i, inet_ntop(AF_INET, api.nexthop[i], buf[1],
				    sizeof(buf[1])));
	}

      zapi_ipv4_route (ZEBRA_IPV4_ROUTE_ADD, zclient, 
                       (struct prefix_ipv4 *) p, &api);
    }

  /* We have to think about a IPv6 link-local address curse. */
  if (p->family == AF_INET6)
    {
      ifindex_t ifindex;
      struct in6_addr *nexthop;
      struct zapi_ipv6 api;
      int valid_nh_count = 0;

      /* resize nexthop buffer size if necessary */
      if ((oldsize = stream_get_size (bgp_nexthop_buf)) <
          (sizeof (struct in6_addr *) * nhcount))
        {
          newsize = (sizeof (struct in6_addr *) * nhcount);
          newsize = stream_resize (bgp_nexthop_buf, newsize);
          if (newsize == oldsize)
            {
              zlog_err ("can't resize nexthop buffer");
              return;
            }
        }
      stream_reset (bgp_nexthop_buf);

      /* resize ifindices buffer size if necessary */
      if ((oldsize = stream_get_size (bgp_ifindices_buf)) <
          (sizeof (unsigned int) * nhcount))
        {
          newsize = (sizeof (unsigned int) * nhcount);
          newsize = stream_resize (bgp_ifindices_buf, newsize);
          if (newsize == oldsize)
            {
              zlog_err ("can't resize nexthop buffer");
              return;
            }
        }
      stream_reset (bgp_ifindices_buf);

      ifindex = 0;
      nexthop = NULL;

      assert (info->attr->extra);
      
      /* Only global address nexthop exists. */
      if (info->attr->extra->mp_nexthop_len == 16)
	nexthop = &info->attr->extra->mp_nexthop_global;
      
      /* If both global and link-local address present. */
      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 (info->peer->nexthop.ifp)
	    ifindex = info->peer->nexthop.ifp->ifindex;
	}

      if (nexthop == NULL)
	return;

      if (!ifindex)
	{
	  if (info->peer->ifname)
	    ifindex = ifname2ifindex (info->peer->ifname);
	  else if (info->peer->nexthop.ifp)
	    ifindex = info->peer->nexthop.ifp->ifindex;
	}
      stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in6_addr *));
      stream_put (bgp_ifindices_buf, &ifindex, sizeof (unsigned int));
      valid_nh_count++;

      for (mpinfo = bgp_info_mpath_first (info); mpinfo;
           mpinfo = bgp_info_mpath_next (mpinfo))
	{
	  ifindex = 0;

          /* Only global address nexthop exists. */
          if (mpinfo->attr->extra->mp_nexthop_len == 16)
              nexthop = &mpinfo->attr->extra->mp_nexthop_global;

          /* If both global and link-local address present. */
	  if (mpinfo->attr->extra->mp_nexthop_len == 32)
            {
              /* Workaround for Cisco's nexthop bug.  */
              if (IN6_IS_ADDR_UNSPECIFIED (&mpinfo->attr->extra->mp_nexthop_global)
                  && mpinfo->peer->su_remote->sa.sa_family == AF_INET6)
                {
		  nexthop = &mpinfo->peer->su_remote->sin6.sin6_addr;
                }
              else
                {
		  nexthop = &mpinfo->attr->extra->mp_nexthop_local;
	        }

              if (mpinfo->peer->nexthop.ifp)
                {
                  ifindex = mpinfo->peer->nexthop.ifp->ifindex;
                }
            }

	  if (nexthop == NULL)
	    {
	      continue;
	    }

          if (!ifindex)
	    {
	      if (mpinfo->peer->ifname)
                {
		  ifindex = if_nametoindex (mpinfo->peer->ifname);
		}
	      else if (mpinfo->peer->nexthop.ifp)
		{
		  ifindex = mpinfo->peer->nexthop.ifp->ifindex;
		}
	    }

	  if (ifindex == 0)
	    {
	      continue;
	    }

          stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in6_addr *));
          stream_put (bgp_ifindices_buf, &ifindex, sizeof (unsigned int));
          valid_nh_count++;
	}

      /* Make Zebra API structure. */
      api.vrf_id = VRF_DEFAULT;
      api.flags = flags;
      api.type = ZEBRA_ROUTE_BGP;
      api.message = 0;
      api.safi = safi;
      SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
      api.nexthop_num = valid_nh_count;
      api.nexthop = (struct in6_addr **)STREAM_DATA (bgp_nexthop_buf);
      SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX);
      api.ifindex_num = valid_nh_count;
      api.ifindex = (ifindex_t *)STREAM_DATA (bgp_ifindices_buf);
      SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
      api.metric = info->attr->med;

      distance = ipv6_bgp_distance_apply (p, info, bgp);

      if (distance)
        {
          SET_FLAG (api.message, ZAPI_MESSAGE_DISTANCE);
          api.distance = distance;
        }
      
      if (tag)
	{
	  SET_FLAG (api.message, ZAPI_MESSAGE_TAG);
	  api.tag = tag;
	}

      if (BGP_DEBUG(zebra, ZEBRA))
	{
	  char buf[2][INET6_ADDRSTRLEN];
	  zlog_debug("Zebra send: IPv6 route add %s/%d nexthop %s metric %u"
                     " tag %u",
		     inet_ntop(AF_INET6, &p->u.prefix6, buf[0], sizeof(buf[0])),
		     p->prefixlen,
		     inet_ntop(AF_INET6, nexthop, buf[1], sizeof(buf[1])),
		     api.metric, api.tag);
	}

      zapi_ipv6_route (ZEBRA_IPV6_ROUTE_ADD, zclient, 
                       (struct prefix_ipv6 *) p, &api);
    }
}
Beispiel #13
0
/* Send ECMP routes to zebra. */
static void
ripng_zebra_ipv6_send (struct route_node *rp, u_char cmd)
{
  static struct in6_addr **nexthops = NULL;
  static unsigned int *ifindexes = NULL;
  static unsigned int nexthops_len = 0;

  struct list *list = (struct list *)rp->info;
  struct zapi_ipv6 api;
  struct listnode *listnode = NULL;
  struct ripng_info *rinfo = NULL;
  int count = 0;

  if (vrf_bitmap_check (zclient->redist[ZEBRA_ROUTE_RIPNG], VRF_DEFAULT))
    {
      api.vrf_id = VRF_DEFAULT;
      api.type = ZEBRA_ROUTE_RIPNG;
      api.flags = 0;
      api.message = 0;
      api.safi = SAFI_UNICAST;

      if (nexthops_len < listcount (list))
        {
          nexthops_len = listcount (list);
          nexthops = XREALLOC (MTYPE_TMP, nexthops,
                               nexthops_len * sizeof (struct in6_addr *));
          ifindexes = XREALLOC (MTYPE_TMP, ifindexes,
                                nexthops_len * sizeof (unsigned int));
        }

      SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
      SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX);
      for (ALL_LIST_ELEMENTS_RO (list, listnode, rinfo))
        {
          nexthops[count] = &rinfo->nexthop;
          ifindexes[count] = rinfo->ifindex;
          count++;
          if (cmd == ZEBRA_IPV6_ROUTE_ADD)
            SET_FLAG (rinfo->flags, RIPNG_RTF_FIB);
          else
            UNSET_FLAG (rinfo->flags, RIPNG_RTF_FIB);
        }

      api.nexthop = nexthops;
      api.nexthop_num = count;
      api.ifindex = ifindexes;
      api.ifindex_num = count;

      rinfo = listgetdata (listhead (list));

      SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
      api.metric = rinfo->metric;

      zapi_ipv6_route (cmd, zclient,
                       (struct prefix_ipv6 *)&rp->p, &api);

      if (IS_RIPNG_DEBUG_ZEBRA)
        {
          if (ripng->ecmp)
            zlog_debug ("%s: %s/%d nexthops %d",
                        (cmd == ZEBRA_IPV6_ROUTE_ADD) ? \
                            "Install into zebra" : "Delete from zebra",
                        inet6_ntoa (rp->p.u.prefix6), rp->p.prefixlen, count);
          else
            zlog_debug ("%s: %s/%d",
                        (cmd == ZEBRA_IPV6_ROUTE_ADD) ? \
                            "Install into zebra" : "Delete from zebra",
                        inet6_ntoa (rp->p.u.prefix6), rp->p.prefixlen);
        }
    }