My API presentation tomorrow includes a section on why we choose Cap'n Proto and why it is better than Protobuf ;)
The biggest argument is: > > - Library routines for working with protobuf, including functions > > that help translate between common quagga types and their protobuf > > equivalents. I came up with a way to avoid these as much as possible. That said, I don't disagree with this patchset. If nothing else, it might be nice to modularize things so that it is easier to change interfaces. Cheers, -David On Mon, Mar 14, 2016 at 09:04:33AM -0400, Donald Sharp wrote: > Can you give us some background on why proto-buf was choosen as a > communication methodology and why it's superior from a netlink perspective? > > Some more thoughts inline. > > > On Fri, Mar 11, 2016 at 3:21 PM, Avneesh Sachdev <avne...@sproute.com> > 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 <avne...@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]) > > + > > > > This hunk sure seems like it should be it's own separate patch. It seems > like a reasonable fix but I don't think it needs to be part of the generic > add of protobuff to the system? > > > > > 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 <avne...@sproute.com> > > + * > > + * This file is part of GNU Zebra. > > > > > 1,$s/GNU Zebra/Quagga/ > please. For all new files. > > > > > + * > > + * 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 <avne...@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 <avne...@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; > > +}; > > > > What's the plan for VPNv4 and 6, as well as MPLS? These are coming in > *soonish* so let's start thinking about handling them now? > > The reasoning about why I am asking about thought process for protobuf -vs- > netlink. I want it documented. Can you provide some documentation for the > doc/ directory to talk about design choices and how this is all planed to > go together? > > donald > > > > + > > +// > > +// 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 <avne...@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 <avne...@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@lists.quagga.net > > https://lists.quagga.net/mailman/listinfo/quagga-dev > > > _______________________________________________ > Quagga-dev mailing list > Quagga-dev@lists.quagga.net > https://lists.quagga.net/mailman/listinfo/quagga-dev _______________________________________________ Quagga-dev mailing list Quagga-dev@lists.quagga.net https://lists.quagga.net/mailman/listinfo/quagga-dev