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
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
#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;
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))
{
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;
struct channel_counts
{
+ unsigned long long lastused;
+ unsigned long long oldlastused;
unsigned long pktcnt;
unsigned long oldpktcnt;
unsigned long bytecnt;
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);
#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;
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;
+
+}
void pim_zlookup_show_ip_multicast (struct vty *vty);
+int pim_zlookup_sg_statistics (struct channel_oil *c_oil);
#endif /* PIM_ZLOOKUP_H */
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 \
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)
#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
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)
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];
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));
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])
{
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);
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)
{
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 */
#include "log.h"
#include "rib.h"
#include "vty.h"
+#include "prefix.h"
#include "zebra/zserv.h"
#include "zebra/zebra_ns.h"
--- /dev/null
+/* 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;
+}
--- /dev/null
+/* 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
+
#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 };
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;