Sure, Donald, will do.

Thanks!
Avneesh

On Mon, Mar 14, 2016 at 6:10 AM, Donald Sharp <[email protected]>
wrote:

> Can we get a respin of this patch with a 'GNU Zebra' replaced with
> 'Quagga' and no introduction of #if def HAVE_IPV6?
>
> thanks!
>
> donald
>
> On Fri, Mar 11, 2016 at 3:21 PM, Avneesh Sachdev <[email protected]>
> wrote:
>
>> Change zebra so that it can optionally use protobuf serialization when
>> communicating with a Forwarding Plane Manager component.
>>
>>   * zebra/main.c
>>
>>     Add the --fpm-format/-F command line option. This allows the user
>>     to control the format (protbuf|netlink) that is used to
>>     communicate with the FPM.
>>
>>   * zebra/zebra_fpm.c
>>
>>     - zebra_init_msg_format(),
>>
>>       This new function is invoked on process startup to determine the
>>       FPM format that should be used.
>>
>>     - zfpm_init()
>>
>>       Change to accept any 'FPM message format' specified by the user
>>       (via the new command line flag).
>>
>>     - zebra_encode_route()
>>
>>       Tweak to use the selected FPM format.
>>
>>   * zebra_fpm_protobuf.c
>>
>>     New code to build protobuf messages to be sent to the FPM.
>>
>>   * zebra/Makefile.am
>>
>>     - Include common.am
>>
>>     - Build new file zebra_fpm_protobuf.c when protobuf is available.
>>
>>     - Link with the fpm_pb library.
>>
>> Signed-off-by: Avneesh Sachdev <[email protected]>
>> ---
>>  zebra/Makefile.am          |  10 +-
>>  zebra/main.c               |  14 +-
>>  zebra/zebra_fpm.c          | 139 +++++++++++++++++---
>>  zebra/zebra_fpm.h          |   3 +-
>>  zebra/zebra_fpm_private.h  |   5 +
>>  zebra/zebra_fpm_protobuf.c | 313
>> +++++++++++++++++++++++++++++++++++++++++++++
>>  6 files changed, 456 insertions(+), 28 deletions(-)
>>  create mode 100644 zebra/zebra_fpm_protobuf.c
>>
>> diff --git a/zebra/Makefile.am b/zebra/Makefile.am
>> index 96dc6f0..f3265b1 100644
>> --- a/zebra/Makefile.am
>> +++ b/zebra/Makefile.am
>> @@ -1,3 +1,5 @@
>> +include ../common.am
>> +
>>  ## Process this file with automake to produce Makefile.in.
>>
>>  AM_CPPFLAGS = -I.. -I$(top_srcdir) -I$(top_srcdir)/lib
>> -I$(top_builddir)/lib
>> @@ -20,6 +22,10 @@ if HAVE_NETLINK
>>  othersrc = zebra_fpm_netlink.c
>>  endif
>>
>> +if HAVE_PROTOBUF
>> +protobuf_srcs = zebra_fpm_protobuf.c
>> +endif
>> +
>>  AM_CFLAGS = $(WERROR)
>>
>>  sbin_PROGRAMS = zebra
>> @@ -30,7 +36,7 @@ zebra_SOURCES = \
>>         zserv.c main.c interface.c connected.c zebra_rib.c
>> zebra_routemap.c \
>>         redistribute.c debug.c rtadv.c zebra_snmp.c zebra_vty.c \
>>         irdp_main.c irdp_interface.c irdp_packet.c router-id.c
>> zebra_fpm.c \
>> -       $(othersrc)
>> +       $(othersrc) $(protobuf_srcs)
>>
>>  testzebra_SOURCES = test_main.c zebra_rib.c interface.c connected.c
>> debug.c \
>>         zebra_vty.c \
>> @@ -42,7 +48,7 @@ noinst_HEADERS = \
>>         rt_netlink.h zebra_fpm.h zebra_fpm_private.h \
>>         ioctl_solaris.h
>>
>> -zebra_LDADD = $(otherobj) ../lib/libzebra.la $(LIBCAP)
>> +zebra_LDADD = $(otherobj) ../lib/libzebra.la $(LIBCAP)
>> $(Q_FPM_PB_CLIENT_LDOPTS)
>>
>>  testzebra_LDADD = ../lib/libzebra.la $(LIBCAP)
>>
>> diff --git a/zebra/main.c b/zebra/main.c
>> index f3c08f1..9a34b04 100644
>> --- a/zebra/main.c
>> +++ b/zebra/main.c
>> @@ -71,6 +71,7 @@ struct option longopts[] =
>>    { "batch",       no_argument,       NULL, 'b'},
>>    { "daemon",      no_argument,       NULL, 'd'},
>>    { "keep_kernel", no_argument,       NULL, 'k'},
>> +  { "fpm_format",  required_argument, NULL, 'F'},
>>    { "config_file", required_argument, NULL, 'f'},
>>    { "pid_file",    required_argument, NULL, 'i'},
>>    { "socket",      required_argument, NULL, 'z'},
>> @@ -130,6 +131,7 @@ usage (char *progname, int status)
>>               "-b, --batch        Runs in batch mode\n"\
>>               "-d, --daemon       Runs in daemon mode\n"\
>>               "-f, --config_file  Set configuration file name\n"\
>> +             "-F, --fpm_format   Set fpm format to 'netlink' or
>> 'protobuf'\n"\
>>               "-i, --pid_file     Set process identifier file name\n"\
>>               "-z, --socket       Set path of zebra socket\n"\
>>               "-k, --keep_kernel  Don't delete old routes which installed
>> by "\
>> @@ -295,6 +297,7 @@ main (int argc, char **argv)
>>    char *progname;
>>    struct thread thread;
>>    char *zserv_path = NULL;
>> +  char *fpm_format = NULL;
>>
>>    /* Set umask before anything for security */
>>    umask (0027);
>> @@ -310,9 +313,9 @@ main (int argc, char **argv)
>>        int opt;
>>
>>  #ifdef HAVE_NETLINK
>> -      opt = getopt_long (argc, argv, "bdkf:i:z:hA:P:ru:g:vs:C",
>> longopts, 0);
>> +      opt = getopt_long (argc, argv, "bdkf:F:i:z:hA:P:ru:g:vs:C",
>> longopts, 0);
>>  #else
>> -      opt = getopt_long (argc, argv, "bdkf:i:z:hA:P:ru:g:vC", longopts,
>> 0);
>> +      opt = getopt_long (argc, argv, "bdkf:F:i:z:hA:P:ru:g:vC",
>> longopts, 0);
>>  #endif /* HAVE_NETLINK */
>>
>>        if (opt == EOF)
>> @@ -336,6 +339,9 @@ main (int argc, char **argv)
>>         case 'f':
>>           config_file = optarg;
>>           break;
>> +       case 'F':
>> +         fpm_format = optarg;
>> +         break;
>>         case 'A':
>>           vty_addr = optarg;
>>           break;
>> @@ -423,9 +429,9 @@ main (int argc, char **argv)
>>  #endif /* HAVE_SNMP */
>>
>>  #ifdef HAVE_FPM
>> -  zfpm_init (zebrad.master, 1, 0);
>> +  zfpm_init (zebrad.master, 1, 0, fpm_format);
>>  #else
>> -  zfpm_init (zebrad.master, 0, 0);
>> +  zfpm_init (zebrad.master, 0, 0, fpm_format);
>>  #endif
>>
>>    /* Process the configuration file. Among other configuration
>> diff --git a/zebra/zebra_fpm.c b/zebra/zebra_fpm.c
>> index 292dbb6..f788df5 100644
>> --- a/zebra/zebra_fpm.c
>> +++ b/zebra/zebra_fpm.c
>> @@ -139,6 +139,15 @@ typedef enum {
>>  } zfpm_state_t;
>>
>>  /*
>> + * Message format to be used to communicate with the FPM.
>> + */
>> +typedef enum
>> +{
>> +  ZFPM_MSG_FORMAT_NONE,
>> +  ZFPM_MSG_FORMAT_NETLINK,
>> +  ZFPM_MSG_FORMAT_PROTOBUF,
>> +} zfpm_msg_format_e;
>> +/*
>>   * Globals.
>>   */
>>  typedef struct zfpm_glob_t_
>> @@ -149,6 +158,11 @@ typedef struct zfpm_glob_t_
>>     */
>>    int enabled;
>>
>> +  /*
>> +   * Message format to be used to communicate with the fpm.
>> +   */
>> +  zfpm_msg_format_e message_format;
>> +
>>    struct thread_master *master;
>>
>>    zfpm_state_t state;
>> @@ -862,19 +876,40 @@ zfpm_writes_pending (void)
>>   */
>>  static inline int
>>  zfpm_encode_route (rib_dest_t *dest, struct rib *rib, char *in_buf,
>> -                  size_t in_buf_len)
>> +                  size_t in_buf_len, fpm_msg_type_e *msg_type)
>>  {
>> -#ifndef HAVE_NETLINK
>> -  return 0;
>> -#else
>> -
>> +  size_t len;
>>    int cmd;
>> +  len = 0;
>>
>> -  cmd = rib ? RTM_NEWROUTE : RTM_DELROUTE;
>> +  *msg_type = FPM_MSG_TYPE_NONE;
>>
>> -  return zfpm_netlink_encode_route (cmd, dest, rib, in_buf, in_buf_len);
>> +  switch (zfpm_g->message_format) {
>>
>> +  case ZFPM_MSG_FORMAT_PROTOBUF:
>> +#ifdef HAVE_PROTOBUF
>> +    len = zfpm_protobuf_encode_route (dest, rib, (uint8_t *) in_buf,
>> +                                     in_buf_len);
>> +    *msg_type = FPM_MSG_TYPE_PROTOBUF;
>> +#endif
>> +    break;
>> +
>> +  case ZFPM_MSG_FORMAT_NETLINK:
>> +#ifdef HAVE_NETLINK
>> +    *msg_type = FPM_MSG_TYPE_NETLINK;
>> +    cmd = rib ? RTM_NEWROUTE : RTM_DELROUTE;
>> +    len = zfpm_netlink_encode_route (cmd, dest, rib, in_buf, in_buf_len);
>> +    assert(fpm_msg_align(len) == len);
>> +    *msg_type = FPM_MSG_TYPE_NETLINK;
>>  #endif /* HAVE_NETLINK */
>> +    break;
>> +
>> +  default:
>> +    break;
>> +  }
>> +
>> +  return len;
>> +
>>  }
>>
>>  /*
>> @@ -882,7 +917,7 @@ zfpm_encode_route (rib_dest_t *dest, struct rib *rib,
>> char *in_buf,
>>   *
>>   * Returns the rib that is to be sent to the FPM for a given dest.
>>   */
>> -static struct rib *
>> +struct rib *
>>  zfpm_route_for_update (rib_dest_t *dest)
>>  {
>>    struct rib *rib;
>> @@ -918,6 +953,7 @@ zfpm_build_updates (void)
>>    fpm_msg_hdr_t *hdr;
>>    struct rib *rib;
>>    int is_add, write_msg;
>> +  fpm_msg_type_e msg_type;
>>
>>    s = zfpm_g->obuf;
>>
>> @@ -942,7 +978,6 @@ zfpm_build_updates (void)
>>
>>      hdr = (fpm_msg_hdr_t *) buf;
>>      hdr->version = FPM_PROTO_VERSION;
>> -    hdr->msg_type = FPM_MSG_TYPE_NETLINK;
>>
>>      data = fpm_msg_data (hdr);
>>
>> @@ -962,11 +997,13 @@ zfpm_build_updates (void)
>>        }
>>
>>      if (write_msg) {
>> -      data_len = zfpm_encode_route (dest, rib, (char *) data, buf_end -
>> data);
>> +      data_len = zfpm_encode_route (dest, rib, (char *) data, buf_end -
>> data,
>> +                                   &msg_type);
>>
>>        assert (data_len);
>>        if (data_len)
>>         {
>> +         hdr->msg_type = msg_type;
>>           msg_len = fpm_data_len_to_msg_len (data_len);
>>           hdr->msg_len = htons (msg_len);
>>           stream_forward_endp (s, msg_len);
>> @@ -1517,6 +1554,64 @@ DEFUN (clear_zebra_fpm_stats,
>>    return CMD_SUCCESS;
>>  }
>>
>> +/*
>> + * zfpm_init_message_format
>> + */
>> +static inline void
>> +zfpm_init_message_format (const char *format)
>> +{
>> +  int have_netlink, have_protobuf;
>> +
>> +  have_netlink = have_protobuf = 0;
>> +
>> +#ifdef HAVE_NETLINK
>> +  have_netlink = 1;
>> +#endif
>> +
>> +#ifdef HAVE_PROTOBUF
>> +  have_protobuf = 1;
>> +#endif
>> +
>> +  zfpm_g->message_format = ZFPM_MSG_FORMAT_NONE;
>> +
>> +  if (!format)
>> +    {
>> +      if (have_netlink)
>> +       {
>> +         zfpm_g->message_format = ZFPM_MSG_FORMAT_NETLINK;
>> +       }
>> +      else if (have_protobuf)
>> +       {
>> +         zfpm_g->message_format = ZFPM_MSG_FORMAT_PROTOBUF;
>> +       }
>> +      return;
>> +    }
>> +
>> +  if (!strcmp ("netlink", format))
>> +    {
>> +      if (!have_netlink)
>> +       {
>> +         zlog_err ("FPM netlink message format is not available");
>> +         return;
>> +       }
>> +      zfpm_g->message_format = ZFPM_MSG_FORMAT_NETLINK;
>> +      return;
>> +    }
>> +
>> +  if (!strcmp ("protobuf", format))
>> +    {
>> +      if (!have_protobuf)
>> +       {
>> +         zlog_err ("FPM protobuf message format is not available");
>> +         return;
>> +       }
>> +      zfpm_g->message_format = ZFPM_MSG_FORMAT_PROTOBUF;
>> +      return;
>> +    }
>> +
>> +  zlog_warn ("Unknown fpm format '%s'", format);
>> +}
>> +
>>  /**
>>   * zfpm_init
>>   *
>> @@ -1524,11 +1619,13 @@ DEFUN (clear_zebra_fpm_stats,
>>   *
>>   * @param[in] port port at which FPM is running.
>>   * @param[in] enable TRUE if the zebra FPM module should be enabled
>> + * @param[in] format to use to talk to the FPM. Can be 'netink' or
>> 'protobuf'.
>>   *
>>   * Returns TRUE on success.
>>   */
>>  int
>> -zfpm_init (struct thread_master *master, int enable, uint16_t port)
>> +zfpm_init (struct thread_master *master, int enable, uint16_t port,
>> +          const char *format)
>>  {
>>    static int initialized = 0;
>>
>> @@ -1544,16 +1641,6 @@ zfpm_init (struct thread_master *master, int
>> enable, uint16_t port)
>>    zfpm_g->sock = -1;
>>    zfpm_g->state = ZFPM_STATE_IDLE;
>>
>> -  /*
>> -   * Netlink must currently be available for the Zebra-FPM interface
>> -   * to be enabled.
>> -   */
>> -#ifndef HAVE_NETLINK
>> -  enable = 0;
>> -#endif
>> -
>> -  zfpm_g->enabled = enable;
>> -
>>    zfpm_stats_init (&zfpm_g->stats);
>>    zfpm_stats_init (&zfpm_g->last_ivl_stats);
>>    zfpm_stats_init (&zfpm_g->cumulative_stats);
>> @@ -1561,6 +1648,16 @@ zfpm_init (struct thread_master *master, int
>> enable, uint16_t port)
>>    install_element (ENABLE_NODE, &show_zebra_fpm_stats_cmd);
>>    install_element (ENABLE_NODE, &clear_zebra_fpm_stats_cmd);
>>
>> +  zfpm_init_message_format(format);
>> +
>> +  /*
>> +   * Disable FPM interface if no suitable format is available.
>> +   */
>> +  if (zfpm_g->message_format == ZFPM_MSG_FORMAT_NONE)
>> +      enable = 0;
>> +
>> +  zfpm_g->enabled = enable;
>> +
>>    if (!enable) {
>>      return 1;
>>    }
>> diff --git a/zebra/zebra_fpm.h b/zebra/zebra_fpm.h
>> index 44dec02..ecd23c7 100644
>> --- a/zebra/zebra_fpm.h
>> +++ b/zebra/zebra_fpm.h
>> @@ -28,7 +28,8 @@
>>  /*
>>   * Externs.
>>   */
>> -extern int zfpm_init (struct thread_master *master, int enable, uint16_t
>> port);
>> +extern int zfpm_init (struct thread_master *master, int enable, uint16_t
>> port,
>> +                     const char *message_format);
>>  extern void zfpm_trigger_update (struct route_node *rn, const char
>> *reason);
>>
>>  #endif /* _ZEBRA_FPM_H */
>> diff --git a/zebra/zebra_fpm_private.h b/zebra/zebra_fpm_private.h
>> index 809a70a..1c4fd4c 100644
>> --- a/zebra/zebra_fpm_private.h
>> +++ b/zebra/zebra_fpm_private.h
>> @@ -53,4 +53,9 @@ extern int
>>  zfpm_netlink_encode_route (int cmd, rib_dest_t *dest, struct rib *rib,
>>                            char *in_buf, size_t in_buf_len);
>>
>> +extern int
>> +zfpm_protobuf_encode_route (rib_dest_t *dest, struct rib *rib,
>> +                           uint8_t *in_buf, size_t in_buf_len);
>> +
>> +extern struct rib *zfpm_route_for_update (rib_dest_t *dest);
>>  #endif /* _ZEBRA_FPM_PRIVATE_H */
>> diff --git a/zebra/zebra_fpm_protobuf.c b/zebra/zebra_fpm_protobuf.c
>> new file mode 100644
>> index 0000000..316c452
>> --- /dev/null
>> +++ b/zebra/zebra_fpm_protobuf.c
>> @@ -0,0 +1,313 @@
>> +/*
>> + * zebra_fpm_protobuf.c
>> + *
>> + * @copyright Copyright (C) 2016 Sproute Networks, Inc.
>> + *
>> + * @author Avneesh Sachdev <[email protected]>
>> + *
>> + * This file is part of GNU Zebra.
>> + *
>> + * GNU Zebra is free software; you can redistribute it and/or modify it
>> + * under the terms of the GNU General Public License as published by the
>> + * Free Software Foundation; either version 2, or (at your option) any
>> + * later version.
>> + *
>> + * GNU Zebra is distributed in the hope that it will be useful, but
>> + * WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> + * General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with GNU Zebra; see the file COPYING.  If not, write to the Free
>> + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
>> + * 02111-1307, USA.
>> + */
>> +#include <zebra.h>
>> +
>> +#include "log.h"
>> +#include "rib.h"
>> +
>> +#include "qpb/qpb.pb-c.h"
>> +#include "qpb/qpb.h"
>> +#include "qpb/qpb_allocator.h"
>> +#include "qpb/linear_allocator.h"
>> +#include "fpm/fpm_pb.h"
>> +
>> +#include "zebra_fpm_private.h"
>> +
>> +/*
>> + * create_delete_route_message
>> + */
>> +static Fpm__DeleteRoute *
>> +create_delete_route_message (qpb_allocator_t *allocator, rib_dest_t
>> *dest,
>> +                            struct rib *rib)
>> +{
>> +  Fpm__DeleteRoute *msg;
>> +
>> +  msg = QPB_ALLOC(allocator, typeof(*msg));
>> +  if (!msg) {
>> +    assert(0);
>> +    return NULL;
>> +  }
>> +
>> +  fpm__delete_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));
>> +  if (!msg->key) {
>> +    assert(0);
>> +    return NULL;
>> +  }
>> +
>> +  return msg;
>> +}
>> +
>> +/*
>> + * add_nexthop
>> + */
>> +static inline int
>> +add_nexthop (qpb_allocator_t *allocator, Fpm__AddRoute *msg, rib_dest_t
>> *dest,
>> +            struct nexthop *nexthop)
>> +{
>> +  uint32_t if_index;
>> +  union g_addr *gateway, *src;
>> +
>> +  gateway = src = NULL;
>> +
>> +  if_index = nexthop->ifindex;
>> +
>> +  if (nexthop->type == NEXTHOP_TYPE_IPV4
>> +      || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
>> +    {
>> +      gateway = &nexthop->gate;
>> +      if (nexthop->src.ipv4.s_addr)
>> +       src = &nexthop->src;
>> +    }
>> +
>> +#ifdef HAVE_IPV6
>> +  if (nexthop->type == NEXTHOP_TYPE_IPV6
>> +      || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
>> +      || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
>> +    {
>> +      gateway = &nexthop->gate;
>> +    }
>> +#endif /* HAVE_IPV6 */
>> +
>> +  if (nexthop->type == NEXTHOP_TYPE_IFINDEX
>> +      || nexthop->type == NEXTHOP_TYPE_IFNAME)
>> +    {
>> +      if (nexthop->src.ipv4.s_addr)
>> +       src = &nexthop->src;
>> +    }
>> +
>> +  if (!gateway && if_index == 0)
>> +    return 0;
>> +
>> +  /*
>> +   * We have a valid nexthop.
>> +   */
>> +  {
>> +    Fpm__Nexthop *pb_nh;
>> +    pb_nh = QPB_ALLOC(allocator, typeof(*pb_nh));
>> +    if (!pb_nh) {
>> +      assert(0);
>> +      return 0;
>> +    }
>> +
>> +    fpm__nexthop__init(pb_nh);
>> +
>> +    if (if_index != 0) {
>> +      pb_nh->if_id = qpb_if_identifier_create (allocator, if_index);
>> +    }
>> +
>> +    if (gateway) {
>> +      pb_nh->address = qpb_l3_address_create (allocator, gateway,
>> +                                             rib_dest_af(dest));
>> +    }
>> +
>> +    msg->nexthops[msg->n_nexthops++] = pb_nh;
>> +  }
>> +
>> +  // TODO: Use src.
>> +
>> +  return 1;
>> +}
>> +
>> +/*
>> + * 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;
>> +}
>> +
>> +/*
>> + * create_route_message
>> + */
>> +static Fpm__Message *
>> +create_route_message (qpb_allocator_t *allocator, rib_dest_t *dest,
>> +                     struct rib *rib)
>> +{
>> +  Fpm__Message *msg;
>> +
>> +  msg = QPB_ALLOC(allocator, typeof(*msg));
>> +  if (!msg) {
>> +    assert(0);
>> +    return NULL;
>> +  }
>> +
>> +  fpm__message__init(msg);
>> +
>> +  if (!rib) {
>> +    msg->type = FPM__MESSAGE__TYPE__DELETE_ROUTE;
>> +    msg->delete_route = create_delete_route_message(allocator, dest,
>> rib);
>> +    if (!msg->delete_route) {
>> +      assert(0);
>> +      return NULL;
>> +    }
>> +    return msg;
>> +  }
>> +
>> +  msg->type = FPM__MESSAGE__TYPE__ADD_ROUTE;
>> +  msg->add_route = create_add_route_message(allocator, dest, rib);
>> +  if (!msg->add_route) {
>> +    assert(0);
>> +    return NULL;
>> +  }
>> +
>> +  return msg;
>> +}
>> +
>> +/*
>> + * zfpm_protobuf_encode_route
>> + *
>> + * Create a protobuf message corresponding to the given route in the
>> + * given buffer space.
>> + *
>> + * Returns the number of bytes written to the buffer. 0 or a negative
>> + * value indicates an error.
>> + */
>> +int
>> +zfpm_protobuf_encode_route (rib_dest_t *dest, struct rib *rib,
>> +                           uint8_t *in_buf, size_t in_buf_len)
>> +{
>> +  Fpm__Message *msg;
>> +  QPB_DECLARE_STACK_ALLOCATOR (allocator, 4096);
>> +  size_t len;
>> +
>> +  QPB_INIT_STACK_ALLOCATOR (allocator);
>> +
>> +  msg = create_route_message(&allocator, dest, rib);
>> +  if (!msg) {
>> +    assert(0);
>> +    return 0;
>> +  }
>> +
>> +  len = fpm__message__pack(msg, (uint8_t *) in_buf);
>> +  assert(len <= in_buf_len);
>> +
>> +  QPB_RESET_STACK_ALLOCATOR (allocator);
>> +  return len;
>> +}
>> --
>> 1.9.1
>>
>>
>> _______________________________________________
>> Quagga-dev mailing list
>> [email protected]
>> https://lists.quagga.net/mailman/listinfo/quagga-dev
>>
>
>
_______________________________________________
Quagga-dev mailing list
[email protected]
https://lists.quagga.net/mailman/listinfo/quagga-dev

Reply via email to