From: James Li <[email protected]>

This patch provides the ability to send the gateway and ifindex
instead of ZEBRA_MESSAGE_NEXTHOP which sends the gateway or ifindex.

Signed-off-by: James Li <[email protected]>
Signed-off-by: Dinesh Dutt <[email protected]>
Reviewed-by: JR Rivers <[email protected]>
---
 lib/zclient.c     |   34 +++++++++++++++++++++++++++++++++-
 lib/zclient.h     |    1 +
 lib/zebra.h       |    1 +
 zebra/rib.h       |    2 ++
 zebra/zebra_rib.c |   30 ++++++++++++++++++++++++++++++
 zebra/zserv.c     |    5 +++++
 6 files changed, 72 insertions(+), 1 deletion(-)

diff --git a/lib/zclient.c b/lib/zclient.c
index 8e443e2..1433f3c 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -475,6 +475,21 @@ zclient_connect (struct thread *t)
   * nexthop information is provided, and the message describes a prefix
   * to blackhole or reject route.
   *
+  * The original struct zapi_ipv4, zapi_ipv4_route() and zread_ipv4_*()
+  * infrastructure was built around the traditional (32-bit "gate OR
+  * ifindex") nexthop data unit. A special encoding can be used to feed
+  * onlink (64-bit "gate AND ifindex") nexthops into zapi_ipv4_route()
+  * using the same zapi_ipv4 structure. This is done by setting zapi_ipv4
+  * fields as follows:
+  *  - .message |= ZAPI_MESSAGE_NEXTHOP | ZAPI_MESSAGE_ONLINK
+  *  - .nexthop_num == .ifindex_num
+  *  - .nexthop and .ifindex are filled with gate and ifindex parts of
+  *    each compound nexthop, both in the same order
+  *
+  * zapi_ipv4_route() will produce two nexthop data units for each such
+  * interleaved 64-bit nexthop. On the zserv side of the socket it will be
+  * mapped to a singlle NEXTHOP_TYPE_IPV4_IFINDEX_OL RIB nexthop structure.
+  *
   * If ZAPI_MESSAGE_DISTANCE is set, the distance value is written as a 1
   * byte value.
   * 
@@ -509,8 +524,25 @@ zapi_ipv4_route (u_char cmd, struct zclient *zclient, 
struct prefix_ipv4 *p,
   stream_write (s, (u_char *) & p->prefix, psize);
 
   /* Nexthop, ifindex, distance and metric information. */
-  if (CHECK_FLAG (api->message, ZAPI_MESSAGE_NEXTHOP))
+  /* ZAPI_MESSAGE_ONLINK implies interleaving */
+  if (CHECK_FLAG (api->message, ZAPI_MESSAGE_ONLINK))
     {
+      /* ZAPI_MESSAGE_NEXTHOP is required for proper receiving */
+      assert (CHECK_FLAG (api->message, ZAPI_MESSAGE_NEXTHOP));
+      /* 64-bit data units, interleaved between nexthop[] and ifindex[] */
+      assert (api->nexthop_num == api->ifindex_num);
+      stream_putc (s, api->nexthop_num * 2);
+      for (i = 0; i < api->nexthop_num; i++)
+        {
+          stream_putc (s, ZEBRA_NEXTHOP_IPV4_ONLINK);
+          stream_put_in_addr (s, api->nexthop[i]);
+          stream_putc (s, ZEBRA_NEXTHOP_IFINDEX);
+          stream_putl (s, api->ifindex[i]);
+        }
+    }
+  else if (CHECK_FLAG (api->message, ZAPI_MESSAGE_NEXTHOP))
+     {
+      /* traditional 32-bit data units */
       if (CHECK_FLAG (api->flags, ZEBRA_FLAG_BLACKHOLE))
         {
           stream_putc (s, 1);
diff --git a/lib/zclient.h b/lib/zclient.h
index 19b4f0e..9f90807 100644
--- a/lib/zclient.h
+++ b/lib/zclient.h
@@ -93,6 +93,7 @@ struct zclient
 #define ZAPI_MESSAGE_IFINDEX  0x02
 #define ZAPI_MESSAGE_DISTANCE 0x04
 #define ZAPI_MESSAGE_METRIC   0x08
+#define ZAPI_MESSAGE_ONLINK   0x20
 
 /* Zserv protocol message header */
 struct zserv_header
diff --git a/lib/zebra.h b/lib/zebra.h
index 8586437..0bc5309 100644
--- a/lib/zebra.h
+++ b/lib/zebra.h
@@ -476,6 +476,7 @@ extern const char *zserv_command_string (unsigned int 
command);
 #define ZEBRA_NEXTHOP_IPV6_IFINDEX       7
 #define ZEBRA_NEXTHOP_IPV6_IFNAME        8
 #define ZEBRA_NEXTHOP_BLACKHOLE          9
+#define ZEBRA_NEXTHOP_IPV4_ONLINK       10
 
 #ifndef INADDR_LOOPBACK
 #define        INADDR_LOOPBACK 0x7f000001      /* Internet address 127.0.0.1.  
*/
diff --git a/zebra/rib.h b/zebra/rib.h
index 8328f23..28e9855 100644
--- a/zebra/rib.h
+++ b/zebra/rib.h
@@ -465,6 +465,8 @@ extern struct nexthop *nexthop_ifname_add (struct rib *, 
char *);
 extern struct nexthop *nexthop_blackhole_add (struct rib *);
 extern struct nexthop *nexthop_ipv4_add (struct rib *, struct in_addr *,
                                         struct in_addr *);
+extern struct nexthop * nexthop_ipv4_ifindex_ol_add (struct rib *, const 
struct in_addr *,
+                                                    const struct in_addr *, 
const unsigned);
 extern struct nexthop *nexthop_ipv4_ifindex_add (struct rib *,
                                                  struct in_addr *,
                                                  struct in_addr *,
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index 084af38..e9f8a9c 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -259,6 +259,22 @@ nexthop_ipv4_ifindex_add (struct rib *rib, struct in_addr 
*ipv4,
   return nexthop;
 }
 
+struct nexthop *
+nexthop_ipv4_ifindex_ol_add (struct rib *rib, const struct in_addr *ipv4,
+                             const struct in_addr *src, const unsigned int 
ifindex)
+{
+  struct nexthop *nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
+
+  nexthop->type = NEXTHOP_TYPE_IPV4_IFINDEX;
+  IPV4_ADDR_COPY (&nexthop->gate.ipv4, ipv4);
+  if (src)
+    IPV4_ADDR_COPY (&nexthop->src.ipv4, src);
+  nexthop->ifindex = ifindex;
+  SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK);
+  nexthop_add (rib, nexthop);
+  return nexthop;
+}
+
 #ifdef HAVE_IPV6
 struct nexthop *
 nexthop_ipv6_add (struct rib *rib, struct in6_addr *ipv6)
@@ -352,6 +368,7 @@ nexthop_active_ipv4 (struct rib *rib, struct nexthop 
*nexthop, int set,
   int resolved;
   struct nexthop *newhop;
   struct nexthop *resolved_hop;
+  struct interface *ifp;
 
   if (nexthop->type == NEXTHOP_TYPE_IPV4)
     nexthop->ifindex = 0;
@@ -363,6 +380,19 @@ nexthop_active_ipv4 (struct rib *rib, struct nexthop 
*nexthop, int set,
       nexthop->resolved = NULL;
     }
 
+  /* onlink flag is an indication that we need to only check that
+   * the link is up, we won't find the GW address in the routing
+   * table.
+   */
+  if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK))
+    {
+      ifp = if_lookup_by_index (nexthop->ifindex);
+      if (ifp && if_is_operative(ifp))
+       return 1;
+      else
+       return 0;
+    }
+
   /* Make lookup prefix. */
   memset (&p, 0, sizeof (struct prefix_ipv4));
   p.family = AF_INET;
diff --git a/zebra/zserv.c b/zebra/zserv.c
index 8ca5615..bb41840 100644
--- a/zebra/zserv.c
+++ b/zebra/zserv.c
@@ -891,6 +891,11 @@ zread_ipv4_add (struct zserv *client, u_short length, 
vrf_id_t vrf_id)
             case ZEBRA_NEXTHOP_BLACKHOLE:
               nexthop_blackhole_add (rib);
               break;
+           case ZEBRA_NEXTHOP_IPV4_ONLINK:
+             nexthop.s_addr = stream_get_ipv4 (s);
+             ifindex = stream_getl (s);
+             nexthop_ipv4_ifindex_ol_add (rib, &nexthop, NULL, ifindex);
+             break;
             }
        }
     }
-- 
1.7.10.4


_______________________________________________
Quagga-dev mailing list
[email protected]
https://lists.quagga.net/mailman/listinfo/quagga-dev

Reply via email to