[quagga-dev 14906] Re: [PATCH 1/6] Add support for protobuf.

Martin Winter mwinter at opensourcerouting.org
Sat Mar 12 02:00:33 GMT 2016


Avneesh,

You missed to update the Makefile infrastructure for the new directory
“make dist” does not add the new qpb directory to the tar it
creates.

(This causes theCentOS package fail to build on my CI system)

- Martin


On 11 Mar 2016, at 12:21, Avneesh Sachdev wrote:

> Infrastructure that allows protocol buffers to be used in Quagga. The
> changes below comprise of:
>
> - Build hooks
>
> - Protobuf definitions for common types.
>
> - Library routines for working with protobuf, including functions
>  that help translate between common quagga types and their protobuf
>  equivalents.
>
> Changes:
>
> * qpb/{Makefile.am,README.txt,qpb.h,.gitignore}
>
>  Add the qpb library, which provides shared code and definitions
>  for using protocol buffers in quagga code.
>
> * qpb/qpb.proto
>
>  Protobuf definitions that can be shared by all of quagga.
>
> * qpb/linear_allocator.h
>
>  An allocator that allocates memory by walking down towards the end
>  of a buffer. This is used to cheaply allocate/deallocate memory on
>  the stack for protobuf operations.
>
> * qpb/qpb_allocator.[ch]
>
>  Thin layer that allows a linear allocator to be used with the
>  protobuf-c library.
>
> * common.am
>
>  This is an automake fragment that is intended to be shared by
>  Makefile.am files in the tree. It currently includes definitions
>  related to protobuf.
>
> * configure.ac
>
>  - Add logic to optionally build protobuf code.
>
>    By default, protobuf support is enabled if the protobuf C
>    compiler (protoc-c) is available, and the associated header
>    files/library can be found.
>
>    The user can choose to override this behavior via the new
>    --disable-protobuf/--enable-protobuf flags.
>
>  - Include the quagga protobuf library (qpb) in the build.
>
> * .gitignore
>
>  Ignore source code generated by protobuf compiler.
>
> * Makefile.am
>
>  Add 'qpb' to the list of subdirectories.
>
> Signed-off-by: Avneesh Sachdev <avneesh at sproute.com>
> ---
> .gitignore             |   3 +
> Makefile.am            |   2 +-
> common.am              |  39 ++++++
> configure.ac           |  52 ++++++-
> qpb/.gitignore         |  15 ++
> qpb/Makefile.am        |  20 +++
> qpb/README.txt         |   1 +
> qpb/linear_allocator.h | 207 +++++++++++++++++++++++++++
> qpb/qpb.h              | 372 
> +++++++++++++++++++++++++++++++++++++++++++++++++
> qpb/qpb.proto          | 121 ++++++++++++++++
> qpb/qpb_allocator.c    |  67 +++++++++
> qpb/qpb_allocator.h    | 113 +++++++++++++++
> 12 files changed, 1009 insertions(+), 3 deletions(-)
> create mode 100644 common.am
> create mode 100644 qpb/.gitignore
> create mode 100644 qpb/Makefile.am
> create mode 100644 qpb/README.txt
> create mode 100644 qpb/linear_allocator.h
> create mode 100644 qpb/qpb.h
> create mode 100644 qpb/qpb.proto
> create mode 100644 qpb/qpb_allocator.c
> create mode 100644 qpb/qpb_allocator.h
>
> diff --git a/.gitignore b/.gitignore
> index e8de252..a281555 100644
> --- a/.gitignore
> +++ b/.gitignore
> @@ -38,3 +38,6 @@ build
> m4/*.m4
> !m4/ax_sys_weak_alias.m4
> cscope.*
> +*.pb.h
> +*.pb-c.h
> +*.pb-c.c
> diff --git a/Makefile.am b/Makefile.am
> index d2efb20..ece8a59 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -1,6 +1,6 @@
> ## Process this file with automake to produce Makefile.in.
>
> -SUBDIRS = lib @ZEBRA@ @BGPD@ @RIPD@ @RIPNGD@ @OSPFD@ @OSPF6D@ \
> +SUBDIRS = lib qpb @ZEBRA@ @BGPD@ @RIPD@ @RIPNGD@ @OSPFD@ @OSPF6D@ \
>        @ISISD@ @PIMD@ @WATCHQUAGGA@ @VTYSH@ @OSPFCLIENT@ @DOC@ m4 
> @pkgsrcdir@ \
>        redhat @SOLARIS@ tests
>
> diff --git a/common.am b/common.am
> new file mode 100644
> index 0000000..dc79479
> --- /dev/null
> +++ b/common.am
> @@ -0,0 +1,39 @@
> +#
> +# Automake fragment intended to be shared by Makefile.am files in the
> +# tree.
> +#
> +
> +if HAVE_PROTOBUF
> +
> +# Uncomment to use an non-system version of libprotobuf-c.
> +#
> +# Q_PROTOBUF_C_CLIENT_INCLUDES = 
> -I$(top_srcdir)/third-party/protobuf-c/src
> +# Q_PROTOBUF_C_CLIENT_LDOPTS = 
> $(top_builddir)/third-party/protobuf-c/src/libprotobuf-c.la
> +
> +Q_PROTOBUF_C_CLIENT_INCLUDES=
> +Q_PROTOBUF_C_CLIENT_LDOPTS=-lprotobuf-c
> +
> +Q_PROTOC=protoc
> +Q_PROTOC_C=protoc-c
> +
> +Q_PROTOBUF_CFILES = $(filter %.pb-c.c,$(SOURCES))
> +
> +Q_PROTOBUF_SRCS = $(Q_PROTOBUF_CFILES) $(Q_PROTOBUF_HFILES)
> +
> +# Rules
> +%.pb.h: %.proto
> +	$(Q_PROTOC) $(PROTOBUF_INCLUDES) --cpp_out=$(top_srcdir) 
> $(top_srcdir)/$(PROTOBUF_PACKAGE)/$^
> +
> +%.pb-c.c %.pb-c.h: %.proto
> +	$(Q_PROTOC_C) $(PROTOBUF_INCLUDES) --c_out=$(top_srcdir) 
> $(top_srcdir)/$(PROTOBUF_PACKAGE)/$^
> +
> +#
> +# Information about how to link to various libraries.
> +#
> +Q_QUAGGA_PB_CLIENT_LDOPTS = $(top_srcdir)/qpb/libquagga_pb.la 
> $(Q_PROTOBUF_C_CLIENT_LDOPTS)
> +
> +endif  # HAVE_PROTOBUF
> +
> +Q_CLEANFILES = $(Q_PROTOBUF_SRCS)
> +
> +Q_BUILT_SRCS = $(Q_PROTOBUF_SRCS)
> diff --git a/configure.ac b/configure.ac
> index 3003e62..51be70a 100755
> --- a/configure.ac
> +++ b/configure.ac
> @@ -20,7 +20,10 @@ AC_CANONICAL_BUILD()
> AC_CANONICAL_HOST()
> AC_CANONICAL_TARGET()
>
> -AM_INIT_AUTOMAKE(1.6)
> +# Disable portability warnings -- our automake code (in particular
> +# common.am) uses some constructs specific to gmake.
> +AM_INIT_AUTOMAKE([1.6 -Wno-portability])
> +
> AM_SILENT_RULES([yes])
> AC_CONFIG_HEADERS(config.h)
>
> @@ -302,6 +305,8 @@ AC_ARG_ENABLE(fpm,
> AS_HELP_STRING([--enable-fpm], [enable Forwarding Plane Manager 
> support]))
> AC_ARG_ENABLE(werror,
> AS_HELP_STRING([--enable-werror], [enable -Werror (recommended for 
> developers only)]))
> +AC_ARG_ENABLE([protobuf],
> +    AS_HELP_STRING([--disable-protobuf], [Ignore presence of protobuf 
> and disable it]))
>
> if test x"${enable_gcc_rdynamic}" != x"no" ; then
> if test x"${enable_gcc_rdynamic}" = x"yes" -o x"$COMPILER" = x"GCC"; 
> then
> @@ -321,6 +326,49 @@ if test "${enable_fpm}" = "yes"; then
>  AC_DEFINE(HAVE_FPM,,Forwarding Plane Manager support)
> fi
>
> +#
> +# Logic for protobuf support.
> +#
> +have_protobuf=no
> +if test "x$enable_protobuf" != "xno"; then
> +   have_protobuf=yes
> +
> +   # Check for protoc-c
> +   AC_CHECK_PROG([PROTOC_C], [protoc-c], [protoc-c], [/bin/false])
> +   if test "x$PROTOC_C" = "x/bin/false"; then
> +      have_protobuf=no
> +   else
> +      found_protobuf_c=no
> +      PKG_CHECK_MODULES([PROTOBUF_C], libprotobuf-c >= 0.14,
> +                     [found_protobuf_c=yes],
> +                     [AC_MSG_RESULT([pkg-config did not find 
> libprotobuf-c])])
> +
> +      if test "x$found_protobuf_c" = "xyes"; then
> +         LDFLAGS="$LDFLAGS $PROTOBUF_C_LIBS"
> +         CFLAGS="$CFLAGS $PROTOBUF_C_CFLAGS"
> +      else
> +        AC_CHECK_HEADER([google/protobuf-c/protobuf-c.h], [],
> +                        [have_protobuf=no; AC_MSG_RESULT([Couldn't 
> find google/protobuf-c.h])])
> +      fi
> +   fi
> +fi
> +
> +# Fail if the user explicity enabled protobuf support and we couldn't
> +# find the compiler or libraries.
> +if test "x$have_protobuf" = "xno" && test "x$enable_protobuf" = 
> "xyes"; then
> +   AC_MSG_ERROR([Protobuf enabled explicitly but can't find 
> libraries/tools])
> +fi
> +
> +if test "x$have_protobuf" = "xyes"; then
> +   AC_DEFINE(HAVE_PROTOBUF,, protobuf)
> +fi
> +
> +AM_CONDITIONAL([HAVE_PROTOBUF], [test "x$have_protobuf" = "xyes"])
> +
> +#
> +# End of logic for protobuf support.
> +#
> +
> if test "${enable_tcp_zebra}" = "yes"; then
> AC_DEFINE(HAVE_TCP_ZEBRA,,Use TCP for zebra communication)
> fi
> @@ -1547,7 +1595,7 @@ AC_CACHE_VAL(ac_cv_htonl_works,
> )
> AC_MSG_RESULT($ac_cv_htonl_works)
>
> -AC_CONFIG_FILES([Makefile lib/Makefile zebra/Makefile ripd/Makefile
> +AC_CONFIG_FILES([Makefile lib/Makefile qpb/Makefile zebra/Makefile 
> ripd/Makefile
> 	  ripngd/Makefile bgpd/Makefile ospfd/Makefile watchquagga/Makefile
> 	  ospf6d/Makefile isisd/Makefile vtysh/Makefile
> 	  doc/Makefile ospfclient/Makefile tests/Makefile m4/Makefile
> diff --git a/qpb/.gitignore b/qpb/.gitignore
> new file mode 100644
> index 0000000..b133c52
> --- /dev/null
> +++ b/qpb/.gitignore
> @@ -0,0 +1,15 @@
> +Makefile
> +Makefile.in
> +*.o
> +tags
> +TAGS
> +.deps
> +.nfs*
> +*.lo
> +*.la
> +*.a
> +*.libs
> +.arch-inventory
> +.arch-ids
> +*~
> +*.loT
> diff --git a/qpb/Makefile.am b/qpb/Makefile.am
> new file mode 100644
> index 0000000..549f027
> --- /dev/null
> +++ b/qpb/Makefile.am
> @@ -0,0 +1,20 @@
> +include ../common.am
> +
> +AM_CPPFLAGS = -I.. -I$(top_srcdir) -I$(top_srcdir)/lib 
> -I$(top_builddir)/lib $(Q_PROTOBUF_C_CLIENT_INCLUDES)
> +
> +PROTOBUF_INCLUDES=-I$(top_srcdir)
> +PROTOBUF_PACKAGE = qpb
> +
> +lib_LTLIBRARIES = libquagga_pb.la
> +libquagga_pb_la_LDFLAGS = -version-info 0:0:0
> +
> +if HAVE_PROTOBUF
> +protobuf_srcs = 			\
> +	qpb.pb-c.c			\
> +	qpb_allocator.c
> +endif
> +
> +libquagga_pb_la_SOURCES = $(protobuf_srcs)
> +
> +CLEANFILES = $(Q_CLEANFILES)
> +BUILT_SOURCES = $(Q_PROTOBUF_SRCS)
> diff --git a/qpb/README.txt b/qpb/README.txt
> new file mode 100644
> index 0000000..99ccd05
> --- /dev/null
> +++ b/qpb/README.txt
> @@ -0,0 +1 @@
> +Protobuf definitions and code that is applicable to all of quagga.
> diff --git a/qpb/linear_allocator.h b/qpb/linear_allocator.h
> new file mode 100644
> index 0000000..f5cc49f
> --- /dev/null
> +++ b/qpb/linear_allocator.h
> @@ -0,0 +1,207 @@
> +/*
> + * linear_allocator.h
> + *
> + * @copyright Copyright (C) 2016 Sproute Networks, Inc.
> + *
> + * @author Avneesh Sachdev <avneesh at sproute.com>
> + *
> + * 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.
> + */
> +
> +/*
> + * Header file for the linear allocator.
> + *
> + * An allocator that allocates memory by walking down towards the end
> + * of a buffer. No attempt is made to reuse blocks that are freed
> + * subsequently. The assumption is that the buffer is big enough to
> + * cover allocations for a given purpose.
> + */
> +#include <assert.h>
> +#include <string.h>
> +#include <stdint.h>
> +#include <stddef.h>
> +
> +/*
> + * Alignment for block allocated by the allocator. Must be a power of 
> 2.
> + */
> +#define LINEAR_ALLOCATOR_ALIGNMENT        8
> +
> +#define LINEAR_ALLOCATOR_ALIGN(value)					\
> +  (((value) + LINEAR_ALLOCATOR_ALIGNMENT - 1) & 
> ~(LINEAR_ALLOCATOR_ALIGNMENT - 1));
> +
> +/*
> + * linear_allocator_align_ptr
> + */
> +static inline char *
> +linear_allocator_align_ptr (char *ptr)
> +{
> +  return (char *) LINEAR_ALLOCATOR_ALIGN ((intptr_t) ptr);
> +}
> +
> +typedef struct linear_allocator_t_
> +{
> +  char *buf;
> +
> +  /*
> +   * Current location in the buffer.
> +   */
> +  char *cur;
> +
> +  /*
> +   * End of buffer.
> +   */
> +  char *end;
> +
> +  /*
> +   * Version number of the allocator, this is bumped up when the 
> allocator
> +   * is reset and helps identifies bad frees.
> +   */
> +  uint32_t version;
> +
> +  /*
> +   * The number of blocks that are currently allocated.
> +   */
> +  int num_allocated;
> +} linear_allocator_t;
> +
> +/*
> + * linear_allocator_block_t
> + *
> + * Header structure at the begining of each block.
> + */
> +typedef struct linear_allocator_block_t_
> +{
> +  uint32_t flags;
> +
> +  /*
> +   * The version of the allocator when this block was allocated.
> +   */
> +  uint32_t version;
> +  char data[0];
> +} linear_allocator_block_t;
> +
> +#define LINEAR_ALLOCATOR_BLOCK_IN_USE 0x01
> +
> +#define LINEAR_ALLOCATOR_HDR_SIZE (sizeof(linear_allocator_block_t))
> +
> +/*
> + * linear_allocator_block_size
> + *
> + * The total amount of space a block will take in the buffer,
> + * including the size of the header.
> + */
> +static inline size_t
> +linear_allocator_block_size (size_t user_size)
> +{
> +  return LINEAR_ALLOCATOR_ALIGN (LINEAR_ALLOCATOR_HDR_SIZE + 
> user_size);
> +}
> +
> +/*
> + * linear_allocator_ptr_to_block
> + */
> +static inline linear_allocator_block_t *
> +linear_allocator_ptr_to_block (void *ptr)
> +{
> +  void *block_ptr;
> +  block_ptr = ((char *) ptr) - offsetof (linear_allocator_block_t, 
> data);
> +  return block_ptr;
> +}
> +
> +/*
> + * linear_allocator_init
> + */
> +static inline void
> +linear_allocator_init (linear_allocator_t * allocator, char *buf,
> +		       size_t buf_len)
> +{
> +  memset (allocator, 0, sizeof (*allocator));
> +
> +  assert (linear_allocator_align_ptr (buf) == buf);
> +  allocator->buf = buf;
> +  allocator->cur = buf;
> +  allocator->end = buf + buf_len;
> +}
> +
> +/*
> + * linear_allocator_reset
> + *
> + * Prepare an allocator for reuse.
> + *
> + * *** NOTE ** This implicitly frees all the blocks in the allocator.
> + */
> +static inline void
> +linear_allocator_reset (linear_allocator_t *allocator)
> +{
> +  allocator->num_allocated = 0;
> +  allocator->version++;
> +  allocator->cur = allocator->buf;
> +}
> +
> +/*
> + * linear_allocator_alloc
> + */
> +static inline void *
> +linear_allocator_alloc (linear_allocator_t *allocator, size_t 
> user_size)
> +{
> +  size_t block_size;
> +  linear_allocator_block_t *block;
> +
> +  block_size = linear_allocator_block_size (user_size);
> +
> +  if (allocator->cur + block_size > allocator->end)
> +    {
> +      return NULL;
> +    }
> +
> +  block = (linear_allocator_block_t *) allocator->cur;
> +  allocator->cur += block_size;
> +
> +  block->flags = LINEAR_ALLOCATOR_BLOCK_IN_USE;
> +  block->version = allocator->version;
> +  allocator->num_allocated++;
> +  return block->data;
> +}
> +
> +/*
> + * linear_allocator_free
> + */
> +static inline void
> +linear_allocator_free (linear_allocator_t *allocator, void *ptr)
> +{
> +  linear_allocator_block_t *block;
> +
> +  if (((char *) ptr) < allocator->buf || ((char *) ptr) >= 
> allocator->end)
> +    {
> +      assert (0);
> +      return;
> +    }
> +
> +  block = linear_allocator_ptr_to_block (ptr);
> +  if (block->version != allocator->version)
> +    {
> +      assert (0);
> +      return;
> +    }
> +
> +  block->flags = block->flags & ~LINEAR_ALLOCATOR_BLOCK_IN_USE;
> +
> +  if (--allocator->num_allocated < 0)
> +    {
> +      assert (0);
> +    }
> +}
> diff --git a/qpb/qpb.h b/qpb/qpb.h
> new file mode 100644
> index 0000000..2ff2804
> --- /dev/null
> +++ b/qpb/qpb.h
> @@ -0,0 +1,372 @@
> +/*
> + * qpb.h
> + *
> + * @copyright Copyright (C) 2016 Sproute Networks, Inc.
> + *
> + * @author Avneesh Sachdev <avneesh at sproute.com>
> + *
> + * 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.
> + */
> +
> +/*
> + * Main public header file for the quagga protobuf library.
> + */
> +
> +#ifndef _QPB_H
> +#define _QPB_H
> +
> +#include "prefix.h"
> +
> +#include "qpb/qpb.pb-c.h"
> +
> +#include "qpb/qpb_allocator.h"
> +
> +/*
> + * qpb__address_family__set
> + */
> +#define qpb_address_family_set qpb__address_family__set
> +static inline int
> +qpb__address_family__set (Qpb__AddressFamily *pb_family, u_char 
> family)
> +{
> +  switch (family) {
> +  case AF_INET:
> +    *pb_family = QPB__ADDRESS_FAMILY__IPV4;
> +    return 1;
> +
> +  case AF_INET6:
> +    *pb_family = QPB__ADDRESS_FAMILY__IPV6;
> +    return 1;
> +
> +  default:
> +    *pb_family = QPB__ADDRESS_FAMILY__UNKNOWN_AF;
> +  }
> +
> +  return 0;
> +}
> +
> +/*
> + * qpb__address_family__get
> + */
> +#define qpb_address_family_get qpb__address_family__get
> +static inline int
> +qpb__address_family__get (Qpb__AddressFamily pb_family, u_char 
> *family)
> +{
> +
> +  switch (pb_family) {
> +  case QPB__ADDRESS_FAMILY__IPV4:
> +    *family = AF_INET;
> +    return 1;
> +
> +  case QPB__ADDRESS_FAMILY__IPV6:
> +    *family = AF_INET6;
> +    return 1;
> +
> +  case QPB__ADDRESS_FAMILY__UNKNOWN_AF:
> +    return 0;
> +  }
> +
> +  return 0;
> +}
> +
> +/*
> + * qpb__l3_prefix__create
> + */
> +#define qpb_l3_prefix_create qpb__l3_prefix__create
> +static inline Qpb__L3Prefix *
> +qpb__l3_prefix__create (qpb_allocator_t *allocator, struct prefix *p)
> +{
> +  Qpb__L3Prefix *prefix;
> +
> +  prefix = QPB_ALLOC(allocator, typeof(*prefix));
> +  if (!prefix) {
> +    return NULL;
> +  }
> +  qpb__l3_prefix__init(prefix);
> +  prefix->length = p->prefixlen;
> +  prefix->bytes.len = (p->prefixlen + 7)/8;
> +  prefix->bytes.data = qpb_alloc(allocator, prefix->bytes.len);
> +  if (!prefix->bytes.data) {
> +    return NULL;
> +  }
> +
> +  memcpy(prefix->bytes.data, &p->u.prefix, prefix->bytes.len);
> +
> +  return prefix;
> +}
> +
> +/*
> + * qpb__l3_prefix__get
> + */
> +#define qpb_l3_prefix_get qpb__l3_prefix__get
> +static inline int
> +qpb__l3_prefix__get (const Qpb__L3Prefix *pb_prefix, u_char family,
> +		     struct prefix *prefix)
> +{
> +
> +  switch (family)
> +    {
> +
> +    case AF_INET:
> +      memset(prefix, 0, sizeof(struct prefix_ipv4));
> +      break;
> +
> +    case AF_INET6:
> +      memset(prefix, 0, sizeof(struct prefix_ipv6));
> +      break;
> +
> +    default:
> +      memset(prefix, 0, sizeof(*prefix));
> +    }
> +
> +  prefix->prefixlen = pb_prefix->length;
> +  prefix->family = family;
> +  memcpy(&prefix->u.prefix, pb_prefix->bytes.data, 
> pb_prefix->bytes.len);
> +  return 1;
> +}
> +
> +/*
> + * qpb__protocol__set
> + *
> + * Translate a quagga route type to a protobuf protocol.
> + */
> +#define qpb_protocol_set qpb__protocol__set
> +static inline int
> +qpb__protocol__set (Qpb__Protocol *pb_proto, int route_type)
> +{
> +  switch (route_type) {
> +  case ZEBRA_ROUTE_KERNEL:
> +    *pb_proto = QPB__PROTOCOL__KERNEL;
> +    break;
> +
> +  case ZEBRA_ROUTE_CONNECT:
> +    *pb_proto = QPB__PROTOCOL__CONNECTED;
> +    break;
> +
> +  case ZEBRA_ROUTE_STATIC:
> +    *pb_proto = QPB__PROTOCOL__STATIC;
> +    break;
> +
> +  case ZEBRA_ROUTE_RIP:
> +    *pb_proto = QPB__PROTOCOL__RIP;
> +    break;
> +
> +  case ZEBRA_ROUTE_RIPNG:
> +    *pb_proto = QPB__PROTOCOL__RIPNG;
> +    break;
> +
> +  case ZEBRA_ROUTE_OSPF:
> +  case ZEBRA_ROUTE_OSPF6:
> +    *pb_proto = QPB__PROTOCOL__OSPF;
> +    break;
> +
> +  case ZEBRA_ROUTE_ISIS:
> +    *pb_proto = QPB__PROTOCOL__ISIS;
> +    break;
> +
> +  case ZEBRA_ROUTE_BGP:
> +    *pb_proto = QPB__PROTOCOL__BGP;
> +    break;
> +
> +  case ZEBRA_ROUTE_HSLS:
> +  case ZEBRA_ROUTE_OLSR:
> +  case ZEBRA_ROUTE_BABEL:
> +  case ZEBRA_ROUTE_MAX:
> +  case ZEBRA_ROUTE_SYSTEM:
> +  default:
> +    *pb_proto = QPB__PROTOCOL__OTHER;
> +  }
> +
> +  return 1;
> +}
> +
> +/*
> + * qpb__ipv4_address__create
> + */
> +static inline Qpb__Ipv4Address *
> +qpb__ipv4_address__create (qpb_allocator_t *allocator,
> +			   struct in_addr *addr)
> +{
> +  Qpb__Ipv4Address *v4;
> +
> +  v4 = QPB_ALLOC(allocator, typeof(*v4));
> +  if (!v4) {
> +    return NULL;
> +  }
> +  qpb__ipv4_address__init(v4);
> +
> +  v4->value = ntohl(addr->s_addr);
> +  return v4;
> +}
> +
> +/*
> + * qpb__ipv4_address__get
> + */
> +static inline int
> +qpb__ipv4_address__get (const Qpb__Ipv4Address *v4, struct in_addr 
> *addr)
> +{
> +  addr->s_addr = htonl(v4->value);
> +  return 1;
> +}
> +
> +/*
> + * qpb__ipv6_address__create
> + */
> +static inline Qpb__Ipv6Address *
> +qpb__ipv6_address__create (qpb_allocator_t *allocator, struct 
> in6_addr *addr)
> +{
> +  Qpb__Ipv6Address *v6;
> +
> +  v6 = QPB_ALLOC(allocator, typeof(*v6));
> +  if (!v6)
> +    return NULL;
> +
> +  qpb__ipv6_address__init(v6);
> +  v6->bytes.len = 16;
> +  v6->bytes.data = qpb_alloc(allocator, 16);
> +  if (!v6->bytes.data)
> +    return NULL;
> +
> +  memcpy(v6->bytes.data, addr->s6_addr, v6->bytes.len);
> +  return v6;
> +}
> +
> +/*
> + * qpb__ipv6_address__get
> + *
> + * Read out information from a protobuf ipv6 address structure.
> + */
> +static inline int
> +qpb__ipv6_address__get (const Qpb__Ipv6Address *v6, struct in6_addr 
> *addr)
> +{
> +  if (v6->bytes.len != 16)
> +    return 0;
> +
> +  memcpy(addr->s6_addr, v6->bytes.data, v6->bytes.len);
> +  return 1;
> +}
> +
> +/*
> + * qpb__l3_address__create
> + */
> +#define qpb_l3_address_create qpb__l3_address__create
> +static inline Qpb__L3Address *
> +qpb__l3_address__create (qpb_allocator_t *allocator, union g_addr 
> *addr,
> +			 u_char family)
> +{
> +  Qpb__L3Address *l3_addr;
> +
> +  l3_addr = QPB_ALLOC(allocator, typeof(*l3_addr));
> +  if (!l3_addr)
> +    return NULL;
> +
> +  qpb__l3_address__init(l3_addr);
> +
> +  switch (family) {
> +
> +  case AF_INET:
> +    l3_addr->v4 = qpb__ipv4_address__create (allocator, &addr->ipv4);
> +    if (!l3_addr->v4)
> +      return NULL;
> +
> +    break;
> +
> +  case AF_INET6:
> +    l3_addr->v6 = qpb__ipv6_address__create (allocator, &addr->ipv6);
> +    if (!l3_addr->v6)
> +      return NULL;
> +
> +    break;
> +  }
> +  return l3_addr;
> +}
> +
> +/*
> + * qpb__l3_address__get
> + *
> + * Read out a gateway address from a protobuf l3 address.
> + */
> +#define qpb_l3_address_get qpb__l3_address__get
> +static inline int
> +qpb__l3_address__get (const Qpb__L3Address *l3_addr,
> +		      u_char *family, union g_addr *addr)
> +{
> +  if (l3_addr->v4)
> +    {
> +      qpb__ipv4_address__get (l3_addr->v4, &addr->ipv4);
> +      *family = AF_INET;
> +      return 1;
> +    }
> +
> +  if (l3_addr->v6)
> +    {
> +      qpb__ipv6_address__get(l3_addr->v6, &addr->ipv6);
> +      *family = AF_INET6;
> +      return 1;
> +    }
> +
> +  return 0;
> +}
> +
> +/*
> + * qpb__if_identifier__create
> + */
> +#define qpb_if_identifier_create qpb__if_identifier__create
> +static inline Qpb__IfIdentifier *
> +qpb__if_identifier__create (qpb_allocator_t *allocator, uint 
> if_index)
> +{
> +  Qpb__IfIdentifier *if_id;
> +
> +  if_id = QPB_ALLOC(allocator, typeof(*if_id));
> +  if (!if_id) {
> +    return NULL;
> +  }
> +  qpb__if_identifier__init(if_id);
> +  if_id->has_index = 1;
> +  if_id->index = if_index;
> +  return if_id;
> +}
> +
> +/*
> + * qpb__if_identifier__get
> + *
> + * Get interface name and/or if_index from an if identifier.
> + */
> +#define qpb_if_identifier_get qpb__if_identifier__get
> +static inline int
> +qpb__if_identifier__get (Qpb__IfIdentifier *if_id, uint *if_index,
> +			 char **name)
> +{
> +  char *str;
> +  uint ix;
> +
> +  if (!if_index)
> +    if_index = &ix;
> +
> +  if (!name)
> +    name = &str;
> +
> +  if (if_id->has_index)
> +    *if_index = if_id->index;
> +  else
> +    *if_index = 0;
> +
> +  *name = if_id->name;
> +  return 1;
> +}
> +
> +#endif
> diff --git a/qpb/qpb.proto b/qpb/qpb.proto
> new file mode 100644
> index 0000000..7ee409d
> --- /dev/null
> +++ b/qpb/qpb.proto
> @@ -0,0 +1,121 @@
> +/*
> + * qpb.proto
> + *
> + * @copyright Copyright (C) 2016 Sproute Networks, Inc.
> + *
> + * @author Avneesh Sachdev <avneesh at sproute.com>
> + *
> + * Permission is granted to use, copy, modify and/or distribute this
> + * software under either one of the licenses below.
> + *
> + * Note that if you use other files from the Quagga tree directly or
> + * indirectly, then the licenses in those files still apply.
> + *
> + * Please retain both licenses below when modifying this code in the
> + * Quagga tree.
> + */
> +
> +/*
> + * License Option 1: GPL
> + *
> + * This program 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 of the License, or (at your 
> option)
> + * any later version.
> + *
> + * This program 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 this program; if not, write to the Free Software Foundation, 
> Inc.,
> + * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
> + */
> +
> +/*
> + * License Option 2: ISC License
> + *
> + * Permission to use, copy, modify, and/or distribute this software
> + * for any purpose with or without fee is hereby granted, provided
> + * that the above copyright notice and this permission notice appear
> + * in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
> + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
> + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
> + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
> + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 
> LOSS
> + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
> + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
> + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +/*
> + * Protobuf definitions pertaining to the Quagga Protobuf component.
> + */
> +package qpb;
> +
> +enum AddressFamily {
> +  UNKNOWN_AF = 0;
> +  IPV4 = 1;		// IP version 4
> +  IPV6 = 2;		// IP version 6
> +};
> +
> +enum SubAddressFamily {
> +  UNKNOWN_SAF = 0;
> +  UNICAST = 1;
> +  MULTICAST = 2;
> +};
> +
> +//
> +// An IP version 4 address, such as 10.1.1.1.
> +//
> +message Ipv4Address {
> +  required fixed32 value = 1 ;
> +};
> +
> +message Ipv6Address {
> +
> +  // 16 bytes.
> +  required bytes bytes = 1;
> +};
> +
> +//
> +// An IP version 4 or IP version 6 address.
> +//
> +message L3Address {
> +  optional Ipv4Address v4 = 1;
> +  optional Ipv6Address v6 = 2;
> +};
> +
> +//
> +// An IP prefix, such as 10.1/16.
> +// We use the message below to represent both IPv4 and IPv6 prefixes.
> +message L3Prefix {
> +  required uint32 length = 1;
> +  required bytes bytes = 2;
> +};
> +
> +//
> +// Something that identifies an interface on a machine. It can either
> +// be a name (for instance, 'eth0') or a number currently.
> +//
> +message IfIdentifier {
> +  optional uint32 index = 1;
> +  optional string name = 2;
> +};
> +
> +enum Protocol {
> +  UNKNOWN_PROTO = 0;
> +  LOCAL = 1;
> +  CONNECTED = 2;
> +  KERNEL = 3;
> +  STATIC = 4;
> +  RIP = 5;
> +  RIPNG = 6;
> +  OSPF = 7;
> +  ISIS = 8;
> +  BGP = 9;
> +  OTHER = 10;
> +}
> \ No newline at end of file
> diff --git a/qpb/qpb_allocator.c b/qpb/qpb_allocator.c
> new file mode 100644
> index 0000000..2d9070d
> --- /dev/null
> +++ b/qpb/qpb_allocator.c
> @@ -0,0 +1,67 @@
> +/*
> + * qpb_allocator.c
> + *
> + * @copyright Copyright (C) 2016 Sproute Networks, Inc.
> + *
> + * @author Avneesh Sachdev <avneesh at sproute.com>
> + *
> + * 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 "linear_allocator.h"
> +
> +#include "qpb_allocator.h"
> +
> +/*
> + * _qpb_alloc
> + */
> +static void *
> +_qpb_alloc (void *allocator_data, size_t size)
> +{
> +  return linear_allocator_alloc (allocator_data, size);
> +}
> +
> +/*
> + * _qpb_free
> + */
> +static void
> +_qpb_free (void *allocator_data, void *ptr)
> +{
> +  linear_allocator_free (allocator_data, ptr);
> +}
> +
> +static ProtobufCAllocator allocator_template = {
> +  _qpb_alloc,
> +  _qpb_free,
> +  NULL,
> +  8192,
> +  NULL
> +};
> +
> +/*
> + * qpb_allocator_init_linear
> + *
> + * Initialize qpb_allocator_t with the given linear allocator.
> + */
> +void
> +qpb_allocator_init_linear (qpb_allocator_t *allocator,
> +			   linear_allocator_t *linear_allocator)
> +{
> +  *allocator = allocator_template;
> +  allocator->allocator_data = linear_allocator;
> +}
> diff --git a/qpb/qpb_allocator.h b/qpb/qpb_allocator.h
> new file mode 100644
> index 0000000..c987f23
> --- /dev/null
> +++ b/qpb/qpb_allocator.h
> @@ -0,0 +1,113 @@
> +/*
> + * qpb_allocator.h
> + *
> + * @copyright Copyright (C) 2016 Sproute Networks, Inc.
> + *
> + * @author Avneesh Sachdev <avneesh at sproute.com>
> + *
> + * 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.
> + */
> +
> +/*
> + * Header file for quagga protobuf memory management code.
> + */
> +
> +#ifndef _QPB_ALLOCATOR_H_
> +#define _QPB_ALLOCATOR_H_
> +
> +#include <google/protobuf-c/protobuf-c.h>
> +
> +struct linear_allocator_t_;
> +
> +/*
> + * Alias for ProtobufCAllocator that is easier on the fingers.
> + */
> +typedef ProtobufCAllocator qpb_allocator_t;
> +
> +/*
> + * qpb_alloc
> + */
> +static inline void *
> +qpb_alloc (qpb_allocator_t *allocator, size_t size)
> +{
> +  return allocator->alloc (allocator->allocator_data, size);
> +}
> +
> +/*
> + * qpb_alloc_ptr_array
> + *
> + * Allocate space for the specified number of pointers.
> + */
> +static inline void *
> +qpb_alloc_ptr_array (qpb_allocator_t *allocator, size_t num_ptrs)
> +{
> +  return qpb_alloc (allocator, num_ptrs * sizeof (void *));
> +}
> +
> +/*
> + * qpb_free
> + */
> +static inline void
> +qpb_free (qpb_allocator_t *allocator, void *ptr)
> +{
> +  allocator->free (allocator->allocator_data, ptr);
> +}
> +
> +/*
> + * QPB_ALLOC
> + *
> + * Convenience macro to reduce the probability of allocating memory 
> of
> + * incorrect size. It returns enough memory to store the given type,
> + * and evaluates to an appropriately typed pointer.
> + */
> +#define QPB_ALLOC(allocator, type)		\
> +  (type *) qpb_alloc(allocator, sizeof(type))
> +
> +
> +/*
> + * Externs.
> + */
> +extern void qpb_allocator_init_linear (qpb_allocator_t *,
> +				       struct linear_allocator_t_ *);
> +
> +/*
> + * The following macros are for the common case where a qpb allocator
> + * is being used alongside a linear allocator that allocates memory
> + * off of the stack.
> + */
> +#define QPB_DECLARE_STACK_ALLOCATOR(allocator, size)	\
> +    qpb_allocator_t allocator;				\
> +    linear_allocator_t lin_ ## allocator;		\
> +    char lin_ ## allocator ## _buf[size]
> +
> +#define QPB_INIT_STACK_ALLOCATOR(allocator)				\
> +  do									\
> +    {									\
> +      linear_allocator_init(&(lin_ ## allocator),			\
> +			    lin_ ## allocator ## _buf,			\
> +			    sizeof(lin_ ## allocator ## _buf));		\
> +      qpb_allocator_init_linear(&allocator, &(lin_ ## allocator));	\
> +    } while (0)
> +
> +#define QPB_RESET_STACK_ALLOCATOR(allocator)		\
> +  do							\
> +    {							\
> +      linear_allocator_reset (&(lin_ ## allocator));	\
> +    } while (0)
> +
> +#endif /* _QPB_ALLOCATOR_H_ */
> -- 
> 1.9.1
>
>
> _______________________________________________
> Quagga-dev mailing list
> Quagga-dev at lists.quagga.net
> https://lists.quagga.net/mailman/listinfo/quagga-dev




More information about the Quagga-dev mailing list