]> git.puffer.fish Git - mirror/frr.git/commitdiff
lib, pimd, zebra: Allow pimd to ask the kernel about mroute info
authorDonald Sharp <sharpd@cumulusnetworks.com>
Thu, 11 Aug 2016 00:04:20 +0000 (00:04 +0000)
committerDonald Sharp <sharpd@cumulusnetworks.com>
Thu, 22 Dec 2016 01:26:06 +0000 (20:26 -0500)
When we need to lookup the mroute info for a route.  Allow
pimd to ask the kernel.

Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
14 files changed:
lib/log.c
lib/zebra.h
pimd/pim_mroute.c
pimd/pim_oil.h
pimd/pim_upstream.c
pimd/pim_zlookup.c
pimd/pim_zlookup.h
zebra/Makefile.am
zebra/rt_netlink.c
zebra/rt_netlink.h
zebra/zebra_fpm_netlink.c
zebra/zebra_mroute.c [new file with mode: 0644]
zebra/zebra_mroute.h [new file with mode: 0644]
zebra/zserv.c

index f9877300b44a5c8c85471ed43e25967da4ef39b3..67f335c6ae0865b56b5d1b253d6caaee3e9360cd 100644 (file)
--- a/lib/log.c
+++ b/lib/log.c
@@ -989,6 +989,7 @@ static const struct zebra_desc_table command_types[] = {
   DESC_ENTRY   (ZEBRA_IPV4_NEXTHOP_DELETE),
   DESC_ENTRY   (ZEBRA_IPV6_NEXTHOP_ADD),
   DESC_ENTRY   (ZEBRA_IPV6_NEXTHOP_DELETE),
+  DESC_ENTRY    (ZEBRA_IPMR_ROUTE_STATS),
 };
 #undef DESC_ENTRY
 
index 1fc643d597eb5ecc7642d7f52c0a4775960ea4c3..f344867697465b84c59f08955758f253a2e46d60 100644 (file)
@@ -405,6 +405,7 @@ typedef enum {
   ZEBRA_IPV4_NEXTHOP_DELETE,
   ZEBRA_IPV6_NEXTHOP_ADD,
   ZEBRA_IPV6_NEXTHOP_DELETE,
+  ZEBRA_IPMR_ROUTE_STATS,
 } zebra_message_types_t;
 
 /* Marker value used in new Zserv, in the byte location corresponding
index 8426a4add53c07de55c152237aa87bfa7b6fcfb8..2fc733e97f8fdaf0d37f661245a2efb807c2d934 100644 (file)
@@ -37,6 +37,7 @@
 #include "pim_oil.h"
 #include "pim_register.h"
 #include "pim_ifchannel.h"
+#include "pim_zlookup.h"
 
 /* GLOBAL VARS */
 extern struct zebra_privs_t pimd_privs;
@@ -740,6 +741,7 @@ pim_mroute_update_counters (struct channel_oil *c_oil)
   c_oil->cc.oldpktcnt = c_oil->cc.pktcnt;
   c_oil->cc.oldbytecnt = c_oil->cc.bytecnt;
   c_oil->cc.oldwrong_if = c_oil->cc.wrong_if;
+  c_oil->cc.oldlastused = c_oil->cc.lastused;
 
   if (ioctl (qpim_mroute_socket_fd, SIOCGETSGCNT, &sgreq))
     {
@@ -758,6 +760,7 @@ pim_mroute_update_counters (struct channel_oil *c_oil)
       return;
     }
 
+  pim_zlookup_sg_statistics (c_oil);
   c_oil->cc.pktcnt = sgreq.pktcnt;
   c_oil->cc.bytecnt = sgreq.bytecnt;
   c_oil->cc.wrong_if = sgreq.wrong_if;
index 6b55bdc4d50cccf48e6f0dda4fec72dde1884798..1bbd232e4d75a98f0163cde3334ffe363e334d36 100644 (file)
@@ -52,6 +52,8 @@
 
 struct channel_counts
 {
+  unsigned long long lastused;
+  unsigned long long oldlastused;
   unsigned long pktcnt;
   unsigned long oldpktcnt;
   unsigned long bytecnt;
index 39f609da286f09913aeb87afce17c1307c3b4330..bb322a7cdd2fca58766759fd12d243cdd7a88bab 100644 (file)
@@ -822,7 +822,8 @@ pim_upstream_keep_alive_timer (struct thread *t)
 
   pim_mroute_update_counters (up->channel_oil);
 
-  if (up->channel_oil->cc.oldpktcnt >= up->channel_oil->cc.pktcnt)
+  if ((up->channel_oil->cc.oldpktcnt >= up->channel_oil->cc.pktcnt) &&
+      (up->channel_oil->cc.oldlastused >= up->channel_oil->cc.lastused))
     {
       pim_mroute_del (up->channel_oil);
       pim_upstream_delete (up);
index ceac1eff7a077121a16d6e024beb31a7b4bbe79e..6cf6a6b2f7e83ccbc56a03de77a3fb9d4079b12c 100644 (file)
 #include "stream.h"
 #include "network.h"
 #include "thread.h"
+#include "prefix.h"
 #include "vty.h"
 
 #include "pimd.h"
+#include "pim_iface.h"
 #include "pim_pim.h"
 #include "pim_str.h"
+#include "pim_oil.h"
 #include "pim_zlookup.h"
 
 extern int zclient_debug;
@@ -451,3 +454,76 @@ pim_zlookup_show_ip_multicast (struct vty *vty)
     vty_out(vty, "<null zclient>%s", VTY_NEWLINE);
   }
 }
+
+int
+pim_zlookup_sg_statistics (struct channel_oil *c_oil)
+{
+  struct stream *s = zlookup->obuf;
+  uint16_t command = 0;
+  unsigned long long lastused;
+  struct prefix_sg sg;
+  int count = 0;
+  int ret;
+  struct interface *ifp = pim_if_find_by_vif_index (c_oil->oil.mfcc_parent);
+
+  if (PIM_DEBUG_ZEBRA)
+    zlog_debug ("Sending Request for New Channel Oil Information");
+
+  stream_reset (s);
+  zclient_create_header (s, ZEBRA_IPMR_ROUTE_STATS, VRF_DEFAULT);
+  stream_put_in_addr (s, &c_oil->oil.mfcc_origin);
+  stream_put_in_addr (s, &c_oil->oil.mfcc_mcastgrp);
+  stream_putl (s,  ifp->ifindex);
+  stream_putw_at(s, 0, stream_get_endp(s));
+
+  count = stream_get_endp (s);
+  ret = writen (zlookup->sock, s->data, count);
+  if (ret <= 0)
+    {
+      zlog_err("%s %s: writen() failure writing to zclient lookup socket",
+               __FILE__, __PRETTY_FUNCTION__);
+      return -1;
+    }
+
+  s = zlookup->ibuf;
+
+  while (command != ZEBRA_IPMR_ROUTE_STATS)
+    {
+      int err;
+      uint16_t length = 0;
+      vrf_id_t vrf_id;
+      u_char marker;
+      u_char version;
+
+      stream_reset (s);
+      err = zclient_read_header (s, zlookup->sock, &length, &marker, &version,
+                                &vrf_id, &command);
+      if (err < 0)
+        {
+          zlog_err ("%s %s: zclient_read_header() failed",
+                 __FILE__, __PRETTY_FUNCTION__);
+        zclient_lookup_failed(zlookup);
+        return -1;
+        }
+    }
+
+  sg.src.s_addr = stream_get_ipv4 (s);
+  sg.grp.s_addr = stream_get_ipv4 (s);
+  if (sg.src.s_addr != c_oil->oil.mfcc_origin.s_addr ||
+      sg.grp.s_addr != c_oil->oil.mfcc_mcastgrp.s_addr)
+    {
+       zlog_err ("%s: Received wrong %s information",
+                __PRETTY_FUNCTION__, pim_str_sg_dump (&sg));
+       zclient_lookup_failed (zlookup);
+       return -3;
+    }
+
+  stream_get (&lastused, s, sizeof (lastused));
+
+  zlog_debug ("Received %lld for %s", lastused, pim_str_sg_dump (&sg));
+
+  c_oil->cc.lastused = lastused;
+
+  return 0;
+
+}
index d92eb089b15c13ffc69ede8e3beb6fc38ad49910..4dea5750c5673a7223c6d0507c08262402c321e4 100644 (file)
@@ -44,4 +44,5 @@ int zclient_lookup_nexthop(struct pim_zlookup_nexthop nexthop_tab[],
 
 void pim_zlookup_show_ip_multicast (struct vty *vty);
 
+int pim_zlookup_sg_statistics (struct channel_oil *c_oil);
 #endif /* PIM_ZLOOKUP_H */
index 65927262f22b3119f92ebd7e5b0ea788e8118729..428090d4887c53e47f98e36b50bc65f3273c4569 100644 (file)
@@ -44,7 +44,7 @@ zebra_SOURCES = \
        irdp_main.c irdp_interface.c irdp_packet.c router-id.c zebra_fpm.c \
        $(othersrc) zebra_ptm.c zebra_rnh.c zebra_ptm_redistribute.c \
        zebra_ns.c zebra_vrf.c zebra_static.c zebra_mpls.c zebra_mpls_vty.c \
-       $(protobuf_srcs) \
+       $(protobuf_srcs) zebra_mroute.c \
        $(dev_srcs)
 
 testzebra_SOURCES = test_main.c zebra_rib.c interface.c connected.c debug.c \
@@ -60,7 +60,7 @@ noinst_HEADERS = \
        rt_netlink.h zebra_fpm.h zebra_fpm_private.h zebra_rnh.h \
        zebra_ptm_redistribute.h zebra_ptm.h zebra_routemap.h \
        zebra_ns.h zebra_vrf.h ioctl_solaris.h zebra_static.h zebra_mpls.h \
-       kernel_netlink.h if_netlink.h
+       kernel_netlink.h if_netlink.h zebra_mroute.h
 
 zebra_LDADD = $(otherobj) ../lib/libzebra.la $(LIBCAP) $(Q_FPM_PB_CLIENT_LDOPTS)
 
index ff907bb8784f05077976bd27192dd59a2affe9ac..5dc9a10e297368e0337242bc6cc835d99b6831f0 100644 (file)
@@ -55,6 +55,8 @@
 #include "zebra/zebra_mpls.h"
 #include "zebra/kernel_netlink.h"
 #include "zebra/rt_netlink.h"
+#include "zebra/zebra_mroute.h"
+
 
 /* TODO - Temporary definitions, need to refine. */
 #ifndef AF_MPLS
@@ -516,6 +518,8 @@ netlink_route_change_read_unicast (struct sockaddr_nl *snl, struct nlmsghdr *h,
   return 0;
 }
 
+static struct mcast_route_data *mroute = NULL;
+
 static int
 netlink_route_change_read_multicast (struct sockaddr_nl *snl, struct nlmsghdr *h,
                                     ns_id_t ns_id)
@@ -524,7 +528,8 @@ netlink_route_change_read_multicast (struct sockaddr_nl *snl, struct nlmsghdr *h
   unsigned long long lastused = 0;
   struct rtmsg *rtm;
   struct rtattr *tb[RTA_MAX + 1];
-  struct prefix_sg sg;
+  struct mcast_route_data *m;
+  struct mcast_route_data mr;
   int iif = 0;
   int count;
   int oif[256];
@@ -532,10 +537,13 @@ netlink_route_change_read_multicast (struct sockaddr_nl *snl, struct nlmsghdr *h
   char sbuf[40];
   char gbuf[40];
   char oif_list[256] = "\0";
-  memset (&sg, 0, sizeof (sg));
-  sg.family = IANA_AFI_IPMR;
   vrf_id_t vrf = ns_id;
 
+  if (mroute)
+    m = mroute;
+  else
+    m = &mr;
+
   rtm = NLMSG_DATA (h);
 
   len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct rtmsg));
@@ -547,13 +555,13 @@ netlink_route_change_read_multicast (struct sockaddr_nl *snl, struct nlmsghdr *h
     iif = *(int *)RTA_DATA (tb[RTA_IIF]);
 
   if (tb[RTA_SRC])
-    sg.src = *(struct in_addr *)RTA_DATA (tb[RTA_SRC]);
+    m->sg.src = *(struct in_addr *)RTA_DATA (tb[RTA_SRC]);
 
   if (tb[RTA_DST])
-    sg.grp = *(struct in_addr *)RTA_DATA (tb[RTA_DST]);
+    m->sg.grp = *(struct in_addr *)RTA_DATA (tb[RTA_DST]);
 
   if (tb[RTA_EXPIRES])
-    lastused = *(unsigned long long *)RTA_DATA (tb[RTA_EXPIRES]);
+    m->lastused = *(unsigned long long *)RTA_DATA (tb[RTA_EXPIRES]);
 
   if (tb[RTA_MULTIPATH])
     {
@@ -576,8 +584,8 @@ netlink_route_change_read_multicast (struct sockaddr_nl *snl, struct nlmsghdr *h
 
   if (IS_ZEBRA_DEBUG_KERNEL)
     {
-      strcpy (sbuf, inet_ntoa (sg.src));
-      strcpy (gbuf, inet_ntoa (sg.grp));
+      strcpy (sbuf, inet_ntoa (m->sg.src));
+      strcpy (gbuf, inet_ntoa (m->sg.grp));
       for (count = 0; count < oif_count; count++)
        {
          struct interface *ifp = if_lookup_by_index_vrf (oif[count], vrf);
@@ -1507,6 +1515,39 @@ skip:
   return netlink_talk (netlink_talk_filter, &req.n, &zns->netlink_cmd, zns);
 }
 
+int
+netlink_get_ipmr_sg_stats (void *in)
+{
+  int suc = 0;
+  struct mcast_route_data *mr = (struct mcast_route_data *)in;
+  struct {
+      struct nlmsghdr         n;
+      struct ndmsg            ndm;
+      char                    buf[256];
+  } req;
+
+  mroute = mr;
+  struct zebra_ns *zns = zebra_ns_lookup (NS_DEFAULT);
+
+  memset(&req.n, 0, sizeof(req.n));
+  memset(&req.ndm, 0, sizeof(req.ndm));
+
+  req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
+  req.n.nlmsg_flags = NLM_F_REQUEST;
+  req.ndm.ndm_family = AF_INET;
+  req.n.nlmsg_type = RTM_GETROUTE;
+
+  addattr_l (&req.n, sizeof (req), RTA_IIF, &mroute->ifindex, 4);
+  addattr_l (&req.n, sizeof (req), RTA_OIF, &mroute->ifindex, 4);
+  addattr_l (&req.n, sizeof (req), RTA_SRC, &mroute->sg.src.s_addr, 4);
+  addattr_l (&req.n, sizeof (req), RTA_DST, &mroute->sg.grp.s_addr, 4);
+
+  suc = netlink_talk (netlink_route_change_read_multicast, &req.n, &zns->netlink_cmd, zns);
+
+  mroute = NULL;
+  return suc;
+}
+
 int
 kernel_route_rib (struct prefix *p, struct rib *old, struct rib *new)
 {
index 7183525fba6ec8c48052afb6893f78833233cdbb..6774b7dd3d0669d3e94a1cc0b3f8223b5c04015e 100644 (file)
@@ -37,6 +37,7 @@ extern int netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h,
                                  ns_id_t ns_id);
 extern int netlink_route_read (struct zebra_ns *zns);
 
+extern int netlink_get_ipmr_sg_stats (void *mroute);
 #endif /* HAVE_NETLINK */
 
 #endif /* _ZEBRA_RT_NETLINK_H */
index a09008b396ea6adb490bb1b2997207ccb4cf5e16..5dd08ca782d6d6953163c4110f6092808c602ff2 100644 (file)
@@ -28,6 +28,7 @@
 #include "log.h"
 #include "rib.h"
 #include "vty.h"
+#include "prefix.h"
 
 #include "zebra/zserv.h"
 #include "zebra/zebra_ns.h"
diff --git a/zebra/zebra_mroute.c b/zebra/zebra_mroute.c
new file mode 100644 (file)
index 0000000..8dddb4e
--- /dev/null
@@ -0,0 +1,66 @@
+/* zebra_mroute code
+ * Copyright (C) 2016 Cumulus Networks, Inc.
+ * Donald Sharp
+ *
+ * This file is part of Quagga
+ *
+ * Quagga 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, or (at your option) any
+ * later version.
+ *
+ * Quagga 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 GNU Zebra; see the file COPYING.  If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include <zebra.h>
+
+#include "stream.h"
+#include "prefix.h"
+#include "vrf.h"
+#include "rib.h"
+
+#include "zebra/zserv.h"
+#include "zebra/zebra_vrf.h"
+#include "zebra/zebra_mroute.h"
+#include "zebra/rt_netlink.h"
+
+int
+zebra_ipmr_route_stats (struct zserv *client, int fd, u_short length, struct zebra_vrf *zvrf)
+{
+  struct mcast_route_data mroute;
+  struct stream *s;
+
+  char sbuf[40];
+  char gbuf[40];
+
+  memset (&mroute, 0, sizeof (mroute));
+  stream_get (&mroute.sg.src, client->ibuf, 4);
+  stream_get (&mroute.sg.grp, client->ibuf, 4);
+  mroute.ifindex = stream_getl (client->ibuf);
+
+  strcpy (sbuf, inet_ntoa (mroute.sg.src));
+  strcpy (gbuf, inet_ntoa (mroute.sg.grp));
+
+  netlink_get_ipmr_sg_stats (&mroute);
+
+  s = client->obuf;
+
+  stream_reset (s);
+
+  zserv_create_header (s, ZEBRA_IPMR_ROUTE_STATS, zvrf_id (zvrf));
+  stream_put_in_addr (s, &mroute.sg.src);
+  stream_put_in_addr (s, &mroute.sg.grp);
+  stream_put (s, &mroute.lastused, sizeof (mroute.lastused));
+
+  stream_putw_at (s, 0, stream_get_endp (s));
+  zebra_server_send_message (client);
+  return 0;
+}
diff --git a/zebra/zebra_mroute.h b/zebra/zebra_mroute.h
new file mode 100644 (file)
index 0000000..c0bac43
--- /dev/null
@@ -0,0 +1,35 @@
+/* zebra_mroute.h
+ * Copyright (C) 2016 Cumulus Networks, Inc.
+ * Donald Sharp
+ *
+ * This file is part of Quagga.
+ *
+ * Quagga 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, or (at your option) any
+ * later version.
+ *
+ * Quagga 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 GNU Zebra; see the file COPYING.  If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef __ZEBRA_MROUTE_H__
+#define __ZEBRA_MROUTE_H__
+
+struct mcast_route_data {
+  struct prefix_sg sg;
+  unsigned int ifindex;
+  unsigned long long lastused;
+};
+
+int zebra_ipmr_route_stats (struct zserv *client, int sock, u_short length, struct zebra_vrf *zvf);
+
+#endif
+
index a92efa027f0af00c1e7fd05d385e1ae003e4f7b0..44e29a8bb0ae2647f04ad3b2578db317bc908cae 100644 (file)
@@ -54,6 +54,7 @@
 #include "zebra/rtadv.h"
 #include "zebra/zebra_mpls.h"
 #include "zebra/zebra_fpm.h"
+#include "zebra/zebra_mroute.h"
 
 /* Event list of zebra. */
 enum event { ZEBRA_SERV, ZEBRA_READ, ZEBRA_WRITE };
@@ -2051,6 +2052,9 @@ zebra_client_read (struct thread *thread)
     case ZEBRA_MPLS_LABELS_DELETE:
       zread_mpls_labels (command, client, length, vrf_id);
       break;
+    case ZEBRA_IPMR_ROUTE_STATS:
+      zebra_ipmr_route_stats (client, sock, length, zvrf);
+      break;
     default:
       zlog_info ("Zebra received unknown command %d", command);
       break;