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

This enhancement to the bgp.capnp scheme files permits bgp daemon
to handle get requests to parse a routing table. It is possible
to retrieve the next element of a table, by reusing the passed
as parameter element, then, the query will response with the
associated next element.

Signed-off-by: David Lamparter <equi...@opensourcerouting.org>
Signed-off-by: Philippe Guibert <philippe.guib...@6wind.com>
---
 bgpd/bgp.bcapnp.c | 23 +++++++++++++++---
 bgpd/bgp.bcapnp.h |  6 ++++-
 bgpd/bgp.capnp    | 13 ++++++++++
 bgpd/bgp_route.c  | 52 +++++++++++++++++++++++++++++++++++++++
 bgpd/bgpd.h       | 10 +++++++-
 bgpd/bgpd.ndef.i  | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++----
 6 files changed, 166 insertions(+), 11 deletions(-)

diff --git a/bgpd/bgp.bcapnp.c b/bgpd/bgp.bcapnp.c
index 0da76f7a492b..2bf038128cd1 100644
--- a/bgpd/bgp.bcapnp.c
+++ b/bgpd/bgp.bcapnp.c
@@ -1109,13 +1109,11 @@ void qcapn_BGPVRFRoute_set(struct bgp_api_route *s, 
capn_ptr p)
 }
 
 
-capn_ptr qcapn_new_BGPVRFRoute(struct capn_segment *s)
+capn_ptr qcapn_new_BGPVRFRoute(struct capn_segment *s, uint8_t extend_by)
 {
-    return capn_new_struct(s, 8, 2);
+    return capn_new_struct(s, CAPN_BGPVRF_ROUTE_DEF_SIZE + extend_by, 2);
 }
 
-
-
 void qcapn_BGPEventVRFRoute_read(struct bgp_event_vrf *s, capn_ptr p)
 {
     uint64_t tmp;
@@ -1246,3 +1244,20 @@ capn_ptr qcapn_new_BGPEventShut(struct capn_segment *s)
     return capn_new_struct(s, 8, 1);
 }
 
+capn_ptr qcapn_new_BGPVRFInfoIter(struct capn_segment *s)
+{
+    return capn_new_struct(s, 8, 0);
+}
+
+void qcapn_BGPVRFInfoIter_write(const unsigned long s, capn_ptr p, int offset)
+{
+    capn_resolve(&p);
+    capn_write64(p, offset, s);
+}
+
+void qcapn_BGPVRFInfoIter_read(unsigned long *s, capn_ptr p, int offset)
+{
+    capn_resolve(&p);
+
+    *s = capn_read64(p, offset);
+}
diff --git a/bgpd/bgp.bcapnp.h b/bgpd/bgp.bcapnp.h
index fafaf6cce83a..3b8ce361f6b2 100644
--- a/bgpd/bgp.bcapnp.h
+++ b/bgpd/bgp.bcapnp.h
@@ -43,7 +43,7 @@ capn_ptr qcapn_new_BGPVRF(struct capn_segment *s);
 void qcapn_BGPVRFRoute_read(struct bgp_api_route *s, capn_ptr p);
 void qcapn_BGPVRFRoute_write(const struct bgp_api_route *s, capn_ptr p);
 void qcapn_BGPVRFRoute_set(struct bgp_api_route *s, capn_ptr p);
-capn_ptr qcapn_new_BGPVRFRoute(struct capn_segment *s);
+capn_ptr qcapn_new_BGPVRFRoute(struct capn_segment *s, uint8_t extend_by);
 void qcapn_BGPEventVRFRoute_read(struct bgp_event_vrf *s, capn_ptr p);
 void qcapn_BGPEventVRFRoute_write(const struct bgp_event_vrf *s, capn_ptr p);
 void qcapn_BGPEventVRFRoute_set(struct bgp_event_vrf *s, capn_ptr p);
@@ -52,5 +52,9 @@ void qcapn_BGPEventShut_read(struct bgp_event_shut *s, 
capn_ptr p);
 void qcapn_BGPEventShut_write(const struct bgp_event_shut *s, capn_ptr p);
 void qcapn_BGPEventShut_set(struct bgp_event_shut *s, capn_ptr p);
 capn_ptr qcapn_new_BGPEventShut(struct capn_segment *s);
+capn_ptr qcapn_new_BGPVRFInfoIter(struct capn_segment *s);
+void qcapn_BGPVRFInfoIter_write(const unsigned long s, capn_ptr p, int offset);
+void qcapn_BGPVRFInfoIter_read(unsigned long *s, capn_ptr p, int offset);
 
+#define  CAPN_BGPVRF_ROUTE_DEF_SIZE  8
 #endif /* CAPN_C4C948A17D3B2250 */
diff --git a/bgpd/bgp.capnp b/bgpd/bgp.capnp
index da56ee4d2548..27a917ff62cd 100644
--- a/bgpd/bgp.capnp
+++ b/bgpd/bgp.capnp
@@ -40,6 +40,9 @@ struct AfiSafiKey $cgennaked $cgetfield {
        afi                      @0 :UInt8 $ctype("afi_t");
        safi                     @1 :UInt8 $ctype("safi_t");
 }
+struct AfiKey $cgennaked $cgetfield {
+       afi                      @0 :UInt8 $ctype("afi_t");
+}
 struct ExtCommunityList {
        values                   @0 :List(UInt64);
 }
@@ -47,6 +50,9 @@ struct PrefixV4 {
        addr                     @0 :UInt32;
        prefixlen                @1 :UInt8;
 }
+struct VRFTableIter $ctype("struct tbliter_v4") $cgen {
+       prefix                   @0 :PrefixV4;
+}
 
 struct BGP $ctype("struct bgp") $cgen
                $csetter("bgp_%%_set")
@@ -159,6 +165,13 @@ struct BGPVRF $ctype("struct bgp_vrf") $cgen
        rtExport                 @2 :ExtCommunityList;
 }
 
+struct BGPVRFRoute $ctype("struct bgp_api_route") $cgen
+{
+       prefix                   @0 :PrefixV4;
+       nexthop                  @1 :IPv4;
+       label                    @2 :UInt32;
+}
+
 struct BGPEventVRFRoute $ctype("struct bgp_event_vrf") $cgen
 {
        announce                 @0 :Bool;
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index d26e64256985..652c47e6274a 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -1543,6 +1543,58 @@ bgp_process_announce_selected (struct peer *peer, struct 
bgp_info *selected,
   return 0;
 }
 
+bool bgp_api_route_get (struct bgp_api_route *out, struct bgp_node *bn,
+                        int iter_on_multipath, void **next)
+{
+  struct bgp_info *sel, *iter;
+
+  memset(out, 0, sizeof (*out));
+  if (bn->p.family != AF_INET)
+    return false;
+  if (!bn->info)
+    return false;
+
+  prefix_copy ((struct prefix *)&out->prefix, &bn->p);
+
+  for (sel = bn->info; sel; sel = sel->next)
+    {
+      if (iter_on_multipath)
+        {
+          if (CHECK_FLAG (sel->flags, BGP_INFO_MULTIPATH))
+            break;
+        }
+      else
+        {
+          if (CHECK_FLAG (sel->flags, BGP_INFO_SELECTED))
+            break;
+          {
+            /* prepare sel with start of list to look for multipath entries */
+            /* Since this function should be first called with 
iter_on_multipath set to 0 */
+            /* sel should correspond to the start of the list */
+            sel = bn->info;
+            break;
+          }
+        }
+    }
+
+  if (!sel)
+    return false;
+
+  if (sel->attr && sel->attr->extra)
+    out->nexthop = sel->attr->extra->mp_nexthop_global_in;
+  if (sel->extra && sel->extra->nlabels)
+    out->label = sel->extra->labels[0] >> 4;
+
+  /* now that an entry with SELECTED flag was found, check for possibly 
MULTIPATH entries
+     in next items */
+  for (iter = sel->next; iter; iter = iter->next)
+    if (CHECK_FLAG (iter->flags, BGP_INFO_MULTIPATH))
+      {
+        *next = iter;
+        break;
+      }
+  return true;
+}
 
 static bool rd_same (const struct prefix_rd *a, const struct prefix_rd *b)
 {
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index dfc2a4e97ef2..4c79071abe2f 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -278,6 +278,11 @@ struct bgp_event_shut
   uint8_t type, subtype;
 };
 
+struct tbliter_v4
+{
+  struct prefix_ipv4 prefix;
+};
+
 struct bgp_api_route
 {
   struct prefix_ipv4 prefix;
@@ -1120,5 +1125,8 @@ extern void bgp_vrf_rt_import_unset (struct bgp_vrf *vrf);
 extern void bgp_vrf_rt_export_unset (struct bgp_vrf *vrf);
 extern int bgp_vrf_static_set (struct bgp_vrf *vrf, afi_t afi, const struct 
bgp_api_route *route);
 extern int bgp_vrf_static_unset (struct bgp_vrf *vrf, afi_t afi, const struct 
bgp_api_route *route);
-
+extern bool bgp_api_route_get (struct bgp_api_route *out, 
+                               struct bgp_node *bn,
+                               int iter_on_multipath, 
+                               void **next);
 #endif /* _QUAGGA_BGPD_H */
diff --git a/bgpd/bgpd.ndef.i b/bgpd/bgpd.ndef.i
index 54b5d185aa08..c235b557479f 100644
--- a/bgpd/bgpd.ndef.i
+++ b/bgpd/bgpd.ndef.i
@@ -524,6 +524,7 @@ _qzc_get_bgp_vrf_2(struct bgp_vrf *p,
     struct tbliter_v4 iter, nextiter;
     const struct tbliter_v4 *iterptr;
     afi_t afi;
+    void *next  = NULL;
 
     if (req->ctxtype != 0xac25a73c3ff455c0)
         /* error */
@@ -556,16 +557,75 @@ _qzc_get_bgp_vrf_2(struct bgp_vrf *p,
     if (val) {
         struct bgp_api_route *outptr;
         struct bgp_api_route tmpval;
-        if (!bgp_api_route_get(&tmpval, val))
-            return;
+
+        memset(&tmpval,0, sizeof(struct bgp_api_route));
         outptr = &tmpval;
-        rep->data = qcapn_new_BGPVRFRoute(seg);
-        qcapn_BGPVRFRoute_write(outptr, rep->data);
+        rep->data = qcapn_new_BGPVRFRoute(seg, sizeof(next));
         rep->datatype = 0x8f217eb4bad6c06f;
+        qcapn_BGPVRFRoute_write(outptr, rep->data);
+        if (!bgp_api_route_get(&tmpval, val, 0, &next))
+            return;
+
+        qcapn_BGPVRFRoute_write(outptr, rep->data);
+        /* send value of pointer to next  ri which has BGP_INFO_MULTIPATH flag,
+           sending 0 means there is no next element */
+        qcapn_BGPVRFInfoIter_write((unsigned long) next,
+                                   rep->data, CAPN_BGPVRF_ROUTE_DEF_SIZE);
+
     }
 }
 
+/* Iterated GET bgp_vrf:4 <> bgp_vrf->rib ()*/
 
+static void
+_qzc_get_bgp_vrf_4(struct bgp_vrf *p,
+        struct QZCGetReq *req, struct QZCGetRep *rep,
+        struct capn_segment *seg)
+{
+    unsigned long mpath_iter_ptr = 0;
+    struct bgp_node dummy;
+    void *next = NULL;
+    struct bgp_api_route *outptr;
+    struct bgp_api_route tmpval;
+
+    if (req->itertype == 0xeb8ab4f58b7753ee) {
+        qcapn_BGPVRFInfoIter_read(&mpath_iter_ptr, req->iterdata, 0);
+    } else {
+        /* error */
+        zlog_err("%s: req->itertype:%016lx != 0xeb8ab4f58b7753ee",
+                   __func__, req->itertype);
+        return;
+    }
+
+    memset(&dummy, 0, sizeof(dummy));
+    dummy.p.family = AF_INET;
+    dummy.info = (struct bgp_info*) mpath_iter_ptr;
+    rep->datatype = 0;
+    rep->itertype = 0; /* by default, no need to iterate more */
+
+    /* do not write route if bgp info has nothing, but keep next iteration */
+    memset(&tmpval,0, sizeof(struct bgp_api_route));
+    outptr = &tmpval;
+    rep->data = qcapn_new_BGPVRFRoute(seg, 0);
+    rep->datatype = 0x8f217eb4bad6c06f;
+    qcapn_BGPVRFRoute_write(outptr, rep->data);
+
+    /* do this way to look for multipath entries instead of selected */
+    if (!bgp_api_route_get(&tmpval, &dummy, 1, &next))
+        return;
+
+    qcapn_BGPVRFRoute_write(outptr, rep->data);
+    /* send value of pointer to next  ri which has BGP_INFO_MULTIPATH flag,
+       sending 0 means there is no next element */
+    if ((unsigned long) next)
+      {
+        /* This way bgp_configurator can know there is something next after the
+         route transfert done above */
+        rep->itertype = 0xeb8ab4f58b7753ee;
+        rep->nextiter = qcapn_new_BGPVRFInfoIter(seg);
+        qcapn_BGPVRFInfoIter_write((unsigned long) next, rep->nextiter, 0);
+      }
+}
 
 static struct bgp_node * qcap_iter_bgp_vrf_route(struct bgp_table *table,
         const struct tbliter_v4 *prev_iter,
@@ -635,7 +695,7 @@ _qzc_get_bgp_vrf_3(struct bgp_vrf *p,
         if (!bgp_api_static_get(&tmpval, val))
             return;
         outptr = &tmpval;
-        rep->data = qcapn_new_BGPVRFRoute(seg);
+        rep->data = qcapn_new_BGPVRFRoute(seg, 0);
         qcapn_BGPVRFRoute_write(outptr, rep->data);
         rep->datatype = 0x8f217eb4bad6c06f;
     }
@@ -734,6 +794,9 @@ _qzc_get_bgp_vrf(void *entity, struct QZCGetReq *req, 
struct QZCGetRep *rep,
     case 3:
         _qzc_get_bgp_vrf_3(p, req, rep, seg);
         return;
+    case 4:
+        _qzc_get_bgp_vrf_4(p, req, rep, seg);
+        return;
     default:
         return;
     }
-- 
2.1.4


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

Reply via email to