]> git.proxmox.com Git - mirror_frr.git/blobdiff - pimd/pim_mroute.c
Merge pull request #10960 from opensourcerouting/pim-unmacro-1
[mirror_frr.git] / pimd / pim_mroute.c
index af6f59824ccab7b9f8ca96fc6b9855639c3e044c..3015c4a61bc2f8cca869b1cbc1e395c75e23ba2c 100644 (file)
 #include "pim_ssm.h"
 #include "pim_sock.h"
 #include "pim_vxlan.h"
+#include "pim_msg.h"
 
 static void mroute_read_on(struct pim_instance *pim);
 
-static int pim_mroute_set(struct pim_instance *pim, int enable)
-{
-       int err;
-       int opt, data;
-       socklen_t data_len = sizeof(data);
-       long flags;
-
-       /*
-        * We need to create the VRF table for the pim mroute_socket
-        */
-       if (pim->vrf->vrf_id != VRF_DEFAULT) {
-               frr_with_privs(&pimd_privs) {
-
-                       data = pim->vrf->data.l.table_id;
-                       err = setsockopt(pim->mroute_socket, IPPROTO_IP,
-                                        MRT_TABLE,
-                                        &data, data_len);
-                       if (err) {
-                               zlog_warn(
-                                       "%s %s: failure: setsockopt(fd=%d,IPPROTO_IP, MRT_TABLE=%d): errno=%d: %s",
-                                       __FILE__, __func__, pim->mroute_socket,
-                                       data, errno, safe_strerror(errno));
-                               return -1;
-                       }
 
-               }
-       }
-
-       frr_with_privs(&pimd_privs) {
-               opt = enable ? MRT_INIT : MRT_DONE;
-               /*
-                * *BSD *cares* about what value we pass down
-                * here
-                */
-               data = 1;
-               err = setsockopt(pim->mroute_socket, IPPROTO_IP,
-                                opt, &data, data_len);
-               if (err) {
-                       zlog_warn(
-                               "%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,%s=%d): errno=%d: %s",
-                               __FILE__, __func__, pim->mroute_socket,
-                               enable ? "MRT_INIT" : "MRT_DONE", data, errno,
-                               safe_strerror(errno));
-                       return -1;
-               }
-       }
-
-#if defined(HAVE_IP_PKTINFO)
-       if (enable) {
-               /* Linux and Solaris IP_PKTINFO */
-               data = 1;
-               if (setsockopt(pim->mroute_socket, IPPROTO_IP, IP_PKTINFO,
-                              &data, data_len)) {
-                       zlog_warn(
-                               "Could not set IP_PKTINFO on socket fd=%d: errno=%d: %s",
-                               pim->mroute_socket, errno,
-                               safe_strerror(errno));
-               }
-       }
-#endif
-
-       setsockopt_so_recvbuf(pim->mroute_socket, 1024 * 1024 * 8);
-
-       flags = fcntl(pim->mroute_socket, F_GETFL, 0);
-       if (flags < 0) {
-               zlog_warn("Could not get flags on socket fd:%d %d %s",
-                         pim->mroute_socket, errno, safe_strerror(errno));
-               close(pim->mroute_socket);
-               return -1;
-       }
-       if (fcntl(pim->mroute_socket, F_SETFL, flags | O_NONBLOCK)) {
-               zlog_warn("Could not set O_NONBLOCK on socket fd:%d %d %s",
-                         pim->mroute_socket, errno, safe_strerror(errno));
-               close(pim->mroute_socket);
-               return -1;
-       }
-
-       if (enable) {
-#if defined linux
-               int upcalls = IGMPMSG_WRVIFWHOLE;
-               opt = MRT_PIM;
-
-               err = setsockopt(pim->mroute_socket, IPPROTO_IP, opt, &upcalls,
-                                sizeof(upcalls));
-               if (err) {
-                       zlog_warn(
-                               "Failure to register for VIFWHOLE and WRONGVIF upcalls %d %s",
-                               errno, safe_strerror(errno));
-                       return -1;
-               }
-#else
-               zlog_warn(
-                       "PIM-SM will not work properly on this platform, until the ability to receive the WRVIFWHOLE upcall");
-#endif
-       }
-
-       return 0;
-}
-
-#if PIM_IPV == 4
-static const char *const igmpmsgtype2str[IGMPMSG_WRVIFWHOLE + 1] = {
-       "<unknown_upcall?>", "NOCACHE", "WRONGVIF", "WHOLEPKT", "WRVIFWHOLE"};
-
-static int pim_mroute_msg_nocache(int fd, struct interface *ifp,
-                                 const struct igmpmsg *msg)
+int pim_mroute_msg_nocache(int fd, struct interface *ifp, const kernmsg *msg)
 {
        struct pim_interface *pim_ifp = ifp->info;
        struct pim_upstream *up;
        struct pim_rpf *rpg;
        pim_sgaddr sg;
 
-       rpg = pim_ifp ? RP(pim_ifp->pim, msg->im_dst) : NULL;
+       rpg = pim_ifp ? RP(pim_ifp->pim, msg->msg_im_dst) : NULL;
        /*
         * If the incoming interface is unknown OR
         * the Interface type is SSM we don't need to
         * do anything here
         */
-       if (!rpg || pim_rpf_addr_is_inaddr_none(rpg)) {
+       if (!rpg || pim_rpf_addr_is_inaddr_any(rpg)) {
                if (PIM_DEBUG_MROUTE_DETAIL)
                        zlog_debug(
                                "%s: Interface is not configured correctly to handle incoming packet: Could be !pim_ifp, !SM, !RP",
@@ -176,7 +74,7 @@ static int pim_mroute_msg_nocache(int fd, struct interface *ifp,
         * If we've received a multicast packet that isn't connected to
         * us
         */
-       if (!pim_if_connected_to_source(ifp, msg->im_src)) {
+       if (!pim_if_connected_to_source(ifp, msg->msg_im_src)) {
                if (PIM_DEBUG_MROUTE_DETAIL)
                        zlog_debug(
                                "%s: Received incoming packet that doesn't originate on our seg",
@@ -185,13 +83,14 @@ static int pim_mroute_msg_nocache(int fd, struct interface *ifp,
        }
 
        memset(&sg, 0, sizeof(sg));
-       sg.src = msg->im_src;
-       sg.grp = msg->im_dst;
+       sg.src = msg->msg_im_src;
+       sg.grp = msg->msg_im_dst;
 
        if (!(PIM_I_am_DR(pim_ifp))) {
                if (PIM_DEBUG_MROUTE_DETAIL)
-                       zlog_debug("%s: Interface is not the DR blackholing incoming traffic for %pSG",
-                                  __func__, &sg);
+                       zlog_debug(
+                               "%s: Interface is not the DR blackholing incoming traffic for %pSG",
+                               __func__, &sg);
 
                /*
                 * We are not the DR, but we are still receiving packets
@@ -238,22 +137,21 @@ static int pim_mroute_msg_nocache(int fd, struct interface *ifp,
        return 0;
 }
 
-static int pim_mroute_msg_wholepkt(int fd, struct interface *ifp,
-                                  const char *buf)
+int pim_mroute_msg_wholepkt(int fd, struct interface *ifp, const char *buf)
 {
        struct pim_interface *pim_ifp;
        pim_sgaddr sg;
        struct pim_rpf *rpg;
-       const struct ip *ip_hdr;
+       const ipv_hdr *ip_hdr;
        struct pim_upstream *up;
 
        pim_ifp = ifp->info;
 
-       ip_hdr = (const struct ip *)buf;
+       ip_hdr = (const ipv_hdr *)buf;
 
        memset(&sg, 0, sizeof(sg));
-       sg.src = ip_hdr->ip_src;
-       sg.grp = ip_hdr->ip_dst;
+       sg.src = IPV_SRC(ip_hdr);
+       sg.grp = IPV_DST(ip_hdr);
 
        up = pim_upstream_find(pim_ifp->pim, &sg);
        if (!up) {
@@ -268,8 +166,9 @@ static int pim_mroute_msg_wholepkt(int fd, struct interface *ifp,
                                              __func__, NULL);
                        if (!up) {
                                if (PIM_DEBUG_MROUTE)
-                                       zlog_debug("%s: Unable to create upstream information for %pSG",
-                                                  __func__, &sg);
+                                       zlog_debug(
+                                               "%s: Unable to create upstream information for %pSG",
+                                               __func__, &sg);
                                return 0;
                        }
                        pim_upstream_keep_alive_timer_start(
@@ -283,8 +182,9 @@ static int pim_mroute_msg_wholepkt(int fd, struct interface *ifp,
                        return 0;
                }
                if (PIM_DEBUG_MROUTE_DETAIL) {
-                       zlog_debug("%s: Unable to find upstream channel WHOLEPKT%pSG",
-                                  __func__, &sg);
+                       zlog_debug(
+                               "%s: Unable to find upstream channel WHOLEPKT%pSG",
+                               __func__, &sg);
                }
                return 0;
        }
@@ -300,8 +200,8 @@ static int pim_mroute_msg_wholepkt(int fd, struct interface *ifp,
 
        rpg = pim_ifp ? RP(pim_ifp->pim, sg.grp) : NULL;
 
-       if ((pim_rpf_addr_is_inaddr_none(rpg)) || (!pim_ifp)
-           || (!(PIM_I_am_DR(pim_ifp)))) {
+       if ((pim_rpf_addr_is_inaddr_any(rpg)) || (!pim_ifp) ||
+           (!(PIM_I_am_DR(pim_ifp)))) {
                if (PIM_DEBUG_MROUTE) {
                        zlog_debug("%s: Failed Check send packet", __func__);
                }
@@ -314,8 +214,9 @@ static int pim_mroute_msg_wholepkt(int fd, struct interface *ifp,
        if (!up->t_rs_timer) {
                if (pim_is_grp_ssm(pim_ifp->pim, sg.grp)) {
                        if (PIM_DEBUG_PIM_REG)
-                               zlog_debug("%pSG register forward skipped as group is SSM",
-                                          &sg);
+                               zlog_debug(
+                                       "%pSG register forward skipped as group is SSM",
+                                       &sg);
                        return 0;
                }
 
@@ -327,23 +228,22 @@ static int pim_mroute_msg_wholepkt(int fd, struct interface *ifp,
                        return 0;
                }
 
-               pim_register_send((uint8_t *)buf + sizeof(struct ip),
-                                 ntohs(ip_hdr->ip_len) - sizeof(struct ip),
+               pim_register_send((uint8_t *)buf + sizeof(ipv_hdr),
+                                 ntohs(IPV_LEN(ip_hdr)) - sizeof(ipv_hdr),
                                  pim_ifp->primary_address, rpg, 0, up);
        }
        return 0;
 }
 
-static int pim_mroute_msg_wrongvif(int fd, struct interface *ifp,
-                                  const struct igmpmsg *msg)
+int pim_mroute_msg_wrongvif(int fd, struct interface *ifp, const kernmsg *msg)
 {
        struct pim_ifchannel *ch;
        struct pim_interface *pim_ifp;
        pim_sgaddr sg;
 
        memset(&sg, 0, sizeof(sg));
-       sg.src = msg->im_src;
-       sg.grp = msg->im_dst;
+       sg.src = msg->msg_im_src;
+       sg.grp = msg->msg_im_dst;
 
        /*
          Send Assert(S,G) on iif as response to WRONGVIF kernel upcall.
@@ -358,16 +258,18 @@ static int pim_mroute_msg_wrongvif(int fd, struct interface *ifp,
 
        if (!ifp) {
                if (PIM_DEBUG_MROUTE)
-                       zlog_debug("%s: WRONGVIF (S,G)=%pSG could not find input interface for input_vif_index=%d",
-                                  __func__, &sg, msg->im_vif);
+                       zlog_debug(
+                               "%s: WRONGVIF (S,G)=%pSG could not find input interface for input_vif_index=%d",
+                               __func__, &sg, msg->msg_im_vif);
                return -1;
        }
 
        pim_ifp = ifp->info;
        if (!pim_ifp) {
                if (PIM_DEBUG_MROUTE)
-                       zlog_debug("%s: WRONGVIF (S,G)=%pSG multicast not enabled on interface %s",
-                                  __func__, &sg, ifp->name);
+                       zlog_debug(
+                               "%s: WRONGVIF (S,G)=%pSG multicast not enabled on interface %s",
+                               __func__, &sg, ifp->name);
                return -2;
        }
 
@@ -375,16 +277,17 @@ static int pim_mroute_msg_wrongvif(int fd, struct interface *ifp,
        if (!ch) {
                pim_sgaddr star_g = sg;
                if (PIM_DEBUG_MROUTE)
-                       zlog_debug("%s: WRONGVIF (S,G)=%pSG could not find channel on interface %s",
-                                  __func__, &sg, ifp->name);
+                       zlog_debug(
+                               "%s: WRONGVIF (S,G)=%pSG could not find channel on interface %s",
+                               __func__, &sg, ifp->name);
 
                star_g.src = PIMADDR_ANY;
                ch = pim_ifchannel_find(ifp, &star_g);
                if (!ch) {
                        if (PIM_DEBUG_MROUTE)
-                               zlog_debug("%s: WRONGVIF (*,G)=%pSG could not find channel on interface %s",
-                                          __func__, &star_g,
-                                          ifp->name);
+                               zlog_debug(
+                                       "%s: WRONGVIF (*,G)=%pSG could not find channel on interface %s",
+                                       __func__, &star_g, ifp->name);
                        return -3;
                }
        }
@@ -433,10 +336,9 @@ static int pim_mroute_msg_wrongvif(int fd, struct interface *ifp,
        return 0;
 }
 
-static int pim_mroute_msg_wrvifwhole(int fd, struct interface *ifp,
-                                    const char *buf)
+int pim_mroute_msg_wrvifwhole(int fd, struct interface *ifp, const char *buf)
 {
-       const struct ip *ip_hdr = (const struct ip *)buf;
+       const ipv_hdr *ip_hdr = (const ipv_hdr *)buf;
        struct pim_interface *pim_ifp;
        struct pim_instance *pim;
        struct pim_ifchannel *ch;
@@ -447,8 +349,8 @@ static int pim_mroute_msg_wrvifwhole(int fd, struct interface *ifp,
        pim_ifp = ifp->info;
 
        memset(&sg, 0, sizeof(sg));
-       sg.src = ip_hdr->ip_src;
-       sg.grp = ip_hdr->ip_dst;
+       sg.src = IPV_SRC(ip_hdr);
+       sg.grp = IPV_DST(ip_hdr);
 
        ch = pim_ifchannel_find(ifp, &sg);
        if (ch) {
@@ -481,8 +383,8 @@ static int pim_mroute_msg_wrvifwhole(int fd, struct interface *ifp,
                struct pim_rpf *rpf = RP(pim_ifp->pim, sg.grp);
 
                /* No RPF or No RPF interface or No mcast on RPF interface */
-               if (!rpf || !rpf->source_nexthop.interface
-                   || !rpf->source_nexthop.interface->info)
+               if (!rpf || !rpf->source_nexthop.interface ||
+                   !rpf->source_nexthop.interface->info)
                        return 0;
 
                /*
@@ -512,7 +414,7 @@ static int pim_mroute_msg_wrvifwhole(int fd, struct interface *ifp,
                         * bow out of doing a nexthop lookup and
                         * setting the SPTBIT to true
                         */
-                       if (up->upstream_register.s_addr != INADDR_ANY &&
+                       if (!(pim_addr_is_any(up->upstream_register)) &&
                            pim_nexthop_lookup(pim_ifp->pim, &source,
                                               up->upstream_register, 0)) {
                                pim_register_stop_send(source.interface, &sg,
@@ -535,6 +437,28 @@ static int pim_mroute_msg_wrvifwhole(int fd, struct interface *ifp,
                                                pim_ifp->primary_address,
                                                up->upstream_register);
                                up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE;
+                       } else {
+                               /*
+                                * At this point pimd is connected to
+                                * the source, it has a parent, we are not
+                                * the RP  and the SPTBIT should be set
+                                * since we know *the* S,G is on the SPT.
+                                * The first time this happens, let's cause
+                                * an immediate join to go out so that
+                                * the RP can trim this guy immediately
+                                * if necessary, instead of waiting
+                                * one join/prune send cycle
+                                */
+                               if (up->sptbit != PIM_UPSTREAM_SPTBIT_TRUE &&
+                                   up->parent &&
+                                   up->rpf.source_nexthop.interface !=
+                                           up->parent->rpf.source_nexthop
+                                                   .interface) {
+                                       up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE;
+                                       pim_jp_agg_single_upstream_send(
+                                               &up->parent->rpf, up->parent,
+                                               true);
+                               }
                        }
                        pim_upstream_keep_alive_timer_start(
                                up, pim_ifp->pim->keep_alive_time);
@@ -551,8 +475,9 @@ static int pim_mroute_msg_wrvifwhole(int fd, struct interface *ifp,
                                      NULL);
                if (!up) {
                        if (PIM_DEBUG_MROUTE)
-                               zlog_debug("%pSG: WRONGVIF%s unable to create upstream on interface",
-                                          &sg, ifp->name);
+                               zlog_debug(
+                                       "%pSG: WRONGVIF%s unable to create upstream on interface",
+                                       &sg, ifp->name);
                        return -2;
                }
                PIM_UPSTREAM_FLAG_SET_SRC_STREAM(up->flags);
@@ -577,117 +502,6 @@ static int pim_mroute_msg_wrvifwhole(int fd, struct interface *ifp,
        return 0;
 }
 
-static int pim_mroute_msg(struct pim_instance *pim, const char *buf,
-                         int buf_size, ifindex_t ifindex)
-{
-       struct interface *ifp;
-       const struct ip *ip_hdr;
-       const struct igmpmsg *msg;
-
-       if (buf_size < (int)sizeof(struct ip))
-               return 0;
-
-       ip_hdr = (const struct ip *)buf;
-
-       if (ip_hdr->ip_p == IPPROTO_IGMP) {
-#if PIM_IPV == 4
-               struct pim_interface *pim_ifp;
-               struct in_addr ifaddr;
-               struct gm_sock *igmp;
-               const struct prefix *connected_src;
-
-               /* We have the IP packet but we do not know which interface this
-                * packet was
-                * received on. Find the interface that is on the same subnet as
-                * the source
-                * of the IP packet.
-                */
-               ifp = if_lookup_by_index(ifindex, pim->vrf->vrf_id);
-
-               if (!ifp || !ifp->info)
-                       return 0;
-
-               connected_src = pim_if_connected_to_source(ifp, ip_hdr->ip_src);
-
-               if (!connected_src) {
-                       if (PIM_DEBUG_IGMP_PACKETS) {
-                               zlog_debug("Recv IGMP packet on interface: %s from a non-connected source: %pI4",
-                                          ifp->name, &ip_hdr->ip_src);
-                       }
-                       return 0;
-               }
-
-               pim_ifp = ifp->info;
-               ifaddr = connected_src->u.prefix4;
-               igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->gm_socket_list,
-                                                  ifaddr);
-
-               if (PIM_DEBUG_IGMP_PACKETS) {
-                       zlog_debug(
-                               "%s(%s): igmp kernel upcall on %s(%p) for %pI4 -> %pI4",
-                               __func__, pim->vrf->name, ifp->name, igmp,
-                               &ip_hdr->ip_src, &ip_hdr->ip_dst);
-               }
-               if (igmp)
-                       pim_igmp_packet(igmp, (char *)buf, buf_size);
-               else if (PIM_DEBUG_IGMP_PACKETS) {
-                       zlog_debug("No IGMP socket on interface: %s with connected source: %pFX",
-                                  ifp->name, connected_src);
-               }
-#endif
-       } else if (ip_hdr->ip_p) {
-               if (PIM_DEBUG_MROUTE_DETAIL) {
-                       zlog_debug(
-                               "%s: no kernel upcall proto=%d src: %pI4 dst: %pI4 msg_size=%d",
-                               __func__, ip_hdr->ip_p, &ip_hdr->ip_src, &ip_hdr->ip_dst,
-                               buf_size);
-               }
-
-       } else {
-               msg = (const struct igmpmsg *)buf;
-
-               ifp = pim_if_find_by_vif_index(pim, msg->im_vif);
-
-               if (!ifp)
-                       return 0;
-               if (PIM_DEBUG_MROUTE) {
-                       zlog_debug(
-                               "%s: pim kernel upcall %s type=%d ip_p=%d from fd=%d for (S,G)=(%pI4,%pI4) on %s vifi=%d  size=%d",
-                               __func__, igmpmsgtype2str[msg->im_msgtype],
-                               msg->im_msgtype, ip_hdr->ip_p,
-                               pim->mroute_socket, &msg->im_src, &msg->im_dst, ifp->name,
-                               msg->im_vif, buf_size);
-               }
-
-               switch (msg->im_msgtype) {
-               case IGMPMSG_WRONGVIF:
-                       return pim_mroute_msg_wrongvif(pim->mroute_socket, ifp,
-                                                      msg);
-               case IGMPMSG_NOCACHE:
-                       return pim_mroute_msg_nocache(pim->mroute_socket, ifp,
-                                                     msg);
-               case IGMPMSG_WHOLEPKT:
-                       return pim_mroute_msg_wholepkt(pim->mroute_socket, ifp,
-                                                      (const char *)msg);
-               case IGMPMSG_WRVIFWHOLE:
-                       return pim_mroute_msg_wrvifwhole(
-                               pim->mroute_socket, ifp, (const char *)msg);
-               default:
-                       break;
-               }
-       }
-
-       return 0;
-}
-#else /* PIM_IPV != 4 */
-
-static int pim_mroute_msg(struct pim_instance *pim, const char *buf,
-                         int buf_size, ifindex_t ifindex)
-{
-       return 0;
-}
-#endif /* PIM_IPV != 4 */
-
 static void mroute_read(struct thread *t)
 {
        struct pim_instance *pim;
@@ -724,6 +538,8 @@ static void mroute_read(struct thread *t)
 /* Keep reading */
 done:
        mroute_read_on(pim);
+
+       return;
 }
 
 static void mroute_read_on(struct pim_instance *pim)
@@ -743,8 +559,11 @@ int pim_mroute_socket_enable(struct pim_instance *pim)
 
        frr_with_privs(&pimd_privs) {
 
+#if PIM_IPV == 4
                fd = socket(AF_INET, SOCK_RAW, IPPROTO_IGMP);
-
+#else
+               fd = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
+#endif
                if (fd < 0) {
                        zlog_warn("Could not create mroute socket: errno=%d: %s",
                                  errno,
@@ -812,7 +631,7 @@ int pim_mroute_add_vif(struct interface *ifp, pim_addr ifaddr,
                       unsigned char flags)
 {
        struct pim_interface *pim_ifp = ifp->info;
-       struct vifctl vc;
+       pim_vifctl vc;
        int err;
 
        if (PIM_DEBUG_MROUTE)
@@ -821,9 +640,10 @@ int pim_mroute_add_vif(struct interface *ifp, pim_addr ifaddr,
                           pim_ifp->pim->vrf->name);
 
        memset(&vc, 0, sizeof(vc));
-       vc.vifc_vifi = pim_ifp->mroute_vif_index;
+       vc.vc_vifi = pim_ifp->mroute_vif_index;
+#if PIM_IPV == 4
 #ifdef VIFF_USE_IFINDEX
-       vc.vifc_lcl_ifindex = ifp->ifindex;
+       vc.vc_lcl_ifindex = ifp->ifindex;
 #else
        if (ifaddr.s_addr == INADDR_ANY) {
                zlog_warn(
@@ -831,24 +651,29 @@ int pim_mroute_add_vif(struct interface *ifp, pim_addr ifaddr,
                        __func__);
                return -1;
        }
-       memcpy(&vc.vifc_lcl_addr, &ifaddr, sizeof(vc.vifc_lcl_addr));
+       memcpy(&vc.vc_lcl_addr, &ifaddr, sizeof(vc.vc_lcl_addr));
+#endif
+#else
+       vc.vc_pifi = ifp->ifindex;
 #endif
-       vc.vifc_flags = flags;
-       vc.vifc_threshold = PIM_MROUTE_MIN_TTL;
-       vc.vifc_rate_limit = 0;
+       vc.vc_flags = flags;
+       vc.vc_threshold = PIM_MROUTE_MIN_TTL;
+       vc.vc_rate_limit = 0;
 
+#if PIM_IPV == 4
 #ifdef PIM_DVMRP_TUNNEL
-       if (vc.vifc_flags & VIFF_TUNNEL) {
-               memcpy(&vc.vifc_rmt_addr, &vif_remote_addr,
-                      sizeof(vc.vifc_rmt_addr));
+       if (vc.vc_flags & VIFF_TUNNEL) {
+               memcpy(&vc.vc_rmt_addr, &vif_remote_addr,
+                      sizeof(vc.vc_rmt_addr));
        }
+#endif
 #endif
 
-       err = setsockopt(pim_ifp->pim->mroute_socket, IPPROTO_IP, MRT_ADD_VIF,
+       err = setsockopt(pim_ifp->pim->mroute_socket, PIM_IPPROTO, MRT_ADD_VIF,
                         (void *)&vc, sizeof(vc));
        if (err) {
                zlog_warn(
-                       "%s: failure: setsockopt(fd=%d,IPPROTO_IP,MRT_ADD_VIF,vif_index=%d,ifaddr=%pPAs,flag=%d): errno=%d: %s",
+                       "%s: failure: setsockopt(fd=%d,PIM_IPPROTO,MRT_ADD_VIF,vif_index=%d,ifaddr=%pPAs,flag=%d): errno=%d: %s",
                        __func__, pim_ifp->pim->mroute_socket, ifp->ifindex,
                        &ifaddr, flags, errno, safe_strerror(errno));
                return -2;
@@ -860,7 +685,7 @@ int pim_mroute_add_vif(struct interface *ifp, pim_addr ifaddr,
 int pim_mroute_del_vif(struct interface *ifp)
 {
        struct pim_interface *pim_ifp = ifp->info;
-       struct vifctl vc;
+       pim_vifctl vc;
        int err;
 
        if (PIM_DEBUG_MROUTE)
@@ -869,13 +694,13 @@ int pim_mroute_del_vif(struct interface *ifp)
                           pim_ifp->pim->vrf->name);
 
        memset(&vc, 0, sizeof(vc));
-       vc.vifc_vifi = pim_ifp->mroute_vif_index;
+       vc.vc_vifi = pim_ifp->mroute_vif_index;
 
-       err = setsockopt(pim_ifp->pim->mroute_socket, IPPROTO_IP, MRT_DEL_VIF,
+       err = setsockopt(pim_ifp->pim->mroute_socket, PIM_IPPROTO, MRT_DEL_VIF,
                         (void *)&vc, sizeof(vc));
        if (err) {
                zlog_warn(
-                       "%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,MRT_DEL_VIF,vif_index=%d): errno=%d: %s",
+                       "%s %s: failure: setsockopt(fd=%d,PIM_IPPROTO,MRT_DEL_VIF,vif_index=%d): errno=%d: %s",
                        __FILE__, __func__, pim_ifp->pim->mroute_socket,
                        pim_ifp->mroute_vif_index, errno, safe_strerror(errno));
                return -2;
@@ -983,20 +808,21 @@ static int pim_mroute_add(struct channel_oil *c_oil, const char *name)
            && *oil_parent(c_oil) != 0) {
                *oil_parent(tmp_oil) = 0;
        }
-       err = setsockopt(pim->mroute_socket, IPPROTO_IP, MRT_ADD_MFC,
+       /* For IPv6 MRT_ADD_MFC is defined to MRT6_ADD_MFC */
+       err = setsockopt(pim->mroute_socket, PIM_IPPROTO, MRT_ADD_MFC,
                         &tmp_oil->oil, sizeof(tmp_oil->oil));
 
        if (!err && !c_oil->installed
            && !pim_addr_is_any(*oil_origin(c_oil))
            && *oil_parent(c_oil) != 0) {
                *oil_parent(tmp_oil) = *oil_parent(c_oil);
-               err = setsockopt(pim->mroute_socket, IPPROTO_IP, MRT_ADD_MFC,
+               err = setsockopt(pim->mroute_socket, PIM_IPPROTO, MRT_ADD_MFC,
                                 &tmp_oil->oil, sizeof(tmp_oil->oil));
        }
 
        if (err) {
                zlog_warn(
-                       "%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,MRT_ADD_MFC): errno=%d: %s",
+                       "%s %s: failure: setsockopt(fd=%d,PIM_IPPROTO,MRT_ADD_MFC): errno=%d: %s",
                        __FILE__, __func__, pim->mroute_socket, errno,
                        safe_strerror(errno));
                return -2;
@@ -1172,12 +998,12 @@ int pim_mroute_del(struct channel_oil *c_oil, const char *name)
                return -2;
        }
 
-       err = setsockopt(pim->mroute_socket, IPPROTO_IP, MRT_DEL_MFC,
+       err = setsockopt(pim->mroute_socket, PIM_IPPROTO, MRT_DEL_MFC,
                         &c_oil->oil, sizeof(c_oil->oil));
        if (err) {
                if (PIM_DEBUG_MROUTE)
                        zlog_warn(
-                               "%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,MRT_DEL_MFC): errno=%d: %s",
+                               "%s %s: failure: setsockopt(fd=%d,PIM_IPPROTO,MRT_DEL_MFC): errno=%d: %s",
                                __FILE__, __func__, pim->mroute_socket, errno,
                                safe_strerror(errno));
                return -2;
@@ -1199,6 +1025,7 @@ int pim_mroute_del(struct channel_oil *c_oil, const char *name)
 void pim_mroute_update_counters(struct channel_oil *c_oil)
 {
        struct pim_instance *pim = c_oil->pim;
+       pim_sioc_sg_req sgreq;
 
        c_oil->cc.oldpktcnt = c_oil->cc.pktcnt;
        c_oil->cc.oldbytecnt = c_oil->cc.bytecnt;
@@ -1217,29 +1044,33 @@ void pim_mroute_update_counters(struct channel_oil *c_oil)
                return;
        }
 
-#if PIM_IPV == 4
-       struct sioc_sg_req sgreq;
 
        memset(&sgreq, 0, sizeof(sgreq));
+
+#if PIM_IPV == 4
        sgreq.src = *oil_origin(c_oil);
        sgreq.grp = *oil_mcastgrp(c_oil);
-
        pim_zlookup_sg_statistics(c_oil);
-       if (ioctl(pim->mroute_socket, SIOCGETSGCNT, &sgreq)) {
+#else
+       sgreq.src = c_oil->oil.mf6cc_origin;
+       sgreq.grp = c_oil->oil.mf6cc_mcastgrp;
+       /* TODO Zlookup_sg_statistics for V6 to be added */
+#endif
+       if (ioctl(pim->mroute_socket, PIM_SIOCGETSGCNT, &sgreq)) {
                pim_sgaddr sg;
 
                sg.src = *oil_origin(c_oil);
                sg.grp = *oil_mcastgrp(c_oil);
 
-               zlog_warn("ioctl(SIOCGETSGCNT=%lu) failure for (S,G)=%pSG: errno=%d: %s",
-                         (unsigned long)SIOCGETSGCNT, &sg,
-                         errno, safe_strerror(errno));
+               zlog_warn(
+                       "ioctl(PIM_SIOCGETSGCNT=%lu) failure for (S,G)=%pSG: errno=%d: %s",
+                       (unsigned long)PIM_SIOCGETSGCNT, &sg, errno,
+                       safe_strerror(errno));
                return;
        }
 
        c_oil->cc.pktcnt = sgreq.pktcnt;
        c_oil->cc.bytecnt = sgreq.bytecnt;
        c_oil->cc.wrong_if = sgreq.wrong_if;
-#endif
        return;
 }