Mailing List Archive

[PATCH 10/23] bgpd: enable use of capn/zmq interface
From: David Lamparter <equinox@opensourcerouting.org>

This commit enables the usage of capn/zmq API on bgp daemon, by
linking and using capn/zmq APIs, through using specific BGP
configuration parameters. It will be possible to receive queries
by using a zmq socket mentioned by -Z parameter.
Also, this commit introduces some new APIs that will be used by
capn/zmq APIs as entry points to manage BGP internals.
Using capn/zmq APIs means sharing data strucures. Those data
structures are defined by schemas, and are mapped on current
BGP structures. In order to be used in BGP daemon, some node
registrations are defined.
This patch introduces also bgp code modifications to
handle peer creation, configure specific bgp fields.

Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
---
bgpd/.gitignore | 5 ++
bgpd/Makefile.am | 9 ++--
bgpd/bgp.capnp | 156 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
bgpd/bgp_main.c | 28 +++++++++-
bgpd/bgpd.c | 108 ++++++++++++++++++++++++++++++++++----
bgpd/bgpd.h | 11 ++++
6 files changed, 302 insertions(+), 15 deletions(-)
create mode 100644 bgpd/bgp.capnp

diff --git a/bgpd/.gitignore b/bgpd/.gitignore
index 105be2299503..863d479f54dd 100644
--- a/bgpd/.gitignore
+++ b/bgpd/.gitignore
@@ -12,6 +12,11 @@ TAGS
*.la
*.a
*.libs
+*.bcapnp
+*.bcapnp.c
+*.bcapnp.h
+*.ndef.i
+*.ndef.hi
.arch-inventory
.arch-ids
*~
diff --git a/bgpd/Makefile.am b/bgpd/Makefile.am
index d5be054f9555..3fcffe62c989 100644
--- a/bgpd/Makefile.am
+++ b/bgpd/Makefile.am
@@ -1,6 +1,6 @@
## Process this file with automake to produce Makefile.in.

-AM_CPPFLAGS = -I.. -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir)/lib
+AM_CPPFLAGS = -I.. -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir)/lib @CAPN_C_CFLAGS@ @ZEROMQ_CFLAGS@
DEFS = @DEFS@ -DSYSCONFDIR=\"$(sysconfdir)/\"
INSTALL_SDATA=@INSTALL@ -m 600

@@ -27,13 +27,16 @@ noinst_HEADERS = \
bgp_encap.h bgp_encap_tlv.h bgp_encap_types.h bgp_nht.h

bgpd_SOURCES = bgp_main.c
-bgpd_LDADD = libbgp.a ../lib/libzebra.la @LIBCAP@ @LIBM@
+
+bgpd_LDADD = libbgp.a ../lib/libzebra.la @LIBCAP@ @LIBM@ @ZEROMQ_LIBS@ @CAPN_C_LIBS@

bgp_btoa_SOURCES = bgp_btoa.c
-bgp_btoa_LDADD = libbgp.a ../lib/libzebra.la @LIBCAP@ @LIBM@
+bgp_btoa_LDADD = libbgp.a ../lib/libzebra.la @LIBCAP@ @LIBM@ @ZEROMQ_LIBS@ @CAPN_C_LIBS@

examplesdir = $(exampledir)
dist_examples_DATA = bgpd.conf.sample bgpd.conf.sample2

EXTRA_DIST = BGP4-MIB.txt

+EXTRA_DIST += bgpd.ndef.i bgpd.ndef.hi bgp.bcapnp.c bgp.bcapnp.h
+libbgp_a_SOURCES += bgp.bcapnp.c
diff --git a/bgpd/bgp.capnp b/bgpd/bgp.capnp
new file mode 100644
index 000000000000..2603e6983ad6
--- /dev/null
+++ b/bgpd/bgp.capnp
@@ -0,0 +1,156 @@
+#
+# Copyright (c) 2016 David Lamparter, for NetDEF, Inc.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+#
+
+@0xc4c948a17d3b2250;
+
+using import "../capnp/codegen.capnp".Cflag;
+using import "../capnp/codegen.capnp".IPv4;
+
+using import "../capnp/codegen.capnp".ctype;
+using import "../capnp/codegen.capnp".cflag;
+using import "../capnp/codegen.capnp".cheader;
+using import "../capnp/codegen.capnp".cgen;
+using import "../capnp/codegen.capnp".csetter;
+using import "../capnp/codegen.capnp".cgetfield;
+using import "../capnp/codegen.capnp".cgennaked;
+using import "../capnp/codegen.capnp".carraykey;
+using import "../capnp/codegen.capnp".caltname;
+using import "../capnp/codegen.capnp".csetwrite;
+
+struct AfiSafiKey $cgennaked $cgetfield {
+ afi @0 :UInt8 $ctype("afi_t");
+ safi @1 :UInt8 $ctype("safi_t");
+}
+struct ExtCommunityList {
+ values @0 :List(UInt64);
+}
+
+struct BGP $ctype("struct bgp") $cgen
+ $csetter("bgp_%%_set")
+ $csetter("bgp_timers_set")
+{
+ as @0 :UInt32 $cgetfield;
+ name @1 :Text;
+
+ routerIdStatic @2 :IPv4;
+
+ cfAlwaysCompareMed @3 :Bool $cflag(field = "flags", setter = "bgp_flag_set", value = "BGP_FLAG_ALWAYS_COMPARE_MED");
+ cfDeterministicMed @4 :Bool $cflag(field = "flags", setter = "bgp_flag_set", value = "BGP_FLAG_DETERMINISTIC_MED");
+ cfMedMissingAsWorst @5 :Bool $cflag(field = "flags", setter = "bgp_flag_set", value = "BGP_FLAG_MED_MISSING_AS_WORST");
+ cfMedConfed @6 :Bool $cflag(field = "flags", setter = "bgp_flag_set", value = "BGP_FLAG_MED_CONFED");
+ cfNoDefaultIPv4 @7 :Bool $cflag(field = "flags", setter = "bgp_flag_set", value = "BGP_FLAG_NO_DEFAULT_IPV4");
+ cfNoClientToClient @8 :Bool $cflag(field = "flags", setter = "bgp_flag_set", value = "BGP_FLAG_NO_CLIENT_TO_CLIENT");
+ cfEnforceFirstAS @9 :Bool $cflag(field = "flags", setter = "bgp_flag_set", value = "BGP_FLAG_ENFORCE_FIRST_AS");
+ cfCompareRouterID @10 :Bool $cflag(field = "flags", setter = "bgp_flag_set", value = "BGP_FLAG_COMPARE_ROUTER_ID");
+ cfAspathIgnore @11 :Bool $cflag(field = "flags", setter = "bgp_flag_set", value = "BGP_FLAG_ASPATH_IGNORE");
+ cfImportCheck @12 :Bool $cflag(field = "flags", setter = "bgp_flag_set", value = "BGP_FLAG_IMPORT_CHECK");
+ cfNoFastExtFailover @13 :Bool $cflag(field = "flags", setter = "bgp_flag_set", value = "BGP_FLAG_NO_FAST_EXT_FAILOVER");
+ cfLogNeighborChanges @14 :Bool $cflag(field = "flags", setter = "bgp_flag_set", value = "BGP_FLAG_LOG_NEIGHBOR_CHANGES");
+ cfGracefulRestart @15 :Bool $cflag(field = "flags", setter = "bgp_flag_set", value = "BGP_FLAG_GRACEFUL_RESTART");
+ cfAspathConfed @16 :Bool $cflag(field = "flags", setter = "bgp_flag_set", value = "BGP_FLAG_ASPATH_CONFED");
+ cfAspathMpathRelax @17 :Bool $cflag(field = "flags", setter = "bgp_flag_set", value = "BGP_FLAG_ASPATH_MULTIPATH_RELAX");
+ cfGrPreservedFwd @18 :Bool $cflag(field = "flags", setter = "bgp_flag_set", value = "BGP_FLAG_GR_PRESERVE_FWD");
+
+ distanceEBGP @19 :UInt8 $csetwrite;
+ distanceIBGP @20 :UInt8 $csetwrite;
+ distanceLocal @21 :UInt8 $csetwrite;
+
+ defaultLocalPref @22 :UInt32 $caltname("default_local_preference");
+ defaultHoldtime @23 :UInt32 $caltname("holdtime");
+ defaultKeepalive @24 :UInt32 $caltname("keepalive");
+
+ restartTime @25 :UInt32;
+ stalepathTime @26 :UInt32 $csetwrite;
+}
+
+struct BGPAfiSafi $ctype("struct bgp") $cgen $carraykey("AfiSafiKey") {
+ cfDampening @0 :Bool $cflag(field = "af_flags", value = "BGP_CONFIG_DAMPENING");
+ cfMultipathRelax @1 :Bool $cflag(field = "af_flags", value = "BGP_CONFIG_ASPATH_MULTIPATH_RELAX");
+ cfMultipathRelax @2 :Bool $cflag(field = "af_flags", value = "BGP_CONFIG_MULTIPATH");
+}
+
+struct BGPPeer $ctype("struct peer") $cgen
+ $csetter("peer_%%_set")
+ $csetter("peer_timers_set")
+{
+ as @0 :UInt32 $cgetfield;
+ host @1 :Text $cgetfield;
+
+# localAs @2 :UInt32; # TBD
+
+ desc @2 :Text $csetter("peer_description_set");
+ port @3 :UInt16;
+ weight @4 :UInt32;
+ holdtime @5 :UInt32;
+ keepalive @6 :UInt32;
+
+ cfPassive @7 :Bool $cflag(field = "flags", setter = "peer_flag_set", value = "PEER_FLAG_PASSIVE");
+ cfShutdown @8 :Bool $cflag(field = "flags", setter = "peer_flag_set", value = "PEER_FLAG_SHUTDOWN");
+ cfDontCapability @9 :Bool $cflag(field = "flags", setter = "peer_flag_set", value = "PEER_FLAG_DONT_CAPABILITY");
+ cfOverrideCapability @10 :Bool $cflag(field = "flags", setter = "peer_flag_set", value = "PEER_FLAG_OVERRIDE_CAPABILITY");
+ cfStrictCapMatch @11 :Bool $cflag(field = "flags", setter = "peer_flag_set", value = "PEER_FLAG_STRICT_CAP_MATCH");
+ cfDynamicCapability @12 :Bool $cflag(field = "flags", setter = "peer_flag_set", value = "PEER_FLAG_DYNAMIC_CAPABILITY");
+ cfDisableConnectedCheck @13 :Bool $cflag(field = "flags", setter = "peer_flag_set", value = "PEER_FLAG_DISABLE_CONNECTED_CHECK");
+# cfLocalAsNoPrepend @14 :Bool $cflag(field = "flags", setter = "peer_local_as_set", value = "PEER_FLAG_LOCAL_AS_NO_PREPEND") $caltname("no_prepend");
+# cfLocalAsReplaceAs @15 :Bool $cflag(field = "flags", setter = "peer_local_as_set", value = "PEER_FLAG_LOCAL_AS_REPLACE_AS") $caltname("replace_as");
+
+ ttl @14 :Int32 $csetter("peer_ebgp_multihop_set");
+ updateSource @15 :Text $csetter("peer_update_source_addr_set");
+}
+
+struct BGPPeerAfiSafi $ctype("struct peer") $cgen
+ $carraykey("AfiSafiKey")
+ $csetter("peer_%%_set")
+{
+ afc @0 :Bool;
+
+ cfSendCommunity @1 :Bool $cflag(field = "af_flags", setter = "peer_af_flag_set", value = "PEER_FLAG_SEND_COMMUNITY");
+ cfSendExtCommunity @2 :Bool $cflag(field = "af_flags", setter = "peer_af_flag_set", value = "PEER_FLAG_SEND_EXT_COMMUNITY");
+ cfNexthopSelf @3 :Bool $cflag(field = "af_flags", setter = "peer_af_flag_set", value = "PEER_FLAG_NEXTHOP_SELF");
+ cfReflectorClient @4 :Bool $cflag(field = "af_flags", setter = "peer_af_flag_set", value = "PEER_FLAG_REFLECTOR_CLIENT");
+ cfRServerClient @5 :Bool $cflag(field = "af_flags", setter = "peer_af_flag_set", value = "PEER_FLAG_RSERVER_CLIENT");
+ cfSoftReconfig @6 :Bool $cflag(field = "af_flags", setter = "peer_af_flag_set", value = "PEER_FLAG_SOFT_RECONFIG");
+ cfAsPathUnchanged @7 :Bool $cflag(field = "af_flags", setter = "peer_af_flag_set", value = "PEER_FLAG_AS_PATH_UNCHANGED");
+ cfNexthopUnchanged @8 :Bool $cflag(field = "af_flags", setter = "peer_af_flag_set", value = "PEER_FLAG_NEXTHOP_UNCHANGED");
+ cfMedUnchanged @9 :Bool $cflag(field = "af_flags", setter = "peer_af_flag_set", value = "PEER_FLAG_MED_UNCHANGED");
+ cfDefaultOriginate @10 :Bool $cflag(field = "af_flags", setter = "peer_af_flag_set", value = "PEER_FLAG_DEFAULT_ORIGINATE");
+ cfRemovePrivateAs @11 :Bool $cflag(field = "af_flags", setter = "peer_af_flag_set", value = "PEER_FLAG_REMOVE_PRIVATE_AS");
+ cfAllowAsIn @12 :Bool $cflag(field = "af_flags", setter = "peer_af_flag_set", value = "PEER_FLAG_ALLOWAS_IN");
+ cfOrfPrefixSM @13 :Bool $cflag(field = "af_flags", setter = "peer_af_flag_set", value = "PEER_FLAG_ORF_PREFIX_SM");
+ cfOrfPrefixRM @14 :Bool $cflag(field = "af_flags", setter = "peer_af_flag_set", value = "PEER_FLAG_ORF_PREFIX_RM");
+ cfMaxPrefix @15 :Bool $cflag(field = "af_flags", setter = "peer_af_flag_set", value = "PEER_FLAG_MAX_PREFIX");
+ cfMaxPrefixWarn @16 :Bool $cflag(field = "af_flags", setter = "peer_af_flag_set", value = "PEER_FLAG_MAX_PREFIX_WARNING");
+ cfNexthopLocalUnchanged @17 :Bool $cflag(field = "af_flags", setter = "peer_af_flag_set", value = "PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED");
+ cfNexthopSelfAll @18 :Bool $cflag(field = "af_flags", setter = "peer_af_flag_set", value = "PEER_FLAG_NEXTHOP_SELF_ALL");
+
+ allowAsIn @19 :Int8;
+}
+
+struct BGPVRF $ctype("struct bgp_vrf") $cgen
+ $csetter("bgp_vrf_%%_set")
+{
+ outboundRd @0 :UInt64 $cgetfield;
+ rtImport @1 :ExtCommunityList;
+ rtExport @2 :ExtCommunityList;
+}
+
+# vim: set noet ts=8 nowrap tw=0:
diff --git a/bgpd/bgp_main.c b/bgpd/bgp_main.c
index 78d6ff38e442..f4bbb382ff7c 100644
--- a/bgpd/bgp_main.c
+++ b/bgpd/bgp_main.c
@@ -38,6 +38,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "stream.h"
#include "vrf.h"
#include "workqueue.h"
+#include "qzc.h"

#include "bgpd/bgpd.h"
#include "bgpd/bgp_attr.h"
@@ -68,6 +69,7 @@ static const struct option longopts[] =
{ "user", required_argument, NULL, 'u'},
{ "group", required_argument, NULL, 'g'},
{ "skip_runas", no_argument, NULL, 'S'},
+ { "zeromq", required_argument, NULL, 'Z'},
{ "version", no_argument, NULL, 'v'},
{ "dryrun", no_argument, NULL, 'C'},
{ "help", no_argument, NULL, 'h'},
@@ -216,6 +218,10 @@ sigusr1 (void)
zlog_rotate (NULL);
}

+#ifdef HAVE_CCAPNPROTO
+static struct qzc_sock *qzc_sock = NULL;
+#endif /* HAVE_CCAPNPROTO */
+
/*
Try to free up allocations we know about so that diagnostic tools such as
valgrind are able to better illuminate leaks.
@@ -333,6 +339,13 @@ bgp_exit (int status)
/* reverse bgp_scan_init */
bgp_scan_finish ();

+ QZC_NODE_UNREG(bm)
+#ifdef HAVE_CCAPNPROTO
+ if (qzc_sock)
+ qzc_close (qzc_sock);
+ qzc_finish ();
+#endif /* HAVE_CCAPNPROTO */
+
/* reverse bgp_master_init */
if (bm->master)
thread_master_free (bm->master);
@@ -356,6 +369,9 @@ main (int argc, char **argv)
int daemon_mode = 0;
int dryrun = 0;
char *progname;
+#ifdef HAVE_ZEROMQ
+ char *zmq_sock = NULL;
+#endif /* HAVE_ZEROMQ */
struct thread thread;
int tmp_port;
int skip_runas = 0;
@@ -375,7 +391,7 @@ main (int argc, char **argv)
/* Command line argument treatment. */
while (1)
{
- opt = getopt_long (argc, argv, "df:i:z:hp:l:A:P:rnu:g:vCS", longopts, 0);
+ opt = getopt_long (argc, argv, "df:i:z:hp:l:A:P:rnu:g:Z:vCS", longopts, 0);

if (opt == EOF)
break;
@@ -436,6 +452,11 @@ main (int argc, char **argv)
case 'S': /* skip run as = override bgpd_privs */
skip_runas = 1;
break;
+ case 'Z':
+#ifdef HAVE_ZEROMQ
+ zmq_sock = optarg;
+#endif /* HAVE_ZEROMQ */
+ break;
case 'v':
print_version (progname);
exit (0);
@@ -466,6 +487,11 @@ main (int argc, char **argv)
/* BGP related initialization. */
bgp_init ();

+#ifdef HAVE_ZEROMQ
+ if (zmq_sock)
+ qzc_sock = qzc_bind (bm->master, zmq_sock);
+#endif /* HAVE_ZEROMQ */
+
/* Parse config file. */
vty_read_config (config_file, config_default);

diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index c7fe6b21e2e0..337a5d0386a0 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -38,6 +38,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "hash.h"
#include "workqueue.h"
#include "table.h"
+#include "qzc.h"

#include "bgpd/bgpd.h"
#include "bgpd/bgp_table.h"
@@ -67,6 +68,11 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "bgpd/bgp_snmp.h"
#endif /* HAVE_SNMP */

+#ifdef HAVE_CCAPNPROTO
+#include "bgp.bcapnp.h"
+#include "bgpd.ndef.hi"
+#endif /* HAVE_CCAPNPROTO */
+
/* BGP process wide configuration. */
static struct bgp_master bgp_master;

@@ -179,7 +185,7 @@ bgp_config_check (struct bgp *bgp, int config)
}

/* Set BGP router identifier. */
-static int
+int
bgp_router_id_set (struct bgp *bgp, struct in_addr *id)
{
struct peer *peer;
@@ -755,6 +761,8 @@ peer_free (struct peer *peer)

bgp_unlock(peer->bgp);

+ QZC_NODE_UNREG(peer)
+
/* this /ought/ to have been done already through bgp_stop earlier,
* but just to be sure..
*/
@@ -908,6 +916,8 @@ peer_new (struct bgp *bgp)
sp = getservbyname ("bgp", "tcp");
peer->port = (sp == NULL) ? BGP_PORT_DEFAULT : ntohs (sp->s_port);

+ QZC_NODE_REG(peer, peer)
+
return peer;
}

@@ -1121,6 +1131,39 @@ peer_remote_as (struct bgp *bgp, union sockunion *su, as_t *as,
return 0;
}

+struct peer *
+peer_create_api (struct bgp *bgp, const char *host, as_t as)
+{
+ int ret;
+ union sockunion su;
+ struct peer *peer;
+ as_t local_as;
+
+ ret = str2sockunion (host, &su);
+ if (ret < 0)
+ return NULL;
+
+#if 0
+ if (peer_address_self_check (&su))
+ return NULL;
+#endif
+
+ peer = peer_lookup (bgp, &su);
+ if (peer)
+ return NULL;
+
+ /* If the peer is not part of our confederation, and its not an
+ iBGP peer then spoof the source AS */
+ if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION)
+ && ! bgp_confederation_peers_check (bgp, as)
+ && bgp->as != as)
+ local_as = bgp->confed_id;
+ else
+ local_as = bgp->as;
+
+ return peer_create (&su, bgp, local_as, as, 0, 0);
+}
+
/* Activate the peer or peer group for specified AFI and SAFI. */
int
peer_activate (struct peer *peer, afi_t afi, safi_t safi)
@@ -2150,6 +2193,7 @@ bgp_vrf_lookup_per_name (struct bgp *bgp, const char *name, int create)
vrf->rib[afi]->type = BGP_TABLE_VRF;
}

+ QZC_NODE_REG(vrf, bgp_vrf)
listnode_add (bgp->vrfs, vrf);
return vrf;
}
@@ -2283,6 +2327,8 @@ bgp_vrf_delete_rd (struct bgp_vrf *vrf)
prefix_rd2str(&vrf->outbound_rd, vrf_rd_str, sizeof(vrf_rd_str));
zlog_info ("deleting rd %s", vrf_rd_str);

+ QZC_NODE_UNREG(vrf)
+
bgp_vrf_clean_tables (vrf);

bgp_vrf_rt_import_unset (vrf);
@@ -2301,6 +2347,7 @@ bgp_vrf_delete_int (void *arg)
zlog_info ("deleting vrf %s", vrf_rd_str);

bgp_vrf_delete_rd (vrf);
+ QZC_NODE_UNREG(vrf)

if (vrf->name)
free (vrf->name);
@@ -2364,6 +2411,7 @@ bgp_create (as_t *as, const char *name)
bgp->vrfs->del = bgp_vrf_delete_int;
bgp->rt_subscribers = hash_create(bgp_rt_hash_key, bgp_rt_hash_cmp);

+ QZC_NODE_REG(bgp, bgp)
THREAD_TIMER_ON (bm->master, bgp->t_startup, bgp_startup_timer_expire,
bgp, bgp->restart_time);

@@ -2408,6 +2456,30 @@ bgp_lookup_by_name (const char *name)
return NULL;
}

+struct bgp *
+bgp_create_api (struct bgp_master *ignore, as_t as)
+{
+ struct bgp *bgp = NULL;
+
+ if (bgp_get_default ())
+ return NULL;
+
+ bgp = bgp_create (&as, NULL);
+ bgp_router_id_set(bgp, &router_id_zebra);
+
+ /* Create BGP server socket, if first instance. */
+ if (list_isempty(bm->bgp)
+ && !bgp_option_check (BGP_OPT_NO_LISTEN))
+ if (bgp_socket (bm->port, bm->address) < 0)
+ {
+ bgp_delete (bgp);
+ return NULL;
+ }
+
+ listnode_add (bm->bgp, bgp);
+ return bgp;
+}
+
/* Called from VTY commands. */
int
bgp_get (struct bgp **bgp_val, as_t *as, const char *name)
@@ -2486,6 +2558,7 @@ bgp_delete (struct bgp *bgp)
SET_FLAG(bgp->flags, BGP_FLAG_DELETING);

THREAD_OFF (bgp->t_startup);
+ QZC_NODE_UNREG(bgp)

for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
{
@@ -2522,8 +2595,6 @@ bgp_delete (struct bgp *bgp)
!bgp_flag_check (bgp, BGP_FLAG_GR_PRESERVE_FWD))
bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
}
-
- peer_delete (peer);
}

for (ALL_LIST_ELEMENTS (bgp->group, node, next, group))
@@ -2538,16 +2609,8 @@ bgp_delete (struct bgp *bgp)
bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
}
}
- peer_group_delete (group);
}

- assert (listcount (bgp->rsclient) == 0);
-
- if (bgp->peer_self) {
- peer_delete(bgp->peer_self);
- bgp->peer_self = NULL;
- }
-
/*
* Free pending deleted routes. Unfortunately, it also has to process
* all the pending activity for other instances of struct bgp.
@@ -2557,6 +2620,19 @@ bgp_delete (struct bgp *bgp)
*/
bgp_process_queues_drain_immediate();

+ /* workqueues hold references to peers */
+ for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
+ peer_delete (peer);
+ for (ALL_LIST_ELEMENTS (bgp->group, node, next, group))
+ peer_group_delete (group);
+
+ assert (listcount (bgp->rsclient) == 0);
+
+ if (bgp->peer_self) {
+ peer_delete(bgp->peer_self);
+ bgp->peer_self = NULL;
+ }
+
/* Remove visibility via the master list - there may however still be
* routes to be processed still referencing the struct bgp.
*/
@@ -6117,6 +6193,11 @@ bgp_master_init (void)
bm->port = BGP_PORT_DEFAULT;
bm->master = thread_master_create ();
bm->start_time = bgp_clock ();
+
+#ifdef HAVE_CCAPNPROTO
+ qzc_init ();
+#endif
+ QZC_NODE_REG(bm, bgp_master)
}


@@ -6200,3 +6281,8 @@ bgp_terminate (void)
bm->process_vrf_queue = NULL;
}
}
+
+#ifdef HAVE_CCAPNPROTO
+#include "bgpd.ndef.i"
+#endif /*HAVE_CCAPNPROTO */
+
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index 0d5bf5eea6fc..09f9c6a1c551 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -25,6 +25,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "sockunion.h"
#include "bgp_ecommunity.h"
#include "prefix.h"
+#include "qzc.h"

/* Typedef BGP specific types. */
typedef u_int32_t as_t;
@@ -74,6 +75,8 @@ struct bgp_master
#define BGP_OPT_MULTIPLE_INSTANCE (1 << 1)
#define BGP_OPT_CONFIG_CISCO (1 << 2)
#define BGP_OPT_NO_LISTEN (1 << 3)
+
+ QZC_NODE
};

/* BGP instance structure. */
@@ -202,6 +205,7 @@ struct bgp

struct hash *rt_subscribers;

+ QZC_NODE
};

struct bgp_rt_sub
@@ -251,6 +255,8 @@ struct bgp_vrf
/* internal flag */
#define BGP_VRF_RD_UNSET 1
uint16_t flag;
+
+ QZC_NODE
};

struct bgp_api_route
@@ -645,6 +651,8 @@ struct peer
#define PEER_RMAP_TYPE_NOSET (1 << 5) /* not allow to set commands */
#define PEER_RMAP_TYPE_IMPORT (1 << 6) /* neighbor route-map import */
#define PEER_RMAP_TYPE_EXPORT (1 << 7) /* neighbor route-map export */
+
+ QZC_NODE
};

#define PEER_PASSWORD_MINLEN (1)
@@ -913,6 +921,7 @@ extern int bgp_nexthop_set (union sockunion *, union sockunion *,
extern struct bgp *bgp_get_default (void);
extern struct bgp *bgp_lookup (as_t, const char *);
extern struct bgp *bgp_lookup_by_name (const char *);
+extern struct bgp *bgp_create_api (struct bgp_master *, as_t as);
extern struct peer *peer_lookup (struct bgp *, union sockunion *);
extern struct peer_group *peer_group_lookup (struct bgp *, const char *);
extern struct peer_group *peer_group_get (struct bgp *, const char *);
@@ -959,6 +968,7 @@ extern void bgp_lock (struct bgp *);
extern void bgp_unlock (struct bgp *);

extern void bgp_router_id_zebra_bump (void);
+extern int bgp_router_id_set (struct bgp *, struct in_addr *);
extern int bgp_router_id_static_set (struct bgp *, struct in_addr);

extern int bgp_cluster_id_set (struct bgp *, struct in_addr *);
@@ -981,6 +991,7 @@ extern int peer_rsclient_active (struct peer *);

extern int peer_remote_as (struct bgp *, union sockunion *, as_t *, afi_t, safi_t);
extern int peer_group_remote_as (struct bgp *, const char *, as_t *);
+extern struct peer *peer_create_api (struct bgp *, const char * host, as_t as);
extern int peer_delete (struct peer *peer);
extern int peer_group_delete (struct peer_group *);
extern int peer_group_remote_as_delete (struct peer_group *);
--
2.1.4


_______________________________________________
Quagga-dev mailing list
Quagga-dev@lists.quagga.net
https://lists.quagga.net/mailman/listinfo/quagga-dev
[PATCH 10/23] bgpd: enable use of capn/zmq interface [ In reply to ]
From: David Lamparter <equinox@opensourcerouting.org>

This commit enables the usage of capn/zmq API on bgp daemon, by
linking and using capn/zmq APIs, through using specific BGP
configuration parameters. It will be possible to receive queries
by using a zmq socket mentioned by -Z parameter.
Also, this commit introduces some new APIs that will be used by
capn/zmq APIs as entry points to manage BGP internals.
Using capn/zmq APIs means sharing data strucures. Those data
structures are defined by schemas, and are mapped on current
BGP structures. In order to be used in BGP daemon, some node
registrations are defined.
This patch introduces also bgp code modifications to
handle peer creation, configure specific bgp fields.

Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
---
bgpd/.gitignore | 5 ++
bgpd/Makefile.am | 9 ++--
bgpd/bgp.capnp | 156 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
bgpd/bgp_main.c | 28 +++++++++-
bgpd/bgpd.c | 108 ++++++++++++++++++++++++++++++++++----
bgpd/bgpd.h | 11 ++++
6 files changed, 302 insertions(+), 15 deletions(-)
create mode 100644 bgpd/bgp.capnp

diff --git a/bgpd/.gitignore b/bgpd/.gitignore
index 105be2299503..863d479f54dd 100644
--- a/bgpd/.gitignore
+++ b/bgpd/.gitignore
@@ -12,6 +12,11 @@ TAGS
*.la
*.a
*.libs
+*.bcapnp
+*.bcapnp.c
+*.bcapnp.h
+*.ndef.i
+*.ndef.hi
.arch-inventory
.arch-ids
*~
diff --git a/bgpd/Makefile.am b/bgpd/Makefile.am
index d5be054f9555..3fcffe62c989 100644
--- a/bgpd/Makefile.am
+++ b/bgpd/Makefile.am
@@ -1,6 +1,6 @@
## Process this file with automake to produce Makefile.in.

-AM_CPPFLAGS = -I.. -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir)/lib
+AM_CPPFLAGS = -I.. -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir)/lib @CAPN_C_CFLAGS@ @ZEROMQ_CFLAGS@
DEFS = @DEFS@ -DSYSCONFDIR=\"$(sysconfdir)/\"
INSTALL_SDATA=@INSTALL@ -m 600

@@ -27,13 +27,16 @@ noinst_HEADERS = \
bgp_encap.h bgp_encap_tlv.h bgp_encap_types.h bgp_nht.h

bgpd_SOURCES = bgp_main.c
-bgpd_LDADD = libbgp.a ../lib/libzebra.la @LIBCAP@ @LIBM@
+
+bgpd_LDADD = libbgp.a ../lib/libzebra.la @LIBCAP@ @LIBM@ @ZEROMQ_LIBS@ @CAPN_C_LIBS@

bgp_btoa_SOURCES = bgp_btoa.c
-bgp_btoa_LDADD = libbgp.a ../lib/libzebra.la @LIBCAP@ @LIBM@
+bgp_btoa_LDADD = libbgp.a ../lib/libzebra.la @LIBCAP@ @LIBM@ @ZEROMQ_LIBS@ @CAPN_C_LIBS@

examplesdir = $(exampledir)
dist_examples_DATA = bgpd.conf.sample bgpd.conf.sample2

EXTRA_DIST = BGP4-MIB.txt

+EXTRA_DIST += bgpd.ndef.i bgpd.ndef.hi bgp.bcapnp.c bgp.bcapnp.h
+libbgp_a_SOURCES += bgp.bcapnp.c
diff --git a/bgpd/bgp.capnp b/bgpd/bgp.capnp
new file mode 100644
index 000000000000..2603e6983ad6
--- /dev/null
+++ b/bgpd/bgp.capnp
@@ -0,0 +1,156 @@
+#
+# Copyright (c) 2016 David Lamparter, for NetDEF, Inc.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+#
+
+@0xc4c948a17d3b2250;
+
+using import "../capnp/codegen.capnp".Cflag;
+using import "../capnp/codegen.capnp".IPv4;
+
+using import "../capnp/codegen.capnp".ctype;
+using import "../capnp/codegen.capnp".cflag;
+using import "../capnp/codegen.capnp".cheader;
+using import "../capnp/codegen.capnp".cgen;
+using import "../capnp/codegen.capnp".csetter;
+using import "../capnp/codegen.capnp".cgetfield;
+using import "../capnp/codegen.capnp".cgennaked;
+using import "../capnp/codegen.capnp".carraykey;
+using import "../capnp/codegen.capnp".caltname;
+using import "../capnp/codegen.capnp".csetwrite;
+
+struct AfiSafiKey $cgennaked $cgetfield {
+ afi @0 :UInt8 $ctype("afi_t");
+ safi @1 :UInt8 $ctype("safi_t");
+}
+struct ExtCommunityList {
+ values @0 :List(UInt64);
+}
+
+struct BGP $ctype("struct bgp") $cgen
+ $csetter("bgp_%%_set")
+ $csetter("bgp_timers_set")
+{
+ as @0 :UInt32 $cgetfield;
+ name @1 :Text;
+
+ routerIdStatic @2 :IPv4;
+
+ cfAlwaysCompareMed @3 :Bool $cflag(field = "flags", setter = "bgp_flag_set", value = "BGP_FLAG_ALWAYS_COMPARE_MED");
+ cfDeterministicMed @4 :Bool $cflag(field = "flags", setter = "bgp_flag_set", value = "BGP_FLAG_DETERMINISTIC_MED");
+ cfMedMissingAsWorst @5 :Bool $cflag(field = "flags", setter = "bgp_flag_set", value = "BGP_FLAG_MED_MISSING_AS_WORST");
+ cfMedConfed @6 :Bool $cflag(field = "flags", setter = "bgp_flag_set", value = "BGP_FLAG_MED_CONFED");
+ cfNoDefaultIPv4 @7 :Bool $cflag(field = "flags", setter = "bgp_flag_set", value = "BGP_FLAG_NO_DEFAULT_IPV4");
+ cfNoClientToClient @8 :Bool $cflag(field = "flags", setter = "bgp_flag_set", value = "BGP_FLAG_NO_CLIENT_TO_CLIENT");
+ cfEnforceFirstAS @9 :Bool $cflag(field = "flags", setter = "bgp_flag_set", value = "BGP_FLAG_ENFORCE_FIRST_AS");
+ cfCompareRouterID @10 :Bool $cflag(field = "flags", setter = "bgp_flag_set", value = "BGP_FLAG_COMPARE_ROUTER_ID");
+ cfAspathIgnore @11 :Bool $cflag(field = "flags", setter = "bgp_flag_set", value = "BGP_FLAG_ASPATH_IGNORE");
+ cfImportCheck @12 :Bool $cflag(field = "flags", setter = "bgp_flag_set", value = "BGP_FLAG_IMPORT_CHECK");
+ cfNoFastExtFailover @13 :Bool $cflag(field = "flags", setter = "bgp_flag_set", value = "BGP_FLAG_NO_FAST_EXT_FAILOVER");
+ cfLogNeighborChanges @14 :Bool $cflag(field = "flags", setter = "bgp_flag_set", value = "BGP_FLAG_LOG_NEIGHBOR_CHANGES");
+ cfGracefulRestart @15 :Bool $cflag(field = "flags", setter = "bgp_flag_set", value = "BGP_FLAG_GRACEFUL_RESTART");
+ cfAspathConfed @16 :Bool $cflag(field = "flags", setter = "bgp_flag_set", value = "BGP_FLAG_ASPATH_CONFED");
+ cfAspathMpathRelax @17 :Bool $cflag(field = "flags", setter = "bgp_flag_set", value = "BGP_FLAG_ASPATH_MULTIPATH_RELAX");
+ cfGrPreservedFwd @18 :Bool $cflag(field = "flags", setter = "bgp_flag_set", value = "BGP_FLAG_GR_PRESERVE_FWD");
+
+ distanceEBGP @19 :UInt8 $csetwrite;
+ distanceIBGP @20 :UInt8 $csetwrite;
+ distanceLocal @21 :UInt8 $csetwrite;
+
+ defaultLocalPref @22 :UInt32 $caltname("default_local_preference");
+ defaultHoldtime @23 :UInt32 $caltname("holdtime");
+ defaultKeepalive @24 :UInt32 $caltname("keepalive");
+
+ restartTime @25 :UInt32;
+ stalepathTime @26 :UInt32 $csetwrite;
+}
+
+struct BGPAfiSafi $ctype("struct bgp") $cgen $carraykey("AfiSafiKey") {
+ cfDampening @0 :Bool $cflag(field = "af_flags", value = "BGP_CONFIG_DAMPENING");
+ cfMultipathRelax @1 :Bool $cflag(field = "af_flags", value = "BGP_CONFIG_ASPATH_MULTIPATH_RELAX");
+ cfMultipathRelax @2 :Bool $cflag(field = "af_flags", value = "BGP_CONFIG_MULTIPATH");
+}
+
+struct BGPPeer $ctype("struct peer") $cgen
+ $csetter("peer_%%_set")
+ $csetter("peer_timers_set")
+{
+ as @0 :UInt32 $cgetfield;
+ host @1 :Text $cgetfield;
+
+# localAs @2 :UInt32; # TBD
+
+ desc @2 :Text $csetter("peer_description_set");
+ port @3 :UInt16;
+ weight @4 :UInt32;
+ holdtime @5 :UInt32;
+ keepalive @6 :UInt32;
+
+ cfPassive @7 :Bool $cflag(field = "flags", setter = "peer_flag_set", value = "PEER_FLAG_PASSIVE");
+ cfShutdown @8 :Bool $cflag(field = "flags", setter = "peer_flag_set", value = "PEER_FLAG_SHUTDOWN");
+ cfDontCapability @9 :Bool $cflag(field = "flags", setter = "peer_flag_set", value = "PEER_FLAG_DONT_CAPABILITY");
+ cfOverrideCapability @10 :Bool $cflag(field = "flags", setter = "peer_flag_set", value = "PEER_FLAG_OVERRIDE_CAPABILITY");
+ cfStrictCapMatch @11 :Bool $cflag(field = "flags", setter = "peer_flag_set", value = "PEER_FLAG_STRICT_CAP_MATCH");
+ cfDynamicCapability @12 :Bool $cflag(field = "flags", setter = "peer_flag_set", value = "PEER_FLAG_DYNAMIC_CAPABILITY");
+ cfDisableConnectedCheck @13 :Bool $cflag(field = "flags", setter = "peer_flag_set", value = "PEER_FLAG_DISABLE_CONNECTED_CHECK");
+# cfLocalAsNoPrepend @14 :Bool $cflag(field = "flags", setter = "peer_local_as_set", value = "PEER_FLAG_LOCAL_AS_NO_PREPEND") $caltname("no_prepend");
+# cfLocalAsReplaceAs @15 :Bool $cflag(field = "flags", setter = "peer_local_as_set", value = "PEER_FLAG_LOCAL_AS_REPLACE_AS") $caltname("replace_as");
+
+ ttl @14 :Int32 $csetter("peer_ebgp_multihop_set");
+ updateSource @15 :Text $csetter("peer_update_source_addr_set");
+}
+
+struct BGPPeerAfiSafi $ctype("struct peer") $cgen
+ $carraykey("AfiSafiKey")
+ $csetter("peer_%%_set")
+{
+ afc @0 :Bool;
+
+ cfSendCommunity @1 :Bool $cflag(field = "af_flags", setter = "peer_af_flag_set", value = "PEER_FLAG_SEND_COMMUNITY");
+ cfSendExtCommunity @2 :Bool $cflag(field = "af_flags", setter = "peer_af_flag_set", value = "PEER_FLAG_SEND_EXT_COMMUNITY");
+ cfNexthopSelf @3 :Bool $cflag(field = "af_flags", setter = "peer_af_flag_set", value = "PEER_FLAG_NEXTHOP_SELF");
+ cfReflectorClient @4 :Bool $cflag(field = "af_flags", setter = "peer_af_flag_set", value = "PEER_FLAG_REFLECTOR_CLIENT");
+ cfRServerClient @5 :Bool $cflag(field = "af_flags", setter = "peer_af_flag_set", value = "PEER_FLAG_RSERVER_CLIENT");
+ cfSoftReconfig @6 :Bool $cflag(field = "af_flags", setter = "peer_af_flag_set", value = "PEER_FLAG_SOFT_RECONFIG");
+ cfAsPathUnchanged @7 :Bool $cflag(field = "af_flags", setter = "peer_af_flag_set", value = "PEER_FLAG_AS_PATH_UNCHANGED");
+ cfNexthopUnchanged @8 :Bool $cflag(field = "af_flags", setter = "peer_af_flag_set", value = "PEER_FLAG_NEXTHOP_UNCHANGED");
+ cfMedUnchanged @9 :Bool $cflag(field = "af_flags", setter = "peer_af_flag_set", value = "PEER_FLAG_MED_UNCHANGED");
+ cfDefaultOriginate @10 :Bool $cflag(field = "af_flags", setter = "peer_af_flag_set", value = "PEER_FLAG_DEFAULT_ORIGINATE");
+ cfRemovePrivateAs @11 :Bool $cflag(field = "af_flags", setter = "peer_af_flag_set", value = "PEER_FLAG_REMOVE_PRIVATE_AS");
+ cfAllowAsIn @12 :Bool $cflag(field = "af_flags", setter = "peer_af_flag_set", value = "PEER_FLAG_ALLOWAS_IN");
+ cfOrfPrefixSM @13 :Bool $cflag(field = "af_flags", setter = "peer_af_flag_set", value = "PEER_FLAG_ORF_PREFIX_SM");
+ cfOrfPrefixRM @14 :Bool $cflag(field = "af_flags", setter = "peer_af_flag_set", value = "PEER_FLAG_ORF_PREFIX_RM");
+ cfMaxPrefix @15 :Bool $cflag(field = "af_flags", setter = "peer_af_flag_set", value = "PEER_FLAG_MAX_PREFIX");
+ cfMaxPrefixWarn @16 :Bool $cflag(field = "af_flags", setter = "peer_af_flag_set", value = "PEER_FLAG_MAX_PREFIX_WARNING");
+ cfNexthopLocalUnchanged @17 :Bool $cflag(field = "af_flags", setter = "peer_af_flag_set", value = "PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED");
+ cfNexthopSelfAll @18 :Bool $cflag(field = "af_flags", setter = "peer_af_flag_set", value = "PEER_FLAG_NEXTHOP_SELF_ALL");
+
+ allowAsIn @19 :Int8;
+}
+
+struct BGPVRF $ctype("struct bgp_vrf") $cgen
+ $csetter("bgp_vrf_%%_set")
+{
+ outboundRd @0 :UInt64 $cgetfield;
+ rtImport @1 :ExtCommunityList;
+ rtExport @2 :ExtCommunityList;
+}
+
+# vim: set noet ts=8 nowrap tw=0:
diff --git a/bgpd/bgp_main.c b/bgpd/bgp_main.c
index 78d6ff38e442..f4bbb382ff7c 100644
--- a/bgpd/bgp_main.c
+++ b/bgpd/bgp_main.c
@@ -38,6 +38,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "stream.h"
#include "vrf.h"
#include "workqueue.h"
+#include "qzc.h"

#include "bgpd/bgpd.h"
#include "bgpd/bgp_attr.h"
@@ -68,6 +69,7 @@ static const struct option longopts[] =
{ "user", required_argument, NULL, 'u'},
{ "group", required_argument, NULL, 'g'},
{ "skip_runas", no_argument, NULL, 'S'},
+ { "zeromq", required_argument, NULL, 'Z'},
{ "version", no_argument, NULL, 'v'},
{ "dryrun", no_argument, NULL, 'C'},
{ "help", no_argument, NULL, 'h'},
@@ -216,6 +218,10 @@ sigusr1 (void)
zlog_rotate (NULL);
}

+#ifdef HAVE_CCAPNPROTO
+static struct qzc_sock *qzc_sock = NULL;
+#endif /* HAVE_CCAPNPROTO */
+
/*
Try to free up allocations we know about so that diagnostic tools such as
valgrind are able to better illuminate leaks.
@@ -333,6 +339,13 @@ bgp_exit (int status)
/* reverse bgp_scan_init */
bgp_scan_finish ();

+ QZC_NODE_UNREG(bm)
+#ifdef HAVE_CCAPNPROTO
+ if (qzc_sock)
+ qzc_close (qzc_sock);
+ qzc_finish ();
+#endif /* HAVE_CCAPNPROTO */
+
/* reverse bgp_master_init */
if (bm->master)
thread_master_free (bm->master);
@@ -356,6 +369,9 @@ main (int argc, char **argv)
int daemon_mode = 0;
int dryrun = 0;
char *progname;
+#ifdef HAVE_ZEROMQ
+ char *zmq_sock = NULL;
+#endif /* HAVE_ZEROMQ */
struct thread thread;
int tmp_port;
int skip_runas = 0;
@@ -375,7 +391,7 @@ main (int argc, char **argv)
/* Command line argument treatment. */
while (1)
{
- opt = getopt_long (argc, argv, "df:i:z:hp:l:A:P:rnu:g:vCS", longopts, 0);
+ opt = getopt_long (argc, argv, "df:i:z:hp:l:A:P:rnu:g:Z:vCS", longopts, 0);

if (opt == EOF)
break;
@@ -436,6 +452,11 @@ main (int argc, char **argv)
case 'S': /* skip run as = override bgpd_privs */
skip_runas = 1;
break;
+ case 'Z':
+#ifdef HAVE_ZEROMQ
+ zmq_sock = optarg;
+#endif /* HAVE_ZEROMQ */
+ break;
case 'v':
print_version (progname);
exit (0);
@@ -466,6 +487,11 @@ main (int argc, char **argv)
/* BGP related initialization. */
bgp_init ();

+#ifdef HAVE_ZEROMQ
+ if (zmq_sock)
+ qzc_sock = qzc_bind (bm->master, zmq_sock);
+#endif /* HAVE_ZEROMQ */
+
/* Parse config file. */
vty_read_config (config_file, config_default);

diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index c7fe6b21e2e0..337a5d0386a0 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -38,6 +38,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "hash.h"
#include "workqueue.h"
#include "table.h"
+#include "qzc.h"

#include "bgpd/bgpd.h"
#include "bgpd/bgp_table.h"
@@ -67,6 +68,11 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "bgpd/bgp_snmp.h"
#endif /* HAVE_SNMP */

+#ifdef HAVE_CCAPNPROTO
+#include "bgp.bcapnp.h"
+#include "bgpd.ndef.hi"
+#endif /* HAVE_CCAPNPROTO */
+
/* BGP process wide configuration. */
static struct bgp_master bgp_master;

@@ -179,7 +185,7 @@ bgp_config_check (struct bgp *bgp, int config)
}

/* Set BGP router identifier. */
-static int
+int
bgp_router_id_set (struct bgp *bgp, struct in_addr *id)
{
struct peer *peer;
@@ -755,6 +761,8 @@ peer_free (struct peer *peer)

bgp_unlock(peer->bgp);

+ QZC_NODE_UNREG(peer)
+
/* this /ought/ to have been done already through bgp_stop earlier,
* but just to be sure..
*/
@@ -908,6 +916,8 @@ peer_new (struct bgp *bgp)
sp = getservbyname ("bgp", "tcp");
peer->port = (sp == NULL) ? BGP_PORT_DEFAULT : ntohs (sp->s_port);

+ QZC_NODE_REG(peer, peer)
+
return peer;
}

@@ -1121,6 +1131,39 @@ peer_remote_as (struct bgp *bgp, union sockunion *su, as_t *as,
return 0;
}

+struct peer *
+peer_create_api (struct bgp *bgp, const char *host, as_t as)
+{
+ int ret;
+ union sockunion su;
+ struct peer *peer;
+ as_t local_as;
+
+ ret = str2sockunion (host, &su);
+ if (ret < 0)
+ return NULL;
+
+#if 0
+ if (peer_address_self_check (&su))
+ return NULL;
+#endif
+
+ peer = peer_lookup (bgp, &su);
+ if (peer)
+ return NULL;
+
+ /* If the peer is not part of our confederation, and its not an
+ iBGP peer then spoof the source AS */
+ if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION)
+ && ! bgp_confederation_peers_check (bgp, as)
+ && bgp->as != as)
+ local_as = bgp->confed_id;
+ else
+ local_as = bgp->as;
+
+ return peer_create (&su, bgp, local_as, as, 0, 0);
+}
+
/* Activate the peer or peer group for specified AFI and SAFI. */
int
peer_activate (struct peer *peer, afi_t afi, safi_t safi)
@@ -2150,6 +2193,7 @@ bgp_vrf_lookup_per_name (struct bgp *bgp, const char *name, int create)
vrf->rib[afi]->type = BGP_TABLE_VRF;
}

+ QZC_NODE_REG(vrf, bgp_vrf)
listnode_add (bgp->vrfs, vrf);
return vrf;
}
@@ -2283,6 +2327,8 @@ bgp_vrf_delete_rd (struct bgp_vrf *vrf)
prefix_rd2str(&vrf->outbound_rd, vrf_rd_str, sizeof(vrf_rd_str));
zlog_info ("deleting rd %s", vrf_rd_str);

+ QZC_NODE_UNREG(vrf)
+
bgp_vrf_clean_tables (vrf);

bgp_vrf_rt_import_unset (vrf);
@@ -2301,6 +2347,7 @@ bgp_vrf_delete_int (void *arg)
zlog_info ("deleting vrf %s", vrf_rd_str);

bgp_vrf_delete_rd (vrf);
+ QZC_NODE_UNREG(vrf)

if (vrf->name)
free (vrf->name);
@@ -2364,6 +2411,7 @@ bgp_create (as_t *as, const char *name)
bgp->vrfs->del = bgp_vrf_delete_int;
bgp->rt_subscribers = hash_create(bgp_rt_hash_key, bgp_rt_hash_cmp);

+ QZC_NODE_REG(bgp, bgp)
THREAD_TIMER_ON (bm->master, bgp->t_startup, bgp_startup_timer_expire,
bgp, bgp->restart_time);

@@ -2408,6 +2456,30 @@ bgp_lookup_by_name (const char *name)
return NULL;
}

+struct bgp *
+bgp_create_api (struct bgp_master *ignore, as_t as)
+{
+ struct bgp *bgp = NULL;
+
+ if (bgp_get_default ())
+ return NULL;
+
+ bgp = bgp_create (&as, NULL);
+ bgp_router_id_set(bgp, &router_id_zebra);
+
+ /* Create BGP server socket, if first instance. */
+ if (list_isempty(bm->bgp)
+ && !bgp_option_check (BGP_OPT_NO_LISTEN))
+ if (bgp_socket (bm->port, bm->address) < 0)
+ {
+ bgp_delete (bgp);
+ return NULL;
+ }
+
+ listnode_add (bm->bgp, bgp);
+ return bgp;
+}
+
/* Called from VTY commands. */
int
bgp_get (struct bgp **bgp_val, as_t *as, const char *name)
@@ -2486,6 +2558,7 @@ bgp_delete (struct bgp *bgp)
SET_FLAG(bgp->flags, BGP_FLAG_DELETING);

THREAD_OFF (bgp->t_startup);
+ QZC_NODE_UNREG(bgp)

for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
{
@@ -2522,8 +2595,6 @@ bgp_delete (struct bgp *bgp)
!bgp_flag_check (bgp, BGP_FLAG_GR_PRESERVE_FWD))
bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
}
-
- peer_delete (peer);
}

for (ALL_LIST_ELEMENTS (bgp->group, node, next, group))
@@ -2538,16 +2609,8 @@ bgp_delete (struct bgp *bgp)
bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
}
}
- peer_group_delete (group);
}

- assert (listcount (bgp->rsclient) == 0);
-
- if (bgp->peer_self) {
- peer_delete(bgp->peer_self);
- bgp->peer_self = NULL;
- }
-
/*
* Free pending deleted routes. Unfortunately, it also has to process
* all the pending activity for other instances of struct bgp.
@@ -2557,6 +2620,19 @@ bgp_delete (struct bgp *bgp)
*/
bgp_process_queues_drain_immediate();

+ /* workqueues hold references to peers */
+ for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
+ peer_delete (peer);
+ for (ALL_LIST_ELEMENTS (bgp->group, node, next, group))
+ peer_group_delete (group);
+
+ assert (listcount (bgp->rsclient) == 0);
+
+ if (bgp->peer_self) {
+ peer_delete(bgp->peer_self);
+ bgp->peer_self = NULL;
+ }
+
/* Remove visibility via the master list - there may however still be
* routes to be processed still referencing the struct bgp.
*/
@@ -6117,6 +6193,11 @@ bgp_master_init (void)
bm->port = BGP_PORT_DEFAULT;
bm->master = thread_master_create ();
bm->start_time = bgp_clock ();
+
+#ifdef HAVE_CCAPNPROTO
+ qzc_init ();
+#endif
+ QZC_NODE_REG(bm, bgp_master)
}


@@ -6200,3 +6281,8 @@ bgp_terminate (void)
bm->process_vrf_queue = NULL;
}
}
+
+#ifdef HAVE_CCAPNPROTO
+#include "bgpd.ndef.i"
+#endif /*HAVE_CCAPNPROTO */
+
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index 0d5bf5eea6fc..09f9c6a1c551 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -25,6 +25,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "sockunion.h"
#include "bgp_ecommunity.h"
#include "prefix.h"
+#include "qzc.h"

/* Typedef BGP specific types. */
typedef u_int32_t as_t;
@@ -74,6 +75,8 @@ struct bgp_master
#define BGP_OPT_MULTIPLE_INSTANCE (1 << 1)
#define BGP_OPT_CONFIG_CISCO (1 << 2)
#define BGP_OPT_NO_LISTEN (1 << 3)
+
+ QZC_NODE
};

/* BGP instance structure. */
@@ -202,6 +205,7 @@ struct bgp

struct hash *rt_subscribers;

+ QZC_NODE
};

struct bgp_rt_sub
@@ -251,6 +255,8 @@ struct bgp_vrf
/* internal flag */
#define BGP_VRF_RD_UNSET 1
uint16_t flag;
+
+ QZC_NODE
};

struct bgp_api_route
@@ -645,6 +651,8 @@ struct peer
#define PEER_RMAP_TYPE_NOSET (1 << 5) /* not allow to set commands */
#define PEER_RMAP_TYPE_IMPORT (1 << 6) /* neighbor route-map import */
#define PEER_RMAP_TYPE_EXPORT (1 << 7) /* neighbor route-map export */
+
+ QZC_NODE
};

#define PEER_PASSWORD_MINLEN (1)
@@ -913,6 +921,7 @@ extern int bgp_nexthop_set (union sockunion *, union sockunion *,
extern struct bgp *bgp_get_default (void);
extern struct bgp *bgp_lookup (as_t, const char *);
extern struct bgp *bgp_lookup_by_name (const char *);
+extern struct bgp *bgp_create_api (struct bgp_master *, as_t as);
extern struct peer *peer_lookup (struct bgp *, union sockunion *);
extern struct peer_group *peer_group_lookup (struct bgp *, const char *);
extern struct peer_group *peer_group_get (struct bgp *, const char *);
@@ -959,6 +968,7 @@ extern void bgp_lock (struct bgp *);
extern void bgp_unlock (struct bgp *);

extern void bgp_router_id_zebra_bump (void);
+extern int bgp_router_id_set (struct bgp *, struct in_addr *);
extern int bgp_router_id_static_set (struct bgp *, struct in_addr);

extern int bgp_cluster_id_set (struct bgp *, struct in_addr *);
@@ -981,6 +991,7 @@ extern int peer_rsclient_active (struct peer *);

extern int peer_remote_as (struct bgp *, union sockunion *, as_t *, afi_t, safi_t);
extern int peer_group_remote_as (struct bgp *, const char *, as_t *);
+extern struct peer *peer_create_api (struct bgp *, const char * host, as_t as);
extern int peer_delete (struct peer *peer);
extern int peer_group_delete (struct peer_group *);
extern int peer_group_remote_as_delete (struct peer_group *);
--
2.1.4


_______________________________________________
Quagga-dev mailing list
Quagga-dev@lists.quagga.net
https://lists.quagga.net/mailman/listinfo/quagga-dev