From: David Lamparter <equi...@opensourcerouting.org>

This commit brings necessary changes in order to send a notification
through capnproto.

Signed-off-by: David Lamparter <equi...@opensourcerouting.org>
Signed-off-by: Philippe Guibert <philippe.guib...@6wind.com>
---
 bgpd/Makefile.am |   4 +++
 bgpd/bgp.capnp   |  22 ++++++++++++
 bgpd/bgp_route.c |  22 ++++++++++++
 bgpd/bgp_zmq.c   | 105 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 bgpd/bgpd.c      |   4 +++
 bgpd/bgpd.h      |  24 +++++++++++++
 lib/memtypes.c   |   1 +
 7 files changed, 182 insertions(+)
 create mode 100644 bgpd/bgp_zmq.c

diff --git a/bgpd/Makefile.am b/bgpd/Makefile.am
index 7cb5d8024757..1304edddeccb 100644
--- a/bgpd/Makefile.am
+++ b/bgpd/Makefile.am
@@ -26,6 +26,10 @@ noinst_HEADERS = \
        bgp_advertise.h bgp_snmp.h bgp_vty.h bgp_mpath.h \
        bgp_encap.h bgp_encap_tlv.h bgp_encap_types.h bgp_nht.h
 
+if HAVE_ZEROMQ
+libbgp_a_SOURCES += bgp_zmq.c
+endif
+
 bgpd_SOURCES = bgp_main.c
 
 bgpd_LDADD = libbgp.a ../lib/libzebra.la @LIBCAP@ @LIBM@ @ZEROMQ_LIBS@ 
@CAPN_C_LIBS@
diff --git a/bgpd/bgp.capnp b/bgpd/bgp.capnp
index 2603e6983ad6..da56ee4d2548 100644
--- a/bgpd/bgp.capnp
+++ b/bgpd/bgp.capnp
@@ -43,6 +43,10 @@ struct AfiSafiKey $cgennaked $cgetfield {
 struct ExtCommunityList {
        values                   @0 :List(UInt64);
 }
+struct PrefixV4 {
+       addr                     @0 :UInt32;
+       prefixlen                @1 :UInt8;
+}
 
 struct BGP $ctype("struct bgp") $cgen
                $csetter("bgp_%%_set")
@@ -80,6 +84,8 @@ struct BGP $ctype("struct bgp") $cgen
 
        restartTime             @25 :UInt32;
        stalepathTime           @26 :UInt32 $csetwrite;
+
+       notifyZMQUrl            @27 :Text;
 }
 
 struct BGPAfiSafi $ctype("struct bgp") $cgen $carraykey("AfiSafiKey") {
@@ -153,4 +159,20 @@ struct BGPVRF $ctype("struct bgp_vrf") $cgen
        rtExport                 @2 :ExtCommunityList;
 }
 
+struct BGPEventVRFRoute $ctype("struct bgp_event_vrf") $cgen
+{
+       announce                 @0 :Bool;
+       outboundRd               @1 :UInt64;
+       prefix                   @2 :PrefixV4;
+       nexthop                  @3 :IPv4;
+       label                    @4 :UInt32;
+}
+
+struct BGPEventShut $ctype("struct bgp_event_shut") $cgen
+{
+       peer                     @0 :IPv4;
+       type                     @1 :UInt8;
+       subtype                  @2 :UInt8;
+}
+
 # vim: set noet ts=8 nowrap tw=0:
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 07aa5a259f32..d26e64256985 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -1590,8 +1590,22 @@ void
 bgp_vrf_update (struct bgp_vrf *vrf, afi_t afi, struct bgp_node *rn,
                 struct bgp_info *selected, uint8_t announce)
 {
+  struct bgp_event_vrf event = {
+    .announce         = announce,
+    .outbound_rd      = vrf->outbound_rd,
+    .prefix.family    = rn->p.family,
+    .prefix.prefixlen = rn->p.prefixlen,
+    .prefix.prefix    = rn->p.u.prefix4,
+  };
+
   if(!vrf || (rn && bgp_node_table (rn)->type != BGP_TABLE_VRF))
     return;
+
+  if (selected->extra->nlabels)
+    event.label = selected->extra->labels[0] >> 4;
+  else
+    event.label = 0;
+
   if (announce == true)
     {
       if(CHECK_FLAG (selected->flags, BGP_INFO_UPDATE_SENT))
@@ -1635,6 +1649,14 @@ bgp_vrf_update (struct bgp_vrf *vrf, afi_t afi, struct 
bgp_node *rn,
         zlog_debug ("vrf[%s] %s: prefix withdrawn nh %s label %s",
                     vrf_rd_str, pfx_str, nh_str, label_str);
     }
+  if (afi == AFI_IP)
+    {
+      if (selected->attr && selected->attr->extra)
+        event.nexthop = selected->attr->extra->mp_nexthop_global_in;
+#ifdef HAVE_ZEROMQ
+      bgp_notify_route (vrf->bgp, &event);
+#endif /* HAVE_ZEROMQ */
+    }
 }
 
 int
diff --git a/bgpd/bgp_zmq.c b/bgpd/bgp_zmq.c
new file mode 100644
index 000000000000..d2e7fb14d40b
--- /dev/null
+++ b/bgpd/bgp_zmq.c
@@ -0,0 +1,105 @@
+/*
+ * bgpd ZeroMQ/Cap'n'Proto event update feed
+ * Copyright (C) 2016  David Lamparter, for NetDEF, Inc.
+ *
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+*/
+
+#include <zebra.h>
+#include <zmq.h>
+#include "memory.h"
+
+#include "prefix.h"
+#include "memory.h"
+#include "log.h"
+#include "qzmq.h"
+#include "bgp.bcapnp.h"
+
+#include "bgpd.h"
+
+void
+bgp_notify_cleanup (struct bgp *bgp)
+{
+  if (bgp->notify_zmq_url)
+    XFREE (MTYPE_ZMQ_NOTIFY, bgp->notify_zmq_url);
+  if (bgp->notify_zmq)
+    zmq_close (bgp->notify_zmq);
+}
+
+int
+bgp_notify_zmq_url_set (struct bgp *bgp, const char *url)
+{
+  if (bgp->notify_zmq_url)
+    {
+      if (url && !strcmp (url, bgp->notify_zmq_url))
+        return 0;
+
+      XFREE (MTYPE_ZMQ_NOTIFY, bgp->notify_zmq_url);
+      bgp->notify_zmq_url = NULL;
+    }
+  if (bgp->notify_zmq)
+    {
+      zmq_close (bgp->notify_zmq);
+      bgp->notify_zmq = NULL;
+    }
+
+  if (!url || !*url)
+    return 0;
+
+  bgp->notify_zmq_url = XSTRDUP (MTYPE_ZMQ_NOTIFY, url);
+  bgp->notify_zmq = zmq_socket (qzmq_context, ZMQ_PUB);
+  if (!bgp->notify_zmq)
+    {
+      zlog_err ("failed to open ZeroMQ PUB socket: %s (%d)",
+                strerror (errno), errno);
+      return -1;
+    }
+  if (zmq_bind (bgp->notify_zmq, bgp->notify_zmq_url))
+    {
+      zlog_err ("ZeroMQ event PUB bind failed: %s (%d)",
+                strerror (errno), errno);
+      zmq_close (bgp->notify_zmq);
+      return -1;
+    }
+  return 0;
+}
+
+static void
+bgp_notify_send (struct bgp *bgp, struct bgp_event_vrf *update)
+{
+  struct capn rc;
+  capn_init_malloc(&rc);
+  struct capn_segment *cs = capn_root(&rc).seg;
+  capn_ptr p = qcapn_new_BGPEventVRFRoute (cs);
+  qcapn_BGPEventVRFRoute_write (update, p);
+  capn_setp(capn_root(&rc), 0, p);
+
+  uint8_t buf[4096];
+  ssize_t rs = capn_write_mem(&rc, buf, sizeof(buf), 0);
+  capn_free(&rc);
+
+  zmq_send (bgp->notify_zmq, buf, rs, 0);
+}
+
+void
+bgp_notify_route (struct bgp *bgp, struct bgp_event_vrf *update)
+{
+  bgp_notify_send (bgp, update);
+}
+
+void
+bgp_notify_shut (struct bgp *bgp, struct bgp_event_shut *shut)
+{
+}
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index 337a5d0386a0..567cdd0af7b5 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -2557,6 +2557,10 @@ bgp_delete (struct bgp *bgp)
 
   SET_FLAG(bgp->flags, BGP_FLAG_DELETING);
 
+#ifdef HAVE_ZEROMQ
+  bgp_notify_cleanup (bgp);
+#endif /* HAVE_ZEROMQ */
+
   THREAD_OFF (bgp->t_startup);
   QZC_NODE_UNREG(bgp)
 
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index 09f9c6a1c551..dfc2a4e97ef2 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -205,6 +205,10 @@ struct bgp
 
   struct hash *rt_subscribers;
 
+  /* outbound update feeds */
+  char *notify_zmq_url;
+  void *notify_zmq;
+
   QZC_NODE
 };
 
@@ -259,6 +263,21 @@ struct bgp_vrf
   QZC_NODE
 };
 
+struct bgp_event_vrf
+{
+  bool announce;
+  struct prefix_rd outbound_rd;
+  struct prefix_ipv4 prefix;
+  struct in_addr nexthop;
+  uint32_t label;
+};
+
+struct bgp_event_shut
+{
+  struct in_addr peer;
+  uint8_t type, subtype;
+};
+
 struct bgp_api_route
 {
   struct prefix_ipv4 prefix;
@@ -987,6 +1006,11 @@ extern int bgp_timers_unset (struct bgp *);
 extern int bgp_default_local_preference_set (struct bgp *, u_int32_t);
 extern int bgp_default_local_preference_unset (struct bgp *);
 
+extern int bgp_notify_zmq_url_set (struct bgp *, const char *url);
+extern void bgp_notify_route (struct bgp *, struct bgp_event_vrf *update);
+extern void bgp_notify_shut (struct bgp *, struct bgp_event_shut *shut);
+extern void bgp_notify_cleanup (struct bgp *);
+
 extern int peer_rsclient_active (struct peer *);
 
 extern int peer_remote_as (struct bgp *, union sockunion *, as_t *, afi_t, 
safi_t);
diff --git a/lib/memtypes.c b/lib/memtypes.c
index 3e43a857322e..f3605d5aabc5 100644
--- a/lib/memtypes.c
+++ b/lib/memtypes.c
@@ -161,6 +161,7 @@ struct memory_list memory_list_bgp[] =
   { MTYPE_ENCAP_TLV,           "ENCAP TLV",                    },
   { MTYPE_BGP_VRF,             "BGP VRF",                      },
   { MTYPE_BGP_RT_SUB,          "BGP RT SUB",                   },
+  { MTYPE_ZMQ_NOTIFY,          "ZMQ notify",                   },
   { -1, NULL }
 };
 
-- 
2.1.4


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

Reply via email to