bgp_create_update(struct bgp_channel *c, byte *buf)
{
  struct bgp_proto *p = (void *) c->c.proto;
  struct bgp_bucket *buck;
  byte *end = buf + (bgp_max_packet_length(p->conn) - BGP_HEADER_LENGTH);
  byte *res = NULL;

again: ;

  /* Initialize write state */
  struct bgp_write_state s = {
    .proto = p,
    .channel = c,
    .pool = bgp_linpool,
    .mp_reach = (c->afi != BGP_AF_IPV4) || c->ext_next_hop,
    .as4_session = p->as4_session,
    .add_path = c->add_path_tx,
    .mpls = c->desc->mpls,
  };

  /* Try unreachable bucket */
  if ((buck = c->withdraw_bucket) && !EMPTY_LIST(buck->prefixes))
  {
    res = (c->afi == BGP_AF_IPV4) && !c->ext_next_hop ?
      bgp_create_ip_unreach(&s, buck, buf, end):
      bgp_create_mp_unreach(&s, buck, buf, end);

    goto done;
  }

  /* Try reachable buckets */
  if (!EMPTY_LIST(c->bucket_queue))
  {
    buck = HEAD(c->bucket_queue);

    /* Cleanup empty buckets */
    if (EMPTY_LIST(buck->prefixes))
    {
      bgp_free_bucket(c, buck);
      goto again;
    }

    res = !s.mp_reach ?
      bgp_create_ip_reach(&s, buck, buf, end):
      bgp_create_mp_reach(&s, buck, buf, end);

    if (EMPTY_LIST(buck->prefixes))
      bgp_free_bucket(c, buck);
    else
      bgp_defer_bucket(c, buck);

    if (!res)
      goto again;

    goto done;
  }

  /* No more prefixes to send */
  return NULL;

done:
  BGP_TRACE_RL(&rl_snd_update, D_PACKETS, "Sending UPDATE");
  lp_flush(s.pool);

  return res;
}
bgp_create_update(struct bgp_channel *c, byte *buf)
{
  struct bgp_proto *p = (void *) c->c.proto;
  struct bgp_bucket *buck;
  byte *end = buf + (bgp_max_packet_length(p->conn) - BGP_HEADER_LENGTH);
  byte *res = NULL;

again: ;

   
  struct bgp_write_state s = {
    .proto = p,
    .channel = c,
    .pool = bgp_linpool,
    .mp_reach = (c->afi != BGP_AF_IPV4) || c->ext_next_hop,
    .as4_session = p->as4_session,
    .add_path = c->add_path_tx,
    .mpls = c->desc->mpls,
  };

   
  if ((buck = c->withdraw_bucket) && !EMPTY_LIST(buck->prefixes))
  {
    res = (c->afi == BGP_AF_IPV4) && !c->ext_next_hop ?
      bgp_create_ip_unreach(&s, buck, buf, end):
      bgp_create_mp_unreach(&s, buck, buf, end);

    goto done;
  }

   
  if (!EMPTY_LIST(c->bucket_queue))
  {
    buck = HEAD(c->bucket_queue);

     
    if (EMPTY_LIST(buck->prefixes))
    {
      bgp_free_bucket(c, buck);
      goto again;
    }

    res = !s.mp_reach ?
      bgp_create_ip_reach(&s, buck, buf, end):
      bgp_create_mp_reach(&s, buck, buf, end);

    if (EMPTY_LIST(buck->prefixes))
      bgp_free_bucket(c, buck);
    else
      bgp_defer_bucket(c, buck);

    if (!res)
      goto again;

    goto done;
  }

   
  return NULL;

done:
  BGP_TRACE_RL(&rl_snd_update, D_PACKETS, "Sending UPDATE");
  lp_flush(s.pool);

  return res;
}