[quagga-dev 10829] [PATCH 2/4] zebra: quagga-re-onlink-support.patch

Dinesh G Dutt ddutt at cumulusnetworks.com
Thu Oct 24 05:06:43 BST 2013


Zebra: Use onlink commit from quagga-re branch for ospf unnumbered interface.

onlink commit from Quagga-RE branch

Signed-off-by: James Li <jli at cumulusnetworks.com>
---
 lib/zclient.c      |   34 +++++++++++++++++++++++++++++++++-
 lib/zclient.h      |    1 +
 lib/zebra.h        |    1 +
 zebra/rib.h        |    6 ++++++
 zebra/rt_netlink.c |    8 +++++++-
 zebra/zebra_rib.c  |   16 ++++++++++++++++
 zebra/zebra_vty.c  |    8 ++++++++
 zebra/zserv.c      |   16 +++++++++++++++-
 8 files changed, 87 insertions(+), 3 deletions(-)

diff --git a/lib/zclient.c b/lib/zclient.c
index 9d2b561..856fea5 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -450,6 +450,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.
   * 
@@ -484,8 +499,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 a660bbf..a082655 100644
--- a/lib/zclient.h
+++ b/lib/zclient.h
@@ -89,6 +89,7 @@ struct zclient
 #define ZAPI_MESSAGE_IFINDEX  0x02
 #define ZAPI_MESSAGE_DISTANCE 0x04
 #define ZAPI_MESSAGE_METRIC   0x08
+#define ZAPI_MESSAGE_ONLINK   0x10
 
 /* Zserv protocol message header */
 struct zserv_header
diff --git a/lib/zebra.h b/lib/zebra.h
index 780e12e..7583a03 100644
--- a/lib/zebra.h
+++ b/lib/zebra.h
@@ -488,6 +488,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 50628bb..b6a4ac2 100644
--- a/zebra/rib.h
+++ b/zebra/rib.h
@@ -235,6 +235,10 @@ enum nexthop_types_t
   NEXTHOP_TYPE_IPV6_IFINDEX,     /* IPv6 nexthop with ifindex.  */
   NEXTHOP_TYPE_IPV6_IFNAME,      /* IPv6 nexthop with ifname.  */
   NEXTHOP_TYPE_BLACKHOLE,        /* Null0 nexthop.  */
+  NEXTHOP_TYPE_IPV4_IFINDEX_OL,
+  /* IPv4 nexthop with ifindex, which does not require the gate address
+   * to belong to a connected network of the given interface. Used for
+   * mesh routing. */
 };
 
 /* Nexthop structure. */
@@ -329,6 +333,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/rt_netlink.c b/zebra/rt_netlink.c
index f41b2f2..95fb217 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -1570,6 +1570,8 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib,
                 }
               else
                 {
+                  if (nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX_OL)
+                    SET_FLAG (req.r.rtm_flags, RTNH_F_ONLINK);
                   if (IS_ZEBRA_DEBUG_KERNEL)
                     {
                       zlog_debug
@@ -1585,6 +1587,7 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib,
                     }
 
                   if (nexthop->type == NEXTHOP_TYPE_IPV4
+                      || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX_OL
                       || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
 		    {
 		      addattr_l (&req.n, sizeof req, RTA_GATEWAY,
@@ -1616,6 +1619,7 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib,
 #endif /* HAVE_IPV6 */
                   if (nexthop->type == NEXTHOP_TYPE_IFINDEX
                       || nexthop->type == NEXTHOP_TYPE_IFNAME
+                      || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX_OL
                       || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
 		    {
 		      addattr32 (&req.n, sizeof req, RTA_OIF, nexthop->ifindex);
@@ -1676,7 +1680,7 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib,
               nexthop_num++;
 
               rtnh->rtnh_len = sizeof (*rtnh);
-              rtnh->rtnh_flags = 0;
+              rtnh->rtnh_flags = nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX_OL ? RTNH_F_ONLINK : 0;
               rtnh->rtnh_hops = 0;
               rta->rta_len += rtnh->rtnh_len;
 
@@ -1770,6 +1774,7 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib,
 			 p->prefixlen, nexthop_type_to_str (nexthop->type));
                     }
                   if (nexthop->type == NEXTHOP_TYPE_IPV4
+                      || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX_OL
                       || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
                     {
 		      rta_addattr_l (rta, NL_PKT_BUF_SIZE, RTA_GATEWAY,
@@ -1802,6 +1807,7 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib,
 #endif /* HAVE_IPV6 */
                   /* ifindex */
                   if (nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX
+		      || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX_OL
 		      || nexthop->type == NEXTHOP_TYPE_IFINDEX
                       || nexthop->type == NEXTHOP_TYPE_IFNAME)
                     {
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index 4a71a4d..2ea4d61 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -303,6 +303,21 @@ 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_OL;
+  IPV4_ADDR_COPY (&nexthop->gate.ipv4, ipv4);
+  if (src)
+    IPV4_ADDR_COPY (&nexthop->src.ipv4, src);
+  nexthop->ifindex = ifindex;
+  nexthop_add (rib, nexthop);
+  return nexthop;
+}
+
 #ifdef HAVE_IPV6
 struct nexthop *
 nexthop_ipv6_add (struct rib *rib, struct in6_addr *ipv6)
@@ -842,6 +857,7 @@ nexthop_active_check (struct route_node *rn, struct rib *rib,
   switch (nexthop->type)
     {
     case NEXTHOP_TYPE_IFINDEX:
+    case NEXTHOP_TYPE_IPV4_IFINDEX_OL:
       ifp = if_lookup_by_index (nexthop->ifindex);
       if (ifp && if_is_operative(ifp))
 	SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c
index 791ce65..5f1fb2e 100644
--- a/zebra/zebra_vty.c
+++ b/zebra/zebra_vty.c
@@ -593,6 +593,7 @@ vty_show_ip_route_detail (struct vty *vty, struct route_node *rn)
 	    {
 	    case NEXTHOP_TYPE_IPV4:
 	    case NEXTHOP_TYPE_IPV4_IFINDEX:
+	    case NEXTHOP_TYPE_IPV4_IFINDEX_OL:
 	      vty_out (vty, " %s", inet_ntoa (nexthop->gate.ipv4));
 	      if (nexthop->ifindex)
 		vty_out (vty, ", via %s", ifindex2ifname (nexthop->ifindex));
@@ -612,6 +613,8 @@ vty_show_ip_route_detail (struct vty *vty, struct route_node *rn)
 	    }
 	  if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
 	    vty_out (vty, " inactive");
+	  if (nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX_OL)
+	    vty_out (vty, " onlink");
 
 	  if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
 	    {
@@ -641,6 +644,7 @@ vty_show_ip_route_detail (struct vty *vty, struct route_node *rn)
             case NEXTHOP_TYPE_IPV4:
             case NEXTHOP_TYPE_IPV4_IFINDEX:
             case NEXTHOP_TYPE_IPV4_IFNAME:
+            case NEXTHOP_TYPE_IPV4_IFINDEX_OL:
               if (nexthop->src.ipv4.s_addr)
                 {
 		  if (inet_ntop(AF_INET, &nexthop->src.ipv4, addrstr,
@@ -707,6 +711,7 @@ vty_show_ip_route (struct vty *vty, struct route_node *rn, struct rib *rib)
 	{
 	case NEXTHOP_TYPE_IPV4:
 	case NEXTHOP_TYPE_IPV4_IFINDEX:
+	case NEXTHOP_TYPE_IPV4_IFINDEX_OL:
 	  vty_out (vty, " via %s", inet_ntoa (nexthop->gate.ipv4));
 	  if (nexthop->ifindex)
 	    vty_out (vty, ", %s", ifindex2ifname (nexthop->ifindex));
@@ -754,6 +759,7 @@ vty_show_ip_route (struct vty *vty, struct route_node *rn, struct rib *rib)
           case NEXTHOP_TYPE_IPV4:
           case NEXTHOP_TYPE_IPV4_IFINDEX:
           case NEXTHOP_TYPE_IPV4_IFNAME:
+          case NEXTHOP_TYPE_IPV4_IFINDEX_OL:
             if (nexthop->src.ipv4.s_addr)
               {
 		if (inet_ntop(AF_INET, &nexthop->src.ipv4, buf, sizeof buf))
@@ -779,6 +785,8 @@ vty_show_ip_route (struct vty *vty, struct route_node *rn, struct rib *rib)
                vty_out (vty, ", bh");
       if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_REJECT))
                vty_out (vty, ", rej");
+      if (nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX_OL)
+               vty_out (vty, ", onlink");
 
       if (rib->type == ZEBRA_ROUTE_RIP
 	  || rib->type == ZEBRA_ROUTE_OSPF
diff --git a/zebra/zserv.c b/zebra/zserv.c
index e850495..330871a 100644
--- a/zebra/zserv.c
+++ b/zebra/zserv.c
@@ -745,6 +745,7 @@ zread_ipv4_add (struct zserv *client, u_short length)
   unsigned int ifindex;
   u_char ifname_len;
   safi_t safi;	
+  u_char onlink = 0;
 
 
   /* Get input stream.  */
@@ -779,27 +780,40 @@ zread_ipv4_add (struct zserv *client, u_short length)
 	    {
 	    case ZEBRA_NEXTHOP_IFINDEX:
 	      ifindex = stream_getl (s);
-	      nexthop_ifindex_add (rib, ifindex);
+              if (onlink)
+                nexthop_ipv4_ifindex_ol_add (rib, &nexthop, NULL, ifindex);
+              else
+                nexthop_ifindex_add (rib, ifindex);
+              onlink = 0;
 	      break;
 	    case ZEBRA_NEXTHOP_IFNAME:
 	      ifname_len = stream_getc (s);
 	      stream_forward_getp (s, ifname_len);
+              onlink = 0;
 	      break;
 	    case ZEBRA_NEXTHOP_IPV4:
 	      nexthop.s_addr = stream_get_ipv4 (s);
 	      nexthop_ipv4_add (rib, &nexthop, NULL);
+              onlink = 0;
 	      break;
 	    case ZEBRA_NEXTHOP_IPV4_IFINDEX:
 	      nexthop.s_addr = stream_get_ipv4 (s);
 	      ifindex = stream_getl (s);
 	      nexthop_ipv4_ifindex_add (rib, &nexthop, NULL, ifindex);
+              onlink = 0;
 	      break;
 	    case ZEBRA_NEXTHOP_IPV6:
 	      stream_forward_getp (s, IPV6_MAX_BYTELEN);
+              onlink = 0;
 	      break;
             case ZEBRA_NEXTHOP_BLACKHOLE:
               nexthop_blackhole_add (rib);
+              onlink = 0;
               break;
+	    case ZEBRA_NEXTHOP_IPV4_ONLINK:
+	      nexthop.s_addr = stream_get_ipv4 (s);
+	      onlink = 1;
+	      break;
             }
 	}
     }





More information about the Quagga-dev mailing list