Example #1
0
static void
add_nexthops(ip_route_t *route, struct nlmsghdr *nlh, struct rtmsg *rtm)
{
	char buf[ENCAP_RTA_SIZE];
	struct rtattr *rta = (void *)buf;
	struct rtnexthop *rtnh;
	nexthop_t *nh;
	element e;

	rta->rta_type = RTA_MULTIPATH;
	rta->rta_len = RTA_LENGTH(0);
	rtnh = RTA_DATA(rta);

	for (e = LIST_HEAD(route->nhs); e; ELEMENT_NEXT(e)) {
		nh = ELEMENT_DATA(e);

		memset(rtnh, 0, sizeof(*rtnh));
		rtnh->rtnh_len = sizeof(*rtnh);
		rta->rta_len += rtnh->rtnh_len;
		add_nexthop(nh, nlh, rtm, rta, sizeof(buf), rtnh);
		rtnh = RTNH_NEXT(rtnh);
	}

	if (rta->rta_len > RTA_LENGTH(0))
		addattr_l(nlh, sizeof(buf), RTA_MULTIPATH, RTA_DATA(rta), RTA_PAYLOAD(rta));
}
Example #2
0
/*
 * create_add_route_message
 */
static Fpm__AddRoute *create_add_route_message(qpb_allocator_t *allocator,
					       rib_dest_t *dest,
					       struct route_entry *re)
{
	Fpm__AddRoute *msg;
	struct nexthop *nexthop;
	uint num_nhs, u;
	struct nexthop *nexthops[MULTIPATH_NUM];

	msg = QPB_ALLOC(allocator, typeof(*msg));
	if (!msg) {
		assert(0);
		return NULL;
	}

	fpm__add_route__init(msg);

	msg->vrf_id = zvrf_id(rib_dest_vrf(dest));

	qpb_address_family_set(&msg->address_family, rib_dest_af(dest));

	/*
	 * XXX Hardcode subaddress family for now.
	 */
	msg->sub_address_family = QPB__SUB_ADDRESS_FAMILY__UNICAST;
	msg->key = fpm_route_key_create(allocator, rib_dest_prefix(dest));
	qpb_protocol_set(&msg->protocol, re->type);
	msg->has_route_type = 1;
	msg->route_type = FPM__ROUTE_TYPE__NORMAL;
	msg->metric = re->metric;

	/*
	 * Figure out the set of nexthops to be added to the message.
	 */
	num_nhs = 0;
	for (ALL_NEXTHOPS(re->ng, nexthop)) {
		if (num_nhs >= multipath_num)
			break;

		if (num_nhs >= ZEBRA_NUM_OF(nexthops))
			break;

		if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE) {
			switch (nexthop->bh_type) {
			case BLACKHOLE_REJECT:
				msg->route_type = FPM__ROUTE_TYPE__UNREACHABLE;
				break;
			case BLACKHOLE_NULL:
			default:
				msg->route_type = FPM__ROUTE_TYPE__BLACKHOLE;
				break;
			}
			return msg;
		}

		if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
			continue;

		if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
			continue;

		nexthops[num_nhs] = nexthop;
		num_nhs++;
	}

	if (!num_nhs) {
		zfpm_debug("netlink_encode_route(): No useful nexthop.");
		assert(0);
		return NULL;
	}

	/*
	 * And add them to the message.
	 */
	if (!(msg->nexthops = qpb_alloc_ptr_array(allocator, num_nhs))) {
		assert(0);
		return NULL;
	}

	msg->n_nexthops = 0;
	for (u = 0; u < num_nhs; u++) {
		if (!add_nexthop(allocator, msg, dest, nexthops[u])) {
			assert(0);
			return NULL;
		}
	}

	assert(msg->n_nexthops == num_nhs);

	return msg;
}
/*
 * create_add_route_message
 */
static Fpm__AddRoute *
create_add_route_message (qpb_allocator_t *allocator, rib_dest_t *dest,
			  struct rib *rib)
{
  Fpm__AddRoute *msg;
  int discard;
  struct nexthop *nexthop, *tnexthop;
  int recursing;
  uint num_nhs, u;
  struct nexthop *nexthops[MAX (MULTIPATH_NUM, 64)];

  msg = QPB_ALLOC(allocator, typeof(*msg));
  if (!msg) {
    assert(0);
    return NULL;
  }

  fpm__add_route__init(msg);

  msg->vrf_id = rib_dest_vrf(dest)->vrf_id;

  qpb_address_family_set (&msg->address_family, rib_dest_af(dest));

  /*
   * XXX Hardcode subaddress family for now.
   */
  msg->sub_address_family = QPB__SUB_ADDRESS_FAMILY__UNICAST;
  msg->key = fpm_route_key_create (allocator, rib_dest_prefix(dest));
  qpb_protocol_set (&msg->protocol, rib->type);

  if ((rib->flags & ZEBRA_FLAG_BLACKHOLE) || (rib->flags & ZEBRA_FLAG_REJECT))
    discard = 1;
  else
    discard = 0;

  if (discard)
    {
      if (rib->flags & ZEBRA_FLAG_BLACKHOLE) {
	msg->route_type = FPM__ROUTE_TYPE__BLACKHOLE;
      } else if (rib->flags & ZEBRA_FLAG_REJECT) {
	msg->route_type = FPM__ROUTE_TYPE__UNREACHABLE;
      } else {
	assert (0);
      }
      return msg;
    }
  else {
    msg->route_type = FPM__ROUTE_TYPE__NORMAL;
  }

  msg->metric = rib->metric;

  /*
   * Figure out the set of nexthops to be added to the message.
   */
  num_nhs = 0;
  for (ALL_NEXTHOPS_RO (rib->nexthop, nexthop, tnexthop, recursing))
    {
      if (MULTIPATH_NUM != 0 && num_nhs >= MULTIPATH_NUM)
        break;

      if (num_nhs >= ZEBRA_NUM_OF(nexthops))
	break;

      if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
        continue;

      if (!CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
	continue;

      nexthops[num_nhs] = nexthop;
      num_nhs++;
    }

  if (!num_nhs) {
    zfpm_debug ("netlink_encode_route(): No useful nexthop.");
    assert(0);
    return NULL;
  }

  /*
   * And add them to the message.
   */
  if (!(msg->nexthops = qpb_alloc_ptr_array(allocator, num_nhs))) {
    assert(0);
    return NULL;
  }

  msg->n_nexthops = 0;
  for (u = 0; u < num_nhs; u++) {
    if (!add_nexthop(allocator, msg, dest, nexthops[u])) {
      assert(0);
      return NULL;
    }
  }

  assert(msg->n_nexthops == num_nhs);

  return msg;
}