From: Donald Sharp Date: Thu, 11 Aug 2016 00:04:20 +0000 (+0000) Subject: lib, pimd, zebra: Allow pimd to ask the kernel about mroute info X-Git-Tag: frr-3.0-branchpoint~64^2~10^2~291 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=e3be04328f601963c825c722355f62c4b4e7cb31;p=mirror%2Ffrr.git lib, pimd, zebra: Allow pimd to ask the kernel about mroute info When we need to lookup the mroute info for a route. Allow pimd to ask the kernel. Signed-off-by: Donald Sharp --- diff --git a/lib/log.c b/lib/log.c index f9877300b4..67f335c6ae 100644 --- 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 diff --git a/lib/zebra.h b/lib/zebra.h index 1fc643d597..f344867697 100644 --- a/lib/zebra.h +++ b/lib/zebra.h @@ -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 diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index 8426a4add5..2fc733e97f 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -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; diff --git a/pimd/pim_oil.h b/pimd/pim_oil.h index 6b55bdc4d5..1bbd232e4d 100644 --- a/pimd/pim_oil.h +++ b/pimd/pim_oil.h @@ -52,6 +52,8 @@ struct channel_counts { + unsigned long long lastused; + unsigned long long oldlastused; unsigned long pktcnt; unsigned long oldpktcnt; unsigned long bytecnt; diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 39f609da28..bb322a7cdd 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -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); diff --git a/pimd/pim_zlookup.c b/pimd/pim_zlookup.c index ceac1eff7a..6cf6a6b2f7 100644 --- a/pimd/pim_zlookup.c +++ b/pimd/pim_zlookup.c @@ -28,11 +28,14 @@ #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, "%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; + +} diff --git a/pimd/pim_zlookup.h b/pimd/pim_zlookup.h index d92eb089b1..4dea5750c5 100644 --- a/pimd/pim_zlookup.h +++ b/pimd/pim_zlookup.h @@ -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 */ diff --git a/zebra/Makefile.am b/zebra/Makefile.am index 65927262f2..428090d488 100644 --- a/zebra/Makefile.am +++ b/zebra/Makefile.am @@ -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) diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index ff907bb878..5dc9a10e29 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -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) { diff --git a/zebra/rt_netlink.h b/zebra/rt_netlink.h index 7183525fba..6774b7dd3d 100644 --- a/zebra/rt_netlink.h +++ b/zebra/rt_netlink.h @@ -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 */ diff --git a/zebra/zebra_fpm_netlink.c b/zebra/zebra_fpm_netlink.c index a09008b396..5dd08ca782 100644 --- a/zebra/zebra_fpm_netlink.c +++ b/zebra/zebra_fpm_netlink.c @@ -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 index 0000000000..8dddb4e507 --- /dev/null +++ b/zebra/zebra_mroute.c @@ -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 + +#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 index 0000000000..c0bac43a81 --- /dev/null +++ b/zebra/zebra_mroute.h @@ -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 + diff --git a/zebra/zserv.c b/zebra/zserv.c index a92efa027f..44e29a8bb0 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -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;