mirror of
https://github.com/FRRouting/frr.git
synced 2025-04-30 13:37:17 +02:00
qpb: Add support for protobuf.
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@sproute.com> Edited: Paul Jakma <paul.jakma@hpe.com>: Change the sense of the configure enable option to require explicit specifying, as an experimental feature.
This commit is contained in:
parent
6d24eb2b75
commit
dad253b46d
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -55,3 +55,6 @@ debian/quagga/
|
|||
debian/tmp/
|
||||
*.swp
|
||||
cscope.*
|
||||
*.pb.h
|
||||
*.pb-c.h
|
||||
*.pb-c.c
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
## Process this file with automake to produce Makefile.in.
|
||||
|
||||
SUBDIRS = lib @ZEBRA@ @BGPD@ @RIPD@ @RIPNGD@ @OSPFD@ @OSPF6D@ @LDPD@ \
|
||||
SUBDIRS = lib qpb @ZEBRA@ @BGPD@ @RIPD@ @RIPNGD@ @OSPFD@ @OSPF6D@ @LDPD@ \
|
||||
@ISISD@ @PIMD@ @WATCHQUAGGA@ @VTYSH@ @OSPFCLIENT@ @DOC@ m4 @pkgsrcdir@ \
|
||||
redhat @SOLARIS@ tests tools cumulus
|
||||
|
||||
DIST_SUBDIRS = lib zebra bgpd ripd ripngd ospfd ospf6d ldpd \
|
||||
DIST_SUBDIRS = lib qpb zebra bgpd ripd ripngd ospfd ospf6d ldpd \
|
||||
isisd watchquagga vtysh ospfclient doc m4 pkgsrc redhat tests \
|
||||
solaris pimd tools cumulus
|
||||
|
||||
|
|
41
common.am
Normal file
41
common.am
Normal file
|
@ -0,0 +1,41 @@
|
|||
#
|
||||
# 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)
|
||||
|
||||
Q_FPM_PB_CLIENT_LDOPTS = $(top_srcdir)/fpm/libfpm_pb.la $(Q_QUAGGA_PB_CLIENT_LDOPTS)
|
||||
|
||||
endif # HAVE_PROTOBUF
|
||||
|
||||
Q_CLEANFILES = $(Q_PROTOBUF_SRCS)
|
||||
|
||||
Q_BUILT_SRCS = $(Q_PROTOBUF_SRCS)
|
47
configure.ac
47
configure.ac
|
@ -315,6 +315,8 @@ AC_ARG_ENABLE(cumulus,
|
|||
AS_HELP_STRING([--enable-cumulus], [enable Cumulus Switch Special Extensions]))
|
||||
AC_ARG_ENABLE(rr-semantics,
|
||||
AS_HELP_STRING([--disable-rr-semantics], [disable the v6 Route Replace semantics]))
|
||||
AC_ARG_ENABLE([protobuf],
|
||||
AS_HELP_STRING([--enable-protobuf], [Enable experimental protobuf support]))
|
||||
|
||||
AC_CHECK_HEADERS(json-c/json.h)
|
||||
AC_CHECK_LIB(json-c, json_object_get, LIBS="$LIBS -ljson-c")
|
||||
|
@ -393,6 +395,48 @@ if test "${enable_fpm}" = "yes"; then
|
|||
AC_DEFINE(HAVE_FPM,,Forwarding Plane Manager support)
|
||||
fi
|
||||
|
||||
#
|
||||
# Logic for protobuf support.
|
||||
#
|
||||
if test "$enable_protobuf" = "yes"; 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
|
||||
|
@ -1673,7 +1717,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 ldpd/Makefile isisd/Makefile vtysh/Makefile
|
||||
doc/Makefile ospfclient/Makefile tests/Makefile m4/Makefile
|
||||
|
@ -1715,6 +1759,7 @@ group to run as : ${enable_group}
|
|||
group for vty sockets : ${enable_vty_group}
|
||||
config file mask : ${enable_configfile_mask}
|
||||
log file mask : ${enable_logfile_mask}
|
||||
zebra protobuf enabled : ${have_protobuf:-no}
|
||||
|
||||
The above user and group must have read/write access to the state file
|
||||
directory and to the config files in the config file directory."
|
||||
|
|
15
qpb/.gitignore
vendored
Normal file
15
qpb/.gitignore
vendored
Normal file
|
@ -0,0 +1,15 @@
|
|||
Makefile
|
||||
Makefile.in
|
||||
*.o
|
||||
tags
|
||||
TAGS
|
||||
.deps
|
||||
.nfs*
|
||||
*.lo
|
||||
*.la
|
||||
*.a
|
||||
*.libs
|
||||
.arch-inventory
|
||||
.arch-ids
|
||||
*~
|
||||
*.loT
|
30
qpb/Makefile.am
Normal file
30
qpb/Makefile.am
Normal file
|
@ -0,0 +1,30 @@
|
|||
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_allocator.c
|
||||
|
||||
protobuf_srcs_nodist = \
|
||||
qpb.pb-c.c
|
||||
endif
|
||||
|
||||
libquagga_pb_la_SOURCES = \
|
||||
linear_allocator.h \
|
||||
qpb.h \
|
||||
qpb.c \
|
||||
qpb_allocator.h \
|
||||
$(protobuf_srcs)
|
||||
|
||||
nodist_libquagga_pb_la_SOURCES = $(protobuf_srcs_nodist)
|
||||
|
||||
CLEANFILES = $(Q_CLEANFILES)
|
||||
BUILT_SOURCES = $(Q_PROTOBUF_SRCS)
|
||||
EXTRA_DIST = qpb.proto
|
1
qpb/README.txt
Normal file
1
qpb/README.txt
Normal file
|
@ -0,0 +1 @@
|
|||
Protobuf definitions and code that is applicable to all of quagga.
|
207
qpb/linear_allocator.h
Normal file
207
qpb/linear_allocator.h
Normal file
|
@ -0,0 +1,207 @@
|
|||
/*
|
||||
* linear_allocator.h
|
||||
*
|
||||
* @copyright Copyright (C) 2016 Sproute Networks, Inc.
|
||||
*
|
||||
* @author Avneesh Sachdev <avneesh@sproute.com>
|
||||
*
|
||||
* This file is part of Quagga.
|
||||
*
|
||||
* Quagga 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.
|
||||
*
|
||||
* Quagga 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 Quagga; 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);
|
||||
}
|
||||
}
|
29
qpb/qpb.c
Normal file
29
qpb/qpb.c
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* qpb.c
|
||||
*
|
||||
* @copyright Copyright (C) 2016 Sproute Networks, Inc.
|
||||
*
|
||||
* @author Avneesh Sachdev <avneesh@sproute.com>
|
||||
*
|
||||
* This file is part of Quagga.
|
||||
*
|
||||
* Quagga 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.
|
||||
*
|
||||
* Quagga 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 Quagga; see the file COPYING. If not, write to the Free
|
||||
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Main file for the qpb library.
|
||||
*/
|
||||
|
372
qpb/qpb.h
Normal file
372
qpb/qpb.h
Normal file
|
@ -0,0 +1,372 @@
|
|||
/*
|
||||
* qpb.h
|
||||
*
|
||||
* @copyright Copyright (C) 2016 Sproute Networks, Inc.
|
||||
*
|
||||
* @author Avneesh Sachdev <avneesh@sproute.com>
|
||||
*
|
||||
* This file is part of Quagga.
|
||||
*
|
||||
* Quagga 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.
|
||||
*
|
||||
* Quagga 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 Quagga; 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
|
121
qpb/qpb.proto
Normal file
121
qpb/qpb.proto
Normal file
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
* qpb.proto
|
||||
*
|
||||
* @copyright Copyright (C) 2016 Sproute Networks, Inc.
|
||||
*
|
||||
* @author Avneesh Sachdev <avneesh@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;
|
||||
}
|
67
qpb/qpb_allocator.c
Normal file
67
qpb/qpb_allocator.c
Normal file
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* qpb_allocator.c
|
||||
*
|
||||
* @copyright Copyright (C) 2016 Sproute Networks, Inc.
|
||||
*
|
||||
* @author Avneesh Sachdev <avneesh@sproute.com>
|
||||
*
|
||||
* This file is part of Quagga.
|
||||
*
|
||||
* Quagga 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.
|
||||
*
|
||||
* Quagga 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 Quagga; 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;
|
||||
}
|
113
qpb/qpb_allocator.h
Normal file
113
qpb/qpb_allocator.h
Normal file
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* qpb_allocator.h
|
||||
*
|
||||
* @copyright Copyright (C) 2016 Sproute Networks, Inc.
|
||||
*
|
||||
* @author Avneesh Sachdev <avneesh@sproute.com>
|
||||
*
|
||||
* This file is part of Quagga.
|
||||
*
|
||||
* Quagga 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.
|
||||
*
|
||||
* Quagga 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 Quagga; 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_ */
|
Loading…
Reference in a new issue