]> git.puffer.fish Git - mirror/frr.git/commitdiff
zebra: add ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB
authorEverton Marques <everton.marques@gmail.com>
Tue, 1 Jul 2014 18:15:52 +0000 (15:15 -0300)
committerDonald Sharp <sharpd@cumulusnetwroks.com>
Thu, 26 May 2016 00:38:31 +0000 (20:38 -0400)
This adds a new zapi call "ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB" performing a
Multicast RPF lookup for a given source.  Details of the lookup
behaviour are left to the zebra side of things.

Note: this is non-reactive, as in, only delivers a snapshot of the state
at a particular point in time.  There's no push notification of changes
happening to the RIB.

This combines the following 3 original patches:
- zebra: add zsend_ipv4_nexthop_lookup_mrib()
- zserv: Query mrib (SAFI_MULTICAST).
- zebra: Cleanups to zebra_rib.

Cc: Everton Marques <everton.marques@gmail.com>
Cc: Balaji G <balajig81@gmail.com>
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
lib/zebra.h
zebra/zserv.c

index 38a1889e722a0dc874f3da3ff3e57186b86ccfa5..8ba105de3747cb8c7ed3b613002c42058b4e80a6 100644 (file)
@@ -455,7 +455,8 @@ struct in_pktinfo
 #define ZEBRA_BFD_CLIENT_REGISTER         46
 #define ZEBRA_INTERFACE_ENABLE_RADV       47
 #define ZEBRA_INTERFACE_DISABLE_RADV      48
-#define ZEBRA_MESSAGE_MAX                 49
+#define ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB    49
+#define ZEBRA_MESSAGE_MAX                 50
 
 /* Marker value used in new Zserv, in the byte location corresponding
  * the command value in the old zserv header. To allow old and new
index 6370508da0f886cf42dcfd481722cf8b127c4cb6..eb616b0405f838f12d889716cb529583e66f6a1f 100644 (file)
@@ -959,6 +959,88 @@ zserv_rnh_unregister (struct zserv *client, int sock, u_short length,
   return 0;
 }
 
+/*
+  Modified version of zsend_ipv4_nexthop_lookup():
+  Query unicast rib if nexthop is not found on mrib.
+  Returns both route metric and protocol distance.
+*/
+static int
+zsend_ipv4_nexthop_lookup_mrib (struct zserv *client, struct in_addr addr, struct zebra_vrf *zvrf)
+{
+  struct stream *s;
+  struct rib *rib;
+  unsigned long nump;
+  u_char num;
+  struct nexthop *nexthop;
+
+  /* Lookup nexthop. */
+  rib = rib_match_ipv4 (addr, SAFI_MULTICAST, zvrf->vrf_id);
+
+  if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV)
+    zlog_debug("%s: %s mrib entry found.", __func__, rib ? "Matching" : "No matching");
+
+  if (!rib) {
+    /* Retry lookup with unicast rib */
+    rib = rib_match_ipv4 (addr, SAFI_UNICAST, zvrf->vrf_id);
+    if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV)
+      zlog_debug("%s: %s rib entry found.", __func__, rib ? "Matching" : "No matching");
+  }
+
+  /* Get output stream. */
+  s = client->obuf;
+  stream_reset (s);
+
+  /* Fill in result. */
+  zserv_create_header (s, ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB, zvrf->vrf_id);
+  stream_put_in_addr (s, &addr);
+
+  if (rib)
+    {
+      stream_putc (s, rib->distance);
+      stream_putl (s, rib->metric);
+      num = 0;
+      nump = stream_get_endp(s); /* remember position for nexthop_num */
+      stream_putc (s, 0);        /* reserve room for nexthop_num */
+      /* Only non-recursive routes are elegible to resolve the nexthop we
+       * are looking up. Therefore, we will just iterate over the top
+       * chain of nexthops. */
+      for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
+       if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
+         {
+           stream_putc (s, nexthop->type);
+           switch (nexthop->type)
+             {
+             case ZEBRA_NEXTHOP_IPV4:
+               stream_put_in_addr (s, &nexthop->gate.ipv4);
+               break;
+             case ZEBRA_NEXTHOP_IPV4_IFINDEX:
+               stream_put_in_addr (s, &nexthop->gate.ipv4);
+               stream_putl (s, nexthop->ifindex);
+               break;
+             case ZEBRA_NEXTHOP_IFINDEX:
+               stream_putl (s, nexthop->ifindex);
+               break;
+             default:
+               /* do nothing */
+               break;
+             }
+           num++;
+         }
+    
+      stream_putc_at (s, nump, num); /* store nexthop_num */
+    }
+  else
+    {
+      stream_putc (s, 0); /* distance */
+      stream_putl (s, 0); /* metric */
+      stream_putc (s, 0); /* nexthop_num */
+    }
+
+  stream_putw_at (s, 0, stream_get_endp (s));
+  
+  return zebra_server_send_message(client);
+}
+
 static int
 zsend_ipv4_import_lookup (struct zserv *client, struct prefix_ipv4 *p,
     vrf_id_t vrf_id)
@@ -1312,6 +1394,16 @@ zread_ipv4_nexthop_lookup (struct zserv *client, u_short length,
   return zsend_ipv4_nexthop_lookup (client, addr, zvrf->vrf_id);
 }
 
+/* MRIB Nexthop lookup for IPv4. */
+static int
+zread_ipv4_nexthop_lookup_mrib (struct zserv *client, u_short length, struct zebra_vrf *zvrf)
+{
+  struct in_addr addr;
+
+  addr.s_addr = stream_get_ipv4 (client->ibuf);
+  return zsend_ipv4_nexthop_lookup_mrib (client, addr, zvrf);
+}
+
 /* Nexthop lookup for IPv4. */
 static int
 zread_ipv4_import_lookup (struct zserv *client, u_short length,
@@ -1990,6 +2082,9 @@ zebra_client_read (struct thread *thread)
     case ZEBRA_IPV4_NEXTHOP_LOOKUP:
       zread_ipv4_nexthop_lookup (client, length, zvrf);
       break;
+    case ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB:
+      zread_ipv4_nexthop_lookup_mrib (client, length, zvrf);
+      break;
     case ZEBRA_IPV6_NEXTHOP_LOOKUP:
       zread_ipv6_nexthop_lookup (client, length, zvrf);
       break;