]> git.proxmox.com Git - mirror_frr.git/blobdiff - pimd/pim_cmd.c
pimd: Create pimreg interface when we start any interface config
[mirror_frr.git] / pimd / pim_cmd.c
index f058b7adbfb26ffbe7c62fcbe94b7b188fb24fc9..19a42964ebaaed1cf9f8d3dde302a1f41de02f5f 100644 (file)
@@ -60,6 +60,7 @@
 #include "pim_ssm.h"
 #include "pim_nht.h"
 #include "pim_bfd.h"
+#include "pim_vxlan.h"
 #include "bfd.h"
 
 #ifndef VTYSH_EXTRACT_PL
@@ -198,7 +199,7 @@ static void pim_show_assert_helper(struct vty *vty,
        pim_time_uptime(uptime, sizeof(uptime), now - ch->ifassert_creation);
        pim_time_timer_to_mmss(timer, sizeof(timer), ch->t_ifassert_timer);
 
-       vty_out(vty, "%-9s %-15s %-15s %-15s %-6s %-15s %-8s %-5s\n",
+       vty_out(vty, "%-16s %-15s %-15s %-15s %-6s %-15s %-8s %-5s\n",
                ch->interface->name, inet_ntoa(ifaddr), ch_src_str, ch_grp_str,
                pim_ifchannel_ifassert_name(ch->ifassert_state), winner_str,
                uptime, timer);
@@ -214,7 +215,7 @@ static void pim_show_assert(struct pim_instance *pim, struct vty *vty)
        now = pim_time_monotonic_sec();
 
        vty_out(vty,
-               "Interface Address         Source          Group           State  Winner          Uptime   Timer\n");
+               "Interface        Address         Source          Group           State  Winner          Uptime   Timer\n");
 
        FOR_ALL_INTERFACES (pim->vrf, ifp) {
                pim_ifp = ifp->info;
@@ -239,7 +240,7 @@ static void pim_show_assert_internal_helper(struct vty *vty,
 
        pim_inet4_dump("<ch_src?>", ch->sg.src, ch_src_str, sizeof(ch_src_str));
        pim_inet4_dump("<ch_grp?>", ch->sg.grp, ch_grp_str, sizeof(ch_grp_str));
-       vty_out(vty, "%-9s %-15s %-15s %-15s %-3s %-3s %-3s %-4s\n",
+       vty_out(vty, "%-16s %-15s %-15s %-15s %-3s %-3s %-3s %-4s\n",
                ch->interface->name, inet_ntoa(ifaddr), ch_src_str, ch_grp_str,
                PIM_IF_FLAG_TEST_COULD_ASSERT(ch->flags) ? "yes" : "no",
                pim_macro_ch_could_assert_eval(ch) ? "yes" : "no",
@@ -261,7 +262,7 @@ static void pim_show_assert_internal(struct pim_instance *pim, struct vty *vty)
                "eATD: Evaluate AssertTrackingDesired\n\n");
 
        vty_out(vty,
-               "Interface Address         Source          Group           CA  eCA ATD eATD\n");
+               "Interface        Address         Source          Group           CA  eCA ATD eATD\n");
        FOR_ALL_INTERFACES (pim->vrf, ifp) {
                pim_ifp = ifp->info;
                if (!pim_ifp)
@@ -292,7 +293,7 @@ static void pim_show_assert_metric_helper(struct vty *vty,
        pim_inet4_dump("<ch_grp?>", ch->sg.grp, ch_grp_str, sizeof(ch_grp_str));
        pim_inet4_dump("<addr?>", am.ip_address, addr_str, sizeof(addr_str));
 
-       vty_out(vty, "%-9s %-15s %-15s %-15s %-3s %4u %6u %-15s\n",
+       vty_out(vty, "%-16s %-15s %-15s %-15s %-3s %4u %6u %-15s\n",
                ch->interface->name, inet_ntoa(ifaddr), ch_src_str, ch_grp_str,
                am.rpt_bit_flag ? "yes" : "no", am.metric_preference,
                am.route_metric, addr_str);
@@ -305,7 +306,7 @@ static void pim_show_assert_metric(struct pim_instance *pim, struct vty *vty)
        struct interface *ifp;
 
        vty_out(vty,
-               "Interface Address         Source          Group           RPT Pref Metric Address        \n");
+               "Interface        Address         Source          Group           RPT Pref Metric Address        \n");
 
        FOR_ALL_INTERFACES (pim->vrf, ifp) {
                pim_ifp = ifp->info;
@@ -349,7 +350,7 @@ static void pim_show_assert_winner_metric_helper(struct vty *vty,
        else
                snprintf(metr_str, sizeof(metr_str), "%6u", am->route_metric);
 
-       vty_out(vty, "%-9s %-15s %-15s %-15s %-3s %-4s %-6s %-15s\n",
+       vty_out(vty, "%-16s %-15s %-15s %-15s %-3s %-4s %-6s %-15s\n",
                ch->interface->name, inet_ntoa(ifaddr), ch_src_str, ch_grp_str,
                am->rpt_bit_flag ? "yes" : "no", pref_str, metr_str, addr_str);
 }
@@ -362,7 +363,7 @@ static void pim_show_assert_winner_metric(struct pim_instance *pim,
        struct interface *ifp;
 
        vty_out(vty,
-               "Interface Address         Source          Group           RPT Pref Metric Address        \n");
+               "Interface        Address         Source          Group           RPT Pref Metric Address        \n");
 
        FOR_ALL_INTERFACES (pim->vrf, ifp) {
                pim_ifp = ifp->info;
@@ -462,7 +463,7 @@ static void pim_show_membership(struct pim_instance *pim, struct vty *vty,
                                             json, JSON_C_TO_STRING_PRETTY));
        } else {
                vty_out(vty,
-                       "Interface  Address          Source           Group            Membership\n");
+                       "Interface         Address          Source           Group            Membership\n");
 
                /*
                 * Example of the json data we are traversing
@@ -499,7 +500,7 @@ static void pim_show_membership(struct pim_instance *pim, struct vty *vty,
                                type = json_object_get_type(if_field_val);
 
                                if (type == json_type_object) {
-                                       vty_out(vty, "%-9s  ", key);
+                                       vty_out(vty, "%-16s  ", key);
 
                                        json_object_object_get_ex(
                                                val, "address", &json_tmp);
@@ -566,7 +567,7 @@ static void igmp_show_interfaces(struct pim_instance *pim, struct vty *vty,
                json = json_object_new_object();
        else
                vty_out(vty,
-                       "Interface  State          Address  V  Querier  Query Timer    Uptime\n");
+                       "Interface         State          Address  V  Querier  Query Timer    Uptime\n");
 
        FOR_ALL_INTERFACES (pim->vrf, ifp) {
                struct pim_interface *pim_ifp;
@@ -614,7 +615,7 @@ static void igmp_show_interfaces(struct pim_instance *pim, struct vty *vty,
                                }
                        } else {
                                vty_out(vty,
-                                       "%-9s  %5s  %15s  %d  %7s  %11s  %8s\n",
+                                       "%-16s  %5s  %15s  %d  %7s  %11s  %8s\n",
                                        ifp->name,
                                        if_is_up(ifp)
                                                ? (igmp->mtrace_only ? "mtrc"
@@ -854,7 +855,7 @@ static void igmp_show_interface_join(struct pim_instance *pim, struct vty *vty)
        now = pim_time_monotonic_sec();
 
        vty_out(vty,
-               "Interface Address         Source          Group           Socket Uptime  \n");
+               "Interface        Address         Source          Group           Socket Uptime  \n");
 
        FOR_ALL_INTERFACES (pim->vrf, ifp) {
                struct pim_interface *pim_ifp;
@@ -888,7 +889,7 @@ static void igmp_show_interface_join(struct pim_instance *pim, struct vty *vty)
                        pim_inet4_dump("<src?>", ij->source_addr, source_str,
                                       sizeof(source_str));
 
-                       vty_out(vty, "%-9s %-15s %-15s %-15s %6d %8s\n",
+                       vty_out(vty, "%-16s %-15s %-15s %-15s %6d %8s\n",
                                ifp->name, pri_addr_str, source_str, group_str,
                                ij->sock_fd, uptime);
                } /* for (pim_ifp->igmp_join_list) */
@@ -1206,6 +1207,8 @@ static void pim_show_interfaces_single(struct pim_instance *pim,
                        print_header = 1;
                        for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, upnode,
                                                  up)) {
+                               if (!up->rpf.source_nexthop.interface)
+                                       continue;
 
                                if (strcmp(ifp->name,
                                           up->rpf.source_nexthop
@@ -1421,11 +1424,11 @@ static void pim_show_interfaces(struct pim_instance *pim, struct vty *vty,
                                             json, JSON_C_TO_STRING_PRETTY));
        } else {
                vty_out(vty,
-                       "Interface  State          Address  PIM Nbrs           PIM DR  FHR IfChannels\n");
+                       "Interface         State          Address  PIM Nbrs           PIM DR  FHR IfChannels\n");
 
                json_object_object_foreach(json, key, val)
                {
-                       vty_out(vty, "%-9s  ", key);
+                       vty_out(vty, "%-16s  ", key);
 
                        json_object_object_get_ex(val, "state", &json_tmp);
                        vty_out(vty, "%5s  ", json_object_get_string(json_tmp));
@@ -1474,12 +1477,13 @@ static void pim_show_interface_traffic(struct pim_instance *pim,
                json = json_object_new_object();
        else {
                vty_out(vty, "\n");
-               vty_out(vty, "%-12s%-17s%-17s%-17s%-17s%-17s%-17s\n",
-                       "Interface", "    HELLO", "    JOIN", "   PRUNE",
-                       "   REGISTER", "  REGISTER-STOP", "  ASSERT");
-               vty_out(vty, "%-10s%-18s%-17s%-17s%-17s%-17s%-17s\n", "",
-                       "      Rx/Tx", "     Rx/Tx", "    Rx/Tx", "    Rx/Tx",
-                       "     Rx/Tx", "    Rx/Tx");
+               vty_out(vty, "%-16s%-17s%-17s%-17s%-17s%-17s%-17s\n",
+                       "Interface", "       HELLO", "       JOIN",
+                       "      PRUNE", "   REGISTER", "REGISTER-STOP",
+                       "  ASSERT");
+               vty_out(vty, "%-16s%-17s%-17s%-17s%-17s%-17s%-17s\n", "",
+                       "       Rx/Tx", "       Rx/Tx", "      Rx/Tx",
+                       "     Rx/Tx", "    Rx/Tx", "   Rx/Tx");
                vty_out(vty,
                        "---------------------------------------------------------------------------------------------------------------\n");
        }
@@ -1519,7 +1523,7 @@ static void pim_show_interface_traffic(struct pim_instance *pim,
                        json_object_object_add(json, ifp->name, json_row);
                } else {
                        vty_out(vty,
-                               "%-10s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u \n",
+                               "%-16s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u \n",
                                ifp->name, pim_ifp->pim_ifstat_hello_recv,
                                pim_ifp->pim_ifstat_hello_sent,
                                pim_ifp->pim_ifstat_join_recv,
@@ -1555,14 +1559,14 @@ static void pim_show_interface_traffic_single(struct pim_instance *pim,
                json = json_object_new_object();
        else {
                vty_out(vty, "\n");
-               vty_out(vty, "%-12s%-17s%-17s%-17s%-17s%-17s%-17s\n",
+               vty_out(vty, "%-16s%-17s%-17s%-17s%-17s%-17s%-17s\n",
                        "Interface", "    HELLO", "    JOIN", "   PRUNE",
                        "   REGISTER", "  REGISTER-STOP", "  ASSERT");
-               vty_out(vty, "%-10s%-18s%-17s%-17s%-17s%-17s%-17s\n", "",
+               vty_out(vty, "%-14s%-18s%-17s%-17s%-17s%-17s%-17s\n", "",
                        "      Rx/Tx", "     Rx/Tx", "    Rx/Tx", "    Rx/Tx",
                        "     Rx/Tx", "    Rx/Tx");
                vty_out(vty,
-                       "---------------------------------------------------------------------------------------------------------------\n");
+                       "---------------------------------------------------------------------------------------------------------------------\n");
        }
 
        FOR_ALL_INTERFACES (pim->vrf, ifp) {
@@ -1605,7 +1609,7 @@ static void pim_show_interface_traffic_single(struct pim_instance *pim,
                        json_object_object_add(json, ifp->name, json_row);
                } else {
                        vty_out(vty,
-                               "%-10s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u \n",
+                               "%-16s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u \n",
                                ifp->name, pim_ifp->pim_ifstat_hello_recv,
                                pim_ifp->pim_ifstat_hello_sent,
                                pim_ifp->pim_ifstat_join_recv,
@@ -1687,7 +1691,7 @@ static void pim_show_join_helper(struct vty *vty, struct pim_interface *pim_ifp,
                } else
                        json_object_object_add(json_grp, ch_src_str, json_row);
        } else {
-               vty_out(vty, "%-9s %-15s %-15s %-15s %-10s %8s %-6s %5s\n",
+               vty_out(vty, "%-16s %-15s %-15s %-15s %-10s %8s %-6s %5s\n",
                        ch->interface->name, inet_ntoa(ifaddr), ch_src_str,
                        ch_grp_str,
                        pim_ifchannel_ifjoin_name(ch->ifjoin_state, ch->flags),
@@ -1695,7 +1699,8 @@ static void pim_show_join_helper(struct vty *vty, struct pim_interface *pim_ifp,
        }
 }
 
-static void pim_show_join(struct pim_instance *pim, struct vty *vty, bool uj)
+static void pim_show_join(struct pim_instance *pim, struct vty *vty,
+                         struct prefix_sg *sg, bool uj)
 {
        struct pim_interface *pim_ifp;
        struct pim_ifchannel *ch;
@@ -1709,7 +1714,7 @@ static void pim_show_join(struct pim_instance *pim, struct vty *vty, bool uj)
                json = json_object_new_object();
        else
                vty_out(vty,
-                       "Interface Address         Source          Group           State      Uptime   Expire Prune\n");
+                       "Interface        Address         Source          Group           State      Uptime   Expire Prune\n");
 
        FOR_ALL_INTERFACES (pim->vrf, ifp) {
                pim_ifp = ifp->info;
@@ -1717,6 +1722,12 @@ static void pim_show_join(struct pim_instance *pim, struct vty *vty, bool uj)
                        continue;
 
                RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
+                       if (sg->grp.s_addr != 0
+                           && sg->grp.s_addr != ch->sg.grp.s_addr)
+                               continue;
+                       if (sg->src.s_addr != 0
+                           && sg->src.s_addr != ch->sg.src.s_addr)
+                       continue;
                        pim_show_join_helper(vty, pim_ifp, ch, json, now, uj);
                } /* scan interface channels */
        }
@@ -1955,9 +1966,9 @@ static void pim_show_state(struct pim_instance *pim, struct vty *vty,
                json = json_object_new_object();
        } else {
                vty_out(vty,
-                       "Codes: J -> Pim Join, I -> IGMP Report, S -> Source, * -> Inherited from (*,G)");
+                       "Codes: J -> Pim Join, I -> IGMP Report, S -> Source, * -> Inherited from (*,G), V -> VxLAN");
                vty_out(vty,
-                       "\nInstalled Source           Group            IIF      OIL\n");
+                       "\nInstalled Source           Group            IIF               OIL\n");
        }
 
        for (ALL_LIST_ELEMENTS_RO(pim->channel_oil_list, node, c_oil)) {
@@ -2040,9 +2051,8 @@ static void pim_show_state(struct pim_instance *pim, struct vty *vty,
                                                    c_oil->cc.wrong_if);
                        }
                } else {
-                       vty_out(vty, "%-9d %-15s  %-15s  %-7s  ",
-                               c_oil->installed, src_str, grp_str,
-                               in_ifname);
+                       vty_out(vty, "%-9d %-15s  %-15s  %-16s  ",
+                               c_oil->installed, src_str, grp_str, in_ifname);
                }
 
                for (oif_vif_index = 0; oif_vif_index < MAXVIFS;
@@ -2085,7 +2095,7 @@ static void pim_show_state(struct pim_instance *pim, struct vty *vty,
                        } else {
                                if (first_oif) {
                                        first_oif = 0;
-                                       vty_out(vty, "%s(%c%c%c%c)", out_ifname,
+                                       vty_out(vty, "%s(%c%c%c%c%c)", out_ifname,
                                                (c_oil->oif_flags[oif_vif_index]
                                                 & PIM_OIF_FLAG_PROTO_IGMP)
                                                        ? 'I'
@@ -2094,6 +2104,10 @@ static void pim_show_state(struct pim_instance *pim, struct vty *vty,
                                                 & PIM_OIF_FLAG_PROTO_PIM)
                                                        ? 'J'
                                                        : ' ',
+                                               (c_oil->oif_flags[oif_vif_index]
+                                                & PIM_OIF_FLAG_PROTO_VXLAN)
+                                                       ? 'V'
+                                                       : ' ',
                                                (c_oil->oif_flags[oif_vif_index]
                                                 & PIM_OIF_FLAG_PROTO_SOURCE)
                                                        ? 'S'
@@ -2103,7 +2117,7 @@ static void pim_show_state(struct pim_instance *pim, struct vty *vty,
                                                        ? '*'
                                                        : ' ');
                                } else
-                                       vty_out(vty, ", %s(%c%c%c%c)",
+                                       vty_out(vty, ", %s(%c%c%c%c%c)",
                                                out_ifname,
                                                (c_oil->oif_flags[oif_vif_index]
                                                 & PIM_OIF_FLAG_PROTO_IGMP)
@@ -2113,6 +2127,10 @@ static void pim_show_state(struct pim_instance *pim, struct vty *vty,
                                                 & PIM_OIF_FLAG_PROTO_PIM)
                                                        ? 'J'
                                                        : ' ',
+                                               (c_oil->oif_flags[oif_vif_index]
+                                                & PIM_OIF_FLAG_PROTO_VXLAN)
+                                                       ? 'V'
+                                                       : ' ',
                                                (c_oil->oif_flags[oif_vif_index]
                                                 & PIM_OIF_FLAG_PROTO_SOURCE)
                                                        ? 'S'
@@ -2159,7 +2177,7 @@ static void pim_show_neighbors(struct pim_instance *pim, struct vty *vty,
                json = json_object_new_object();
        } else {
                vty_out(vty,
-                       "Interface         Neighbor    Uptime  Holdtime  DR Pri\n");
+                       "Interface                Neighbor    Uptime  Holdtime  DR Pri\n");
        }
 
        FOR_ALL_INTERFACES (pim->vrf, ifp) {
@@ -2201,7 +2219,7 @@ static void pim_show_neighbors(struct pim_instance *pim, struct vty *vty,
                                                       neigh_src_str, json_row);
 
                        } else {
-                               vty_out(vty, "%-9s  %15s  %8s  %8s  %6d\n",
+                               vty_out(vty, "%-16s  %15s  %8s  %8s  %6d\n",
                                        ifp->name, neigh_src_str, uptime,
                                        expire, neigh->dr_priority);
                        }
@@ -2226,7 +2244,7 @@ static void pim_show_neighbors_secondary(struct pim_instance *pim,
        struct interface *ifp;
 
        vty_out(vty,
-               "Interface Address         Neighbor        Secondary      \n");
+               "Interface        Address         Neighbor        Secondary      \n");
 
        FOR_ALL_INTERFACES (pim->vrf, ifp) {
                struct pim_interface *pim_ifp;
@@ -2263,7 +2281,7 @@ static void pim_show_neighbors_secondary(struct pim_instance *pim,
                                prefix2str(p, neigh_sec_str,
                                           sizeof(neigh_sec_str));
 
-                               vty_out(vty, "%-9s %-15s %-15s %-15s\n",
+                               vty_out(vty, "%-16s %-15s %-15s %-15s\n",
                                        ifp->name, inet_ntoa(ifaddr),
                                        neigh_src_str, neigh_sec_str);
                        }
@@ -2295,6 +2313,41 @@ static void json_object_pim_upstream_add(json_object *json,
        /* XXX: need to print ths flag in the plain text display as well */
        if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_MSDP)
                json_object_boolean_true_add(json, "sourceMsdp");
+
+       if (up->flags & PIM_UPSTREAM_FLAG_MASK_SEND_SG_RPT_PRUNE)
+               json_object_boolean_true_add(json, "sendSGRptPrune");
+
+       if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_LHR)
+               json_object_boolean_true_add(json, "lastHopRouter");
+
+       if (up->flags & PIM_UPSTREAM_FLAG_MASK_DISABLE_KAT_EXPIRY)
+               json_object_boolean_true_add(json, "disableKATExpiry");
+
+       if (up->flags & PIM_UPSTREAM_FLAG_MASK_STATIC_IIF)
+               json_object_boolean_true_add(json, "staticIncomingInterface");
+
+       if (up->flags & PIM_UPSTREAM_FLAG_MASK_ALLOW_IIF_IN_OIL)
+               json_object_boolean_true_add(json,
+                                            "allowIncomingInterfaceinOil");
+
+       if (up->flags & PIM_UPSTREAM_FLAG_MASK_NO_PIMREG_DATA)
+               json_object_boolean_true_add(json, "noPimRegistrationData");
+
+       if (up->flags & PIM_UPSTREAM_FLAG_MASK_FORCE_PIMREG)
+               json_object_boolean_true_add(json, "forcePimRegistration");
+
+       if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_ORIG)
+               json_object_boolean_true_add(json, "sourceVxlanOrigination");
+
+       if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_TERM)
+               json_object_boolean_true_add(json, "sourceVxlanTermination");
+
+       if (up->flags & PIM_UPSTREAM_FLAG_MASK_MLAG_VXLAN)
+               json_object_boolean_true_add(json, "mlagVxlan");
+
+       if (up->flags & PIM_UPSTREAM_FLAG_MASK_MLAG_NON_DF)
+               json_object_boolean_true_add(json,
+                                            "mlagNonDesignatedForwarder");
 }
 
 static const char *
@@ -2335,7 +2388,7 @@ static const char *pim_reg_state2brief_str(enum pim_reg_state reg_state,
 }
 
 static void pim_show_upstream(struct pim_instance *pim, struct vty *vty,
-                             bool uj)
+                             struct prefix_sg *sg, bool uj)
 {
        struct listnode *upnode;
        struct pim_upstream *up;
@@ -2350,7 +2403,7 @@ static void pim_show_upstream(struct pim_instance *pim, struct vty *vty,
                json = json_object_new_object();
        else
                vty_out(vty,
-                       "Iif       Source          Group           State       Uptime   JoinTimer RSTimer   KATimer   RefCnt\n");
+                       "Iif             Source          Group           State       Uptime   JoinTimer RSTimer   KATimer   RefCnt\n");
 
        for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, upnode, up)) {
                char src_str[INET_ADDRSTRLEN];
@@ -2362,6 +2415,11 @@ static void pim_show_upstream(struct pim_instance *pim, struct vty *vty,
                char msdp_reg_timer[10];
                char state_str[PIM_REG_STATE_STR_LEN];
 
+               if (sg->grp.s_addr != 0 && sg->grp.s_addr != up->sg.grp.s_addr)
+                       continue;
+               if (sg->src.s_addr != 0 && sg->src.s_addr != up->sg.src.s_addr)
+                       continue;
+
                pim_inet4_dump("<src?>", up->sg.src, src_str, sizeof(src_str));
                pim_inet4_dump("<grp?>", up->sg.grp, grp_str, sizeof(grp_str));
                pim_time_uptime(uptime, sizeof(uptime),
@@ -2465,7 +2523,7 @@ static void pim_show_upstream(struct pim_instance *pim, struct vty *vty,
                        json_object_object_add(json_group, src_str, json_row);
                } else {
                        vty_out(vty,
-                               "%-10s%-15s %-15s %-11s %-8s %-9s %-9s %-9s %6d\n",
+                               "%-16s%-15s %-15s %-11s %-8s %-9s %-9s %-9s %6d\n",
                                up->rpf.source_nexthop.interface
                                    ? up->rpf.source_nexthop.interface->name
                                    : "Unknown",
@@ -2527,7 +2585,7 @@ static void pim_show_join_desired_helper(struct pim_instance *pim,
                json_object_object_add(json_group, src_str, json_row);
 
        } else {
-               vty_out(vty, "%-9s %-15s %-15s %-10s %-5s %-10s %-11s %-6s\n",
+               vty_out(vty, "%-16s %-15s %-15s %-10s %-5s %-10s %-11s %-6s\n",
                        ch->interface->name, src_str, grp_str,
                        pim_macro_ch_lost_assert(ch) ? "yes" : "no",
                        pim_macro_chisin_joins(ch) ? "yes" : "no",
@@ -2553,7 +2611,7 @@ static void pim_show_join_desired(struct pim_instance *pim, struct vty *vty,
                json = json_object_new_object();
        else
                vty_out(vty,
-                       "Interface Source          Group           LostAssert Joins PimInclude JoinDesired EvalJD\n");
+                       "Interface        Source          Group           LostAssert Joins PimInclude JoinDesired EvalJD\n");
 
        /* scan per-interface (S,G) state */
        FOR_ALL_INTERFACES (pim->vrf, ifp) {
@@ -2589,7 +2647,7 @@ static void pim_show_upstream_rpf(struct pim_instance *pim, struct vty *vty,
                json = json_object_new_object();
        else
                vty_out(vty,
-                       "Source          Group           RpfIface RibNextHop      RpfAddress     \n");
+                       "Source          Group           RpfIface         RibNextHop      RpfAddress     \n");
 
        for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, upnode, up)) {
                char src_str[INET_ADDRSTRLEN];
@@ -2632,7 +2690,7 @@ static void pim_show_upstream_rpf(struct pim_instance *pim, struct vty *vty,
                                               rpf_addr_str);
                        json_object_object_add(json_group, src_str, json_row);
                } else {
-                       vty_out(vty, "%-15s %-15s %-8s %-15s %-15s\n", src_str,
+                       vty_out(vty, "%-15s %-15s %-16s %-15s %-15s\n", src_str,
                                grp_str, rpf_ifname, rpf_nexthop_str,
                                rpf_addr_str);
                }
@@ -2726,7 +2784,7 @@ static void pim_show_rpf(struct pim_instance *pim, struct vty *vty, bool uj)
                show_rpf_refresh_stats(vty, pim, now, json);
                vty_out(vty, "\n");
                vty_out(vty,
-                       "Source          Group           RpfIface RpfAddress      RibNextHop      Metric Pref\n");
+                       "Source          Group           RpfIface         RpfAddress      RibNextHop      Metric Pref\n");
        }
 
        for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, up_node, up)) {
@@ -2774,7 +2832,7 @@ static void pim_show_rpf(struct pim_instance *pim, struct vty *vty, bool uj)
                        json_object_object_add(json_group, src_str, json_row);
 
                } else {
-                       vty_out(vty, "%-15s %-15s %-8s %-15s %-15s %6d %4d\n",
+                       vty_out(vty, "%-15s %-15s %-16s %-15s %-15s %6d %4d\n",
                                src_str, grp_str, rpf_ifname, rpf_addr_str,
                                rib_nexthop_str,
                                rpf->source_nexthop.mrib_route_metric,
@@ -2809,7 +2867,7 @@ static int pim_print_pnc_cache_walkcb(struct hash_bucket *bucket, void *arg)
                ifp = if_lookup_by_index(first_ifindex, pim->vrf_id);
 
                vty_out(vty, "%-15s ", inet_ntoa(pnc->rpf.rpf_addr.u.prefix4));
-               vty_out(vty, "%-14s ", ifp ? ifp->name : "NULL");
+               vty_out(vty, "%-16s ", ifp ? ifp->name : "NULL");
                vty_out(vty, "%s ", inet_ntoa(nh_node->gate.ipv4));
                vty_out(vty, "\n");
        }
@@ -2824,8 +2882,8 @@ static void pim_show_nexthop(struct pim_instance *pim, struct vty *vty)
        cwd.pim = pim;
        vty_out(vty, "Number of registered addresses: %lu\n",
                pim->rpf_hash->count);
-       vty_out(vty, "Address         Interface      Nexthop\n");
-       vty_out(vty, "-------------------------------------------\n");
+       vty_out(vty, "Address         Interface        Nexthop\n");
+       vty_out(vty, "---------------------------------------------\n");
 
        hash_walk(pim->rpf_hash, pim_print_pnc_cache_walkcb, &cwd);
 }
@@ -2844,7 +2902,7 @@ static void igmp_show_groups(struct pim_instance *pim, struct vty *vty, bool uj)
                json = json_object_new_object();
        else
                vty_out(vty,
-                       "Interface Address         Group           Mode Timer    Srcs V Uptime  \n");
+                       "Interface        Address         Group           Mode Timer    Srcs V Uptime  \n");
 
        /* scan interfaces */
        FOR_ALL_INTERFACES (pim->vrf, ifp) {
@@ -2924,7 +2982,7 @@ static void igmp_show_groups(struct pim_instance *pim, struct vty *vty, bool uj)
 
                                } else {
                                        vty_out(vty,
-                                               "%-9s %-15s %-15s %4s %8s %4d %d %8s\n",
+                                               "%-16s %-15s %-15s %4s %8s %4d %d %8s\n",
                                                ifp->name, ifaddr_str,
                                                group_str,
                                                grp->igmp_version == 3
@@ -2956,7 +3014,7 @@ static void igmp_show_group_retransmission(struct pim_instance *pim,
        struct interface *ifp;
 
        vty_out(vty,
-               "Interface Address         Group           RetTimer Counter RetSrcs\n");
+               "Interface        Address         Group           RetTimer Counter RetSrcs\n");
 
        /* scan interfaces */
        FOR_ALL_INTERFACES (pim->vrf, ifp) {
@@ -3004,7 +3062,7 @@ static void igmp_show_group_retransmission(struct pim_instance *pim,
                                        }
                                }
 
-                               vty_out(vty, "%-9s %-15s %-15s %-8s %7d %7d\n",
+                               vty_out(vty, "%-16s %-15s %-15s %-8s %7d %7d\n",
                                        ifp->name, ifaddr_str, group_str,
                                        grp_retr_mmss,
                                        grp->group_specific_query_retransmit_count,
@@ -3023,7 +3081,7 @@ static void igmp_show_sources(struct pim_instance *pim, struct vty *vty)
        now = pim_time_monotonic_sec();
 
        vty_out(vty,
-               "Interface Address         Group           Source          Timer Fwd Uptime  \n");
+               "Interface        Address         Group           Source          Timer Fwd Uptime  \n");
 
        /* scan interfaces */
        FOR_ALL_INTERFACES (pim->vrf, ifp) {
@@ -3075,7 +3133,7 @@ static void igmp_show_sources(struct pim_instance *pim, struct vty *vty)
                                                now - src->source_creation);
 
                                        vty_out(vty,
-                                               "%-9s %-15s %-15s %-15s %5s %3s %8s\n",
+                                               "%-16s %-15s %-15s %-15s %5s %3s %8s\n",
                                                ifp->name, ifaddr_str,
                                                group_str, source_str, mmss,
                                                IGMP_SOURCE_TEST_FORWARDING(
@@ -3096,7 +3154,7 @@ static void igmp_show_source_retransmission(struct pim_instance *pim,
        struct interface *ifp;
 
        vty_out(vty,
-               "Interface Address         Group           Source          Counter\n");
+               "Interface        Address         Group           Source          Counter\n");
 
        /* scan interfaces */
        FOR_ALL_INTERFACES (pim->vrf, ifp) {
@@ -3138,7 +3196,7 @@ static void igmp_show_source_retransmission(struct pim_instance *pim,
                                                source_str, sizeof(source_str));
 
                                        vty_out(vty,
-                                               "%-9s %-15s %-15s %-15s %7d\n",
+                                               "%-16s %-15s %-15s %-15s %7d\n",
                                                ifp->name, ifaddr_str,
                                                group_str, source_str,
                                                src->source_query_retransmit_count);
@@ -3777,24 +3835,45 @@ DEFUN (show_ip_pim_interface_vrf_all,
        return CMD_SUCCESS;
 }
 
-DEFUN (show_ip_pim_join,
+DEFPY (show_ip_pim_join,
        show_ip_pim_join_cmd,
-       "show ip pim [vrf NAME] join [json]",
+       "show ip pim [vrf NAME] join [A.B.C.D$s_or_g [A.B.C.D$g]] [json$json]",
        SHOW_STR
        IP_STR
        PIM_STR
        VRF_CMD_HELP_STR
        "PIM interface join information\n"
+       "The Source or Group\n"
+       "The Group\n"
        JSON_STR)
 {
-       int idx = 2;
-       struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
-       bool uj = use_json(argc, argv);
+       struct prefix_sg sg = {0};
+       struct vrf *v;
+       bool uj = !!json;
+       struct pim_instance *pim;
 
-       if (!vrf)
+       v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
+
+       if (!v) {
+               vty_out(vty, "%% Vrf specified: %s does not exist\n", vrf);
                return CMD_WARNING;
+       }
+       pim = pim_get_pim_instance(v->vrf_id);
 
-       pim_show_join(vrf->info, vty, uj);
+       if (!pim) {
+               vty_out(vty, "%% Unable to find pim instance\n");
+               return CMD_WARNING;
+       }
+
+       if (s_or_g.s_addr != 0) {
+               if (g.s_addr != 0) {
+                       sg.src = s_or_g;
+                       sg.grp = g;
+               } else
+                       sg.grp = s_or_g;
+       }
+
+       pim_show_join(pim, vty, &sg, uj);
 
        return CMD_SUCCESS;
 }
@@ -3809,6 +3888,7 @@ DEFUN (show_ip_pim_join_vrf_all,
        "PIM interface join information\n"
        JSON_STR)
 {
+       struct prefix_sg sg = {0};
        bool uj = use_json(argc, argv);
        struct vrf *vrf;
        bool first = true;
@@ -3823,7 +3903,7 @@ DEFUN (show_ip_pim_join_vrf_all,
                        first = false;
                } else
                        vty_out(vty, "VRF: %s\n", vrf->name);
-               pim_show_join(vrf->info, vty, uj);
+               pim_show_join(vrf->info, vty, &sg, uj);
        }
        if (uj)
                vty_out(vty, "}\n");
@@ -4022,24 +4102,44 @@ DEFUN (show_ip_pim_state_vrf_all,
        return CMD_SUCCESS;
 }
 
-DEFUN (show_ip_pim_upstream,
+DEFPY (show_ip_pim_upstream,
        show_ip_pim_upstream_cmd,
-       "show ip pim [vrf NAME] upstream [json]",
+       "show ip pim [vrf NAME] upstream [A.B.C.D$s_or_g [A.B.C.D$g]] [json$json]",
        SHOW_STR
        IP_STR
        PIM_STR
        VRF_CMD_HELP_STR
        "PIM upstream information\n"
+       "The Source or Group\n"
+       "The Group\n"
        JSON_STR)
 {
-       int idx = 2;
-       struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
-       bool uj = use_json(argc, argv);
+       struct prefix_sg sg = {0};
+       struct vrf *v;
+       bool uj = !!json;
+       struct pim_instance *pim;
 
-       if (!vrf)
+       v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
+
+       if (!v) {
+               vty_out(vty, "%% Vrf specified: %s does not exist\n", vrf);
                return CMD_WARNING;
+       }
+       pim = pim_get_pim_instance(v->vrf_id);
 
-       pim_show_upstream(vrf->info, vty, uj);
+       if (!pim) {
+               vty_out(vty, "%% Unable to find pim instance\n");
+               return CMD_WARNING;
+       }
+
+       if (s_or_g.s_addr != 0) {
+               if (g.s_addr != 0) {
+                       sg.src = s_or_g;
+                       sg.grp = g;
+               } else
+                       sg.grp = s_or_g;
+       }
+       pim_show_upstream(pim, vty, &sg, uj);
 
        return CMD_SUCCESS;
 }
@@ -4054,6 +4154,7 @@ DEFUN (show_ip_pim_upstream_vrf_all,
        "PIM upstream information\n"
        JSON_STR)
 {
+       struct prefix_sg sg = {0};
        bool uj = use_json(argc, argv);
        struct vrf *vrf;
        bool first = true;
@@ -4068,7 +4169,7 @@ DEFUN (show_ip_pim_upstream_vrf_all,
                        first = false;
                } else
                        vty_out(vty, "VRF: %s\n", vrf->name);
-               pim_show_upstream(vrf->info, vty, uj);
+               pim_show_upstream(vrf->info, vty, &sg, uj);
        }
 
        return CMD_SUCCESS;
@@ -4257,7 +4358,6 @@ DEFUN (show_ip_pim_nexthop_lookup,
        "Source/RP address\n"
        "Multicast Group address\n")
 {
-       struct pim_nexthop_cache *pnc = NULL;
        struct prefix nht_p;
        int result = 0;
        struct in_addr src_addr, grp_addr;
@@ -4269,7 +4369,6 @@ DEFUN (show_ip_pim_nexthop_lookup,
        char grp_str[PREFIX_STRLEN];
        int idx = 2;
        struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
-       struct pim_rpf rpf;
 
        if (!vrf)
                return CMD_WARNING;
@@ -4315,18 +4414,7 @@ DEFUN (show_ip_pim_nexthop_lookup,
        grp.u.prefix4 = grp_addr;
        memset(&nexthop, 0, sizeof(nexthop));
 
-       memset(&rpf, 0, sizeof(struct pim_rpf));
-       rpf.rpf_addr.family = AF_INET;
-       rpf.rpf_addr.prefixlen = IPV4_MAX_BITLEN;
-       rpf.rpf_addr.u.prefix4 = vif_source;
-
-       pnc = pim_nexthop_cache_find(vrf->info, &rpf);
-       if (pnc)
-               result = pim_ecmp_nexthop_search(vrf->info, pnc, &nexthop,
-                                                &nht_p, &grp, 0);
-       else
-               result = pim_ecmp_nexthop_lookup(vrf->info, &nexthop, &nht_p,
-                                                &grp, 0);
+       result = pim_ecmp_nexthop_lookup(vrf->info, &nexthop, &nht_p, &grp, 0);
 
        if (!result) {
                vty_out(vty,
@@ -4378,7 +4466,7 @@ static void show_multicast_interfaces(struct pim_instance *pim, struct vty *vty)
        vty_out(vty, "\n");
 
        vty_out(vty,
-               "Interface Address            ifi Vif  PktsIn PktsOut    BytesIn   BytesOut\n");
+               "Interface        Address            ifi Vif  PktsIn PktsOut    BytesIn   BytesOut\n");
 
        FOR_ALL_INTERFACES (pim->vrf, ifp) {
                struct pim_interface *pim_ifp;
@@ -4403,7 +4491,7 @@ static void show_multicast_interfaces(struct pim_instance *pim, struct vty *vty)
 
                ifaddr = pim_ifp->primary_address;
 
-               vty_out(vty, "%-12s %-15s %3d %3d %7lu %7lu %10lu %10lu\n",
+               vty_out(vty, "%-16s %-15s %3d %3d %7lu %7lu %10lu %10lu\n",
                        ifp->name, inet_ntoa(ifaddr), ifp->ifindex,
                        pim_ifp->mroute_vif_index, (unsigned long)vreq.icount,
                        (unsigned long)vreq.ocount, (unsigned long)vreq.ibytes,
@@ -4506,8 +4594,8 @@ DEFUN (show_ip_multicast_vrf_all,
        return CMD_SUCCESS;
 }
 
-static void show_mroute(struct pim_instance *pim, struct vty *vty, bool fill,
-                       bool uj)
+static void show_mroute(struct pim_instance *pim, struct vty *vty,
+                       struct prefix_sg *sg, bool fill, bool uj)
 {
        struct listnode *node;
        struct channel_oil *c_oil;
@@ -4532,7 +4620,7 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty, bool fill,
                json = json_object_new_object();
        } else {
                vty_out(vty,
-                       "Source          Group           Proto  Input      Output     TTL  Uptime\n");
+                       "Source          Group           Proto  Input            Output           TTL  Uptime\n");
        }
 
        now = pim_time_monotonic_sec();
@@ -4544,6 +4632,13 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty, bool fill,
                if (!c_oil->installed && !uj)
                        continue;
 
+               if (sg->grp.s_addr != 0 &&
+                   sg->grp.s_addr != c_oil->oil.mfcc_mcastgrp.s_addr)
+                       continue;
+               if (sg->src.s_addr != 0 &&
+                   sg->src.s_addr != c_oil->oil.mfcc_origin.s_addr)
+                       continue;
+
                pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, grp_str,
                               sizeof(grp_str));
                pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, src_str,
@@ -4594,7 +4689,7 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty, bool fill,
                for (oif_vif_index = 0; oif_vif_index < MAXVIFS;
                     ++oif_vif_index) {
                        struct interface *ifp_out;
-                       char oif_uptime[10];
+                       char mroute_uptime[10];
                        int ttl;
 
                        ttl = c_oil->oil.mfcc_ttls[oif_vif_index];
@@ -4603,8 +4698,8 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty, bool fill,
 
                        ifp_out = pim_if_find_by_vif_index(pim, oif_vif_index);
                        pim_time_uptime(
-                               oif_uptime, sizeof(oif_uptime),
-                               now - c_oil->oif_creation[oif_vif_index]);
+                               mroute_uptime, sizeof(mroute_uptime),
+                               now - c_oil->mroute_creation);
                        found_oif = 1;
 
                        if (ifp_out)
@@ -4629,6 +4724,11 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty, bool fill,
                                        json_object_boolean_true_add(
                                                json_ifp_out, "protocolIgmp");
 
+                               if (c_oil->oif_flags[oif_vif_index]
+                                   & PIM_OIF_FLAG_PROTO_VXLAN)
+                                       json_object_boolean_true_add(
+                                               json_ifp_out, "protocolVxlan");
+
                                if (c_oil->oif_flags[oif_vif_index]
                                    & PIM_OIF_FLAG_PROTO_SOURCE)
                                        json_object_boolean_true_add(
@@ -4652,7 +4752,7 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty, bool fill,
                                                    oif_vif_index);
                                json_object_int_add(json_ifp_out, "ttl", ttl);
                                json_object_string_add(json_ifp_out, "upTime",
-                                                      oif_uptime);
+                                                      mroute_uptime);
                                if (!json_oil) {
                                        json_oil = json_object_new_object();
                                        json_object_object_add(json_source,
@@ -4671,6 +4771,11 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty, bool fill,
                                        strcpy(proto, "IGMP");
                                }
 
+                               if (c_oil->oif_flags[oif_vif_index]
+                                   & PIM_OIF_FLAG_PROTO_VXLAN) {
+                                       strcpy(proto, "VxLAN");
+                               }
+
                                if (c_oil->oif_flags[oif_vif_index]
                                    & PIM_OIF_FLAG_PROTO_SOURCE) {
                                        strcpy(proto, "SRC");
@@ -4682,9 +4787,9 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty, bool fill,
                                }
 
                                vty_out(vty,
-                                       "%-15s %-15s %-6s %-10s %-10s %-3d  %8s\n",
+                                       "%-15s %-15s %-6s %-16s %-16s %-3d  %8s\n",
                                        src_str, grp_str, proto, in_ifname,
-                                       out_ifname, ttl, oif_uptime);
+                                       out_ifname, ttl, mroute_uptime);
 
                                if (first) {
                                        src_str[0] = '\0';
@@ -4696,7 +4801,7 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty, bool fill,
                }
 
                if (!uj && !found_oif) {
-                       vty_out(vty, "%-15s %-15s %-6s %-10s %-10s %-3d  %8s\n",
+                       vty_out(vty, "%-15s %-15s %-6s %-16s %-16s %-3d  %8s\n",
                                src_str, grp_str, "none", in_ifname, "none", 0,
                                "--:--:--");
                }
@@ -4803,7 +4908,7 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty, bool fill,
                                                       json_ifp_out);
                        } else {
                                vty_out(vty,
-                                       "%-15s %-15s %-6s %-10s %-10s %-3d  %8s %s\n",
+                                       "%-15s %-15s %-6s %-16s %-16s %-3d  %8s %s\n",
                                        src_str, grp_str, proto, in_ifname,
                                        out_ifname, ttl, oif_uptime,
                                        pim->vrf->name);
@@ -4818,7 +4923,7 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty, bool fill,
 
                if (!uj && !found_oif) {
                        vty_out(vty,
-                               "%-15s %-15s %-6s %-10s %-10s %-3d  %8s %s\n",
+                               "%-15s %-15s %-6s %-16s %-16s %-3d  %8s %s\n",
                                src_str, grp_str, proto, in_ifname, "none", 0,
                                "--:--:--", pim->vrf->name);
                }
@@ -4831,28 +4936,43 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty, bool fill,
        }
 }
 
-DEFUN (show_ip_mroute,
+DEFPY (show_ip_mroute,
        show_ip_mroute_cmd,
-       "show ip mroute [vrf NAME] [fill] [json]",
+       "show ip mroute [vrf NAME] [A.B.C.D$s_or_g [A.B.C.D$g]] [fill$fill] [json$json]",
        SHOW_STR
        IP_STR
        MROUTE_STR
        VRF_CMD_HELP_STR
+       "The Source or Group\n"
+       "The Group\n"
        "Fill in Assumed data\n"
        JSON_STR)
 {
-       bool uj = use_json(argc, argv);
-       bool fill = false;
-       int idx = 2;
-       struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
+       struct prefix_sg sg = {0};
+       struct pim_instance *pim;
+       struct vrf *v;
 
-       if (!vrf)
+       v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
+
+       if (!v) {
+               vty_out(vty, "%% Vrf specified: %s does not exist\n", vrf);
                return CMD_WARNING;
+       }
+       pim = pim_get_pim_instance(v->vrf_id);
 
-       if (argv_find(argv, argc, "fill", &idx))
-               fill = true;
+       if (!pim) {
+               vty_out(vty, "%% Unable to find pim instance\n");
+               return CMD_WARNING;
+       }
 
-       show_mroute(vrf->info, vty, fill, uj);
+       if (s_or_g.s_addr != 0) {
+               if (g.s_addr != 0) {
+                       sg.src = s_or_g;
+                       sg.grp = g;
+               } else
+                       sg.grp = s_or_g;
+       }
+       show_mroute(pim, vty, &sg, !!fill, !!json);
        return CMD_SUCCESS;
 }
 
@@ -4866,6 +4986,7 @@ DEFUN (show_ip_mroute_vrf_all,
        "Fill in Assumed data\n"
        JSON_STR)
 {
+       struct prefix_sg sg = {0};
        bool uj = use_json(argc, argv);
        int idx = 4;
        struct vrf *vrf;
@@ -4885,7 +5006,7 @@ DEFUN (show_ip_mroute_vrf_all,
                        first = false;
                } else
                        vty_out(vty, "VRF: %s\n", vrf->name);
-               show_mroute(vrf->info, vty, fill, uj);
+               show_mroute(vrf->info, vty, &sg, fill, uj);
        }
        if (uj)
                vty_out(vty, "}\n");
@@ -5026,7 +5147,7 @@ DEFUN (show_ip_rib,
                return CMD_WARNING;
        }
 
-       if (pim_nexthop_lookup(vrf->info, &nexthop, addr, 0)) {
+       if (!pim_nexthop_lookup(vrf->info, &nexthop, addr, 0)) {
                vty_out(vty,
                        "Failure querying RIB nexthop for unicast address %s\n",
                        addr_str);
@@ -5783,7 +5904,8 @@ static int pim_cmd_igmp_start(struct vty *vty, struct interface *ifp)
        pim_ifp = ifp->info;
 
        if (!pim_ifp) {
-               pim_ifp = pim_if_new(ifp, true, false, false);
+               pim_ifp = pim_if_new(ifp, true, false, false,
+                       false /*vxlan_term*/);
                if (!pim_ifp) {
                        vty_out(vty, "Could not enable IGMP on interface %s\n",
                                ifp->name);
@@ -6394,7 +6516,8 @@ static int pim_cmd_interface_add(struct interface *ifp)
        struct pim_interface *pim_ifp = ifp->info;
 
        if (!pim_ifp) {
-               pim_ifp = pim_if_new(ifp, false, true, false);
+               pim_ifp = pim_if_new(ifp, false, true, false,
+                       false /*vxlan_term*/);
                if (!pim_ifp) {
                        return 0;
                }
@@ -6404,6 +6527,8 @@ static int pim_cmd_interface_add(struct interface *ifp)
 
        pim_if_addr_add_all(ifp);
        pim_if_membership_refresh(ifp);
+
+       pim_if_create_pimreg(pim_ifp->pim);
        return 1;
 }
 
@@ -7068,21 +7193,23 @@ DEFUN (no_debug_mroute_detail,
        return CMD_SUCCESS;
 }
 
-DEFUN (debug_static,
-       debug_static_cmd,
-       "debug static",
+DEFUN (debug_pim_static,
+       debug_pim_static_cmd,
+       "debug pim static",
        DEBUG_STR
+       DEBUG_PIM_STR
        DEBUG_STATIC_STR)
 {
        PIM_DO_DEBUG_STATIC;
        return CMD_SUCCESS;
 }
 
-DEFUN (no_debug_static,
-       no_debug_static_cmd,
-       "no debug static",
+DEFUN (no_debug_pim_static,
+       no_debug_pim_static_cmd,
+       "no debug pim static",
        NO_STR
        DEBUG_STR
+       DEBUG_PIM_STR
        DEBUG_STATIC_STR)
 {
        PIM_DONT_DEBUG_STATIC;
@@ -7391,6 +7518,29 @@ DEFUN (no_debug_pim_zebra,
        return CMD_SUCCESS;
 }
 
+DEFUN (debug_pim_vxlan,
+       debug_pim_vxlan_cmd,
+       "debug pim vxlan",
+       DEBUG_STR
+       DEBUG_PIM_STR
+       DEBUG_PIM_VXLAN_STR)
+{
+       PIM_DO_DEBUG_VXLAN;
+       return CMD_SUCCESS;
+}
+
+DEFUN (no_debug_pim_vxlan,
+       no_debug_pim_vxlan_cmd,
+       "no debug pim vxlan",
+       NO_STR
+       DEBUG_STR
+       DEBUG_PIM_STR
+       DEBUG_PIM_VXLAN_STR)
+{
+       PIM_DONT_DEBUG_VXLAN;
+       return CMD_SUCCESS;
+}
+
 DEFUN (debug_msdp,
        debug_msdp_cmd,
        "debug msdp",
@@ -7414,14 +7564,6 @@ DEFUN (no_debug_msdp,
        return CMD_SUCCESS;
 }
 
-#if CONFDATE > 20190402
-CPP_NOTICE("bgpd: time to remove undebug commands")
-#endif
-ALIAS_HIDDEN (no_debug_msdp,
-              undebug_msdp_cmd,
-              "undebug msdp",
-              UNDEBUG_STR DEBUG_MSDP_STR)
-
 DEFUN (debug_msdp_events,
        debug_msdp_events_cmd,
        "debug msdp events",
@@ -7445,16 +7587,6 @@ DEFUN (no_debug_msdp_events,
        return CMD_SUCCESS;
 }
 
-#if CONFDATE > 20190402
-CPP_NOTICE("bgpd: time to remove undebug commands")
-#endif
-ALIAS_HIDDEN (no_debug_msdp_events,
-              undebug_msdp_events_cmd,
-              "undebug msdp events",
-              UNDEBUG_STR
-              DEBUG_MSDP_STR
-              DEBUG_MSDP_EVENTS_STR)
-
 DEFUN (debug_msdp_packets,
        debug_msdp_packets_cmd,
        "debug msdp packets",
@@ -7478,16 +7610,6 @@ DEFUN (no_debug_msdp_packets,
        return CMD_SUCCESS;
 }
 
-#if CONFDATE > 20190402
-CPP_NOTICE("bgpd: time to remove undebug commands")
-#endif
-ALIAS_HIDDEN (no_debug_msdp_packets,
-              undebug_msdp_packets_cmd,
-              "undebug msdp packets",
-              UNDEBUG_STR
-              DEBUG_MSDP_STR
-              DEBUG_MSDP_PACKETS_STR)
-
 DEFUN (debug_mtrace,
        debug_mtrace_cmd,
        "debug mtrace",
@@ -8720,6 +8842,369 @@ DEFUN (show_ip_msdp_sa_sg_vrf_all,
        return CMD_SUCCESS;
 }
 
+struct pim_sg_cache_walk_data {
+       struct vty *vty;
+       json_object *json;
+       json_object *json_group;
+       struct in_addr addr;
+       bool addr_match;
+};
+
+static void pim_show_vxlan_sg_entry(struct pim_vxlan_sg *vxlan_sg,
+                        struct pim_sg_cache_walk_data *cwd)
+{
+       struct vty *vty = cwd->vty;
+       json_object *json = cwd->json;
+       char src_str[INET_ADDRSTRLEN];
+       char grp_str[INET_ADDRSTRLEN];
+       json_object *json_row;
+       bool installed = (vxlan_sg->up) ? true : false;
+       const char *iif_name = vxlan_sg->iif?vxlan_sg->iif->name:"-";
+       const char *oif_name;
+
+       if (pim_vxlan_is_orig_mroute(vxlan_sg))
+               oif_name = vxlan_sg->orig_oif?vxlan_sg->orig_oif->name:"";
+       else
+               oif_name = vxlan_sg->term_oif?vxlan_sg->term_oif->name:"";
+
+       if (cwd->addr_match && (vxlan_sg->sg.src.s_addr != cwd->addr.s_addr) &&
+                       (vxlan_sg->sg.grp.s_addr != cwd->addr.s_addr)) {
+               return;
+       }
+       pim_inet4_dump("<src?>", vxlan_sg->sg.src, src_str, sizeof(src_str));
+       pim_inet4_dump("<grp?>", vxlan_sg->sg.grp, grp_str, sizeof(grp_str));
+       if (json) {
+               json_object_object_get_ex(json, grp_str, &cwd->json_group);
+
+               if (!cwd->json_group) {
+                       cwd->json_group = json_object_new_object();
+                       json_object_object_add(json, grp_str,
+                                       cwd->json_group);
+               }
+
+               json_row = json_object_new_object();
+               json_object_string_add(json_row, "source", src_str);
+               json_object_string_add(json_row, "group", grp_str);
+               json_object_string_add(json_row, "input", iif_name);
+               json_object_string_add(json_row, "output", oif_name);
+               if (installed)
+                       json_object_boolean_true_add(json_row, "installed");
+               else
+                       json_object_boolean_false_add(json_row, "installed");
+               json_object_object_add(cwd->json_group, src_str, json_row);
+       } else {
+               vty_out(vty, "%-15s %-15s %-15s %-15s %-5s\n",
+                               src_str, grp_str, iif_name, oif_name,
+                               installed?"I":"");
+       }
+}
+
+static void pim_show_vxlan_sg_hash_entry(struct hash_backet *backet, void *arg)
+{
+       pim_show_vxlan_sg_entry((struct pim_vxlan_sg *)backet->data,
+                (struct pim_sg_cache_walk_data *)arg);
+}
+
+static void pim_show_vxlan_sg(struct pim_instance *pim,
+               struct vty *vty, bool uj)
+{
+       json_object *json = NULL;
+       struct pim_sg_cache_walk_data cwd;
+
+       if (uj) {
+               json = json_object_new_object();
+       } else {
+               vty_out(vty, "Codes: I -> installed\n");
+               vty_out(vty,
+                       "Source          Group           Input           Output          Flags\n");
+       }
+
+       memset(&cwd, 0, sizeof(cwd));
+       cwd.vty = vty;
+       cwd.json = json;
+       hash_iterate(pim->vxlan.sg_hash, pim_show_vxlan_sg_hash_entry, &cwd);
+
+       if (uj) {
+               vty_out(vty, "%s\n", json_object_to_json_string_ext(
+                                       json, JSON_C_TO_STRING_PRETTY));
+               json_object_free(json);
+       }
+}
+
+static void pim_show_vxlan_sg_match_addr(struct pim_instance *pim,
+               struct vty *vty, char *addr_str, bool uj)
+{
+       json_object *json = NULL;
+       struct pim_sg_cache_walk_data cwd;
+       int result = 0;
+
+       memset(&cwd, 0, sizeof(cwd));
+       result = inet_pton(AF_INET, addr_str, &cwd.addr);
+       if (result <= 0) {
+               vty_out(vty, "Bad address %s: errno=%d: %s\n", addr_str,
+                               errno, safe_strerror(errno));
+               return;
+       }
+
+       if (uj) {
+               json = json_object_new_object();
+       } else {
+               vty_out(vty, "Codes: I -> installed\n");
+               vty_out(vty,
+                       "Source          Group           Input           Output          Flags\n");
+       }
+
+       cwd.vty = vty;
+       cwd.json = json;
+       cwd.addr_match = true;
+       hash_iterate(pim->vxlan.sg_hash, pim_show_vxlan_sg_hash_entry, &cwd);
+
+       if (uj) {
+               vty_out(vty, "%s\n", json_object_to_json_string_ext(
+                                       json, JSON_C_TO_STRING_PRETTY));
+               json_object_free(json);
+       }
+}
+
+static void pim_show_vxlan_sg_one(struct pim_instance *pim,
+               struct vty *vty, char *src_str, char *grp_str, bool uj)
+{
+       json_object *json = NULL;
+       struct prefix_sg sg;
+       int result = 0;
+       struct pim_vxlan_sg *vxlan_sg;
+       const char *iif_name;
+       bool installed;
+       const char *oif_name;
+
+       result = inet_pton(AF_INET, src_str, &sg.src);
+       if (result <= 0) {
+               vty_out(vty, "Bad src address %s: errno=%d: %s\n", src_str,
+                               errno, safe_strerror(errno));
+               return;
+       }
+       result = inet_pton(AF_INET, grp_str, &sg.grp);
+       if (result <= 0) {
+               vty_out(vty, "Bad grp address %s: errno=%d: %s\n", grp_str,
+                               errno, safe_strerror(errno));
+               return;
+       }
+
+       sg.family = AF_INET;
+       sg.prefixlen = IPV4_MAX_BITLEN;
+       if (uj)
+               json = json_object_new_object();
+
+       vxlan_sg = pim_vxlan_sg_find(pim, &sg);
+       if (vxlan_sg) {
+               installed = (vxlan_sg->up) ? true : false;
+               iif_name = vxlan_sg->iif?vxlan_sg->iif->name:"-";
+
+               if (pim_vxlan_is_orig_mroute(vxlan_sg))
+                       oif_name =
+                               vxlan_sg->orig_oif?vxlan_sg->orig_oif->name:"";
+               else
+                       oif_name =
+                               vxlan_sg->term_oif?vxlan_sg->term_oif->name:"";
+
+               if (uj) {
+                       json_object_string_add(json, "source", src_str);
+                       json_object_string_add(json, "group", grp_str);
+                       json_object_string_add(json, "input", iif_name);
+                       json_object_string_add(json, "output", oif_name);
+                       if (installed)
+                               json_object_boolean_true_add(json, "installed");
+                       else
+                               json_object_boolean_false_add(json,
+                                       "installed");
+               } else {
+                       vty_out(vty, "SG : %s\n", vxlan_sg->sg_str);
+                       vty_out(vty, "  Input     : %s\n", iif_name);
+                       vty_out(vty, "  Output    : %s\n", oif_name);
+                       vty_out(vty, "  installed : %s\n",
+                               installed?"yes":"no");
+               }
+       }
+
+       if (uj) {
+               vty_out(vty, "%s\n", json_object_to_json_string_ext(
+                                       json, JSON_C_TO_STRING_PRETTY));
+               json_object_free(json);
+       }
+}
+
+DEFUN (show_ip_pim_vxlan_sg,
+       show_ip_pim_vxlan_sg_cmd,
+       "show ip pim [vrf NAME] vxlan-groups [A.B.C.D [A.B.C.D]] [json]",
+       SHOW_STR
+       IP_STR
+       PIM_STR
+       VRF_CMD_HELP_STR
+       "VxLAN BUM groups\n"
+       "source or group ip\n"
+       "group ip\n"
+       JSON_STR)
+{
+       bool uj = use_json(argc, argv);
+       struct vrf *vrf;
+       int idx = 2;
+
+       vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
+
+       if (!vrf)
+               return CMD_WARNING;
+
+       char *src_ip = argv_find(argv, argc, "A.B.C.D", &idx) ?
+               argv[idx++]->arg:NULL;
+       char *grp_ip = idx < argc && argv_find(argv, argc, "A.B.C.D", &idx) ?
+               argv[idx]->arg:NULL;
+
+       if (src_ip && grp_ip)
+               pim_show_vxlan_sg_one(vrf->info, vty, src_ip, grp_ip, uj);
+       else if (src_ip)
+               pim_show_vxlan_sg_match_addr(vrf->info, vty, src_ip, uj);
+       else
+               pim_show_vxlan_sg(vrf->info, vty, uj);
+
+       return CMD_SUCCESS;
+}
+
+static void pim_show_vxlan_sg_work(struct pim_instance *pim,
+               struct vty *vty, bool uj)
+{
+       json_object *json = NULL;
+       struct pim_sg_cache_walk_data cwd;
+       struct listnode *node;
+       struct pim_vxlan_sg *vxlan_sg;
+
+       if (uj) {
+               json = json_object_new_object();
+       } else {
+               vty_out(vty, "Codes: I -> installed\n");
+               vty_out(vty,
+                       "Source          Group           Input           Flags\n");
+       }
+
+       memset(&cwd, 0, sizeof(cwd));
+       cwd.vty = vty;
+       cwd.json = json;
+       for (ALL_LIST_ELEMENTS_RO(pim_vxlan_p->work_list, node, vxlan_sg))
+               pim_show_vxlan_sg_entry(vxlan_sg, &cwd);
+
+       if (uj) {
+               vty_out(vty, "%s\n", json_object_to_json_string_ext(
+                                       json, JSON_C_TO_STRING_PRETTY));
+               json_object_free(json);
+       }
+}
+
+DEFUN_HIDDEN (show_ip_pim_vxlan_sg_work,
+              show_ip_pim_vxlan_sg_work_cmd,
+              "show ip pim [vrf NAME] vxlan-work [json]",
+              SHOW_STR
+              IP_STR
+              PIM_STR
+              VRF_CMD_HELP_STR
+              "VxLAN work list\n"
+              JSON_STR)
+{
+       bool uj = use_json(argc, argv);
+       struct vrf *vrf;
+       int idx = 2;
+
+       vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
+
+       if (!vrf)
+               return CMD_WARNING;
+
+       pim_show_vxlan_sg_work(vrf->info, vty, uj);
+
+       return CMD_SUCCESS;
+}
+
+DEFUN_HIDDEN (no_ip_pim_mlag,
+       no_ip_pim_mlag_cmd,
+       "no ip pim mlag",
+       NO_STR
+       IP_STR
+       PIM_STR
+       "MLAG\n")
+{
+       struct in_addr addr;
+
+       addr.s_addr = 0;
+       pim_vxlan_mlag_update(true/*mlag_enable*/,
+               false/*peer_state*/, PIM_VXLAN_MLAG_ROLE_SECONDARY,
+               NULL/*peerlink*/, &addr);
+
+       return CMD_SUCCESS;
+}
+
+DEFUN_HIDDEN (ip_pim_mlag,
+       ip_pim_mlag_cmd,
+       "ip pim mlag INTERFACE role [primary|secondary] state [up|down] addr A.B.C.D",
+       IP_STR
+       PIM_STR
+       "MLAG\n"
+       "peerlink sub interface\n"
+       "MLAG role\n"
+       "MLAG role primary\n"
+       "MLAG role secondary\n"
+       "peer session state\n"
+       "peer session state up\n"
+       "peer session state down\n"
+       "configure PIP\n"
+       "unique ip address\n")
+{
+       struct interface *ifp;
+       const char *peerlink;
+       uint32_t role;
+       int idx;
+       bool peer_state;
+       int result;
+       struct in_addr reg_addr;
+
+       idx = 3;
+       peerlink = argv[idx]->arg;
+       ifp = if_lookup_by_name(peerlink, VRF_DEFAULT);
+       if (!ifp) {
+               vty_out(vty, "No such interface name %s\n", peerlink);
+               return CMD_WARNING;
+       }
+
+       idx += 2;
+       if (!strcmp(argv[idx]->arg, "primary")) {
+               role = PIM_VXLAN_MLAG_ROLE_PRIMARY;
+       } else if (!strcmp(argv[idx]->arg, "secondary")) {
+               role = PIM_VXLAN_MLAG_ROLE_SECONDARY;
+       } else {
+               vty_out(vty, "unknown MLAG role %s\n", argv[idx]->arg);
+               return CMD_WARNING;
+       }
+
+       idx += 2;
+       if (!strcmp(argv[idx]->arg, "up")) {
+               peer_state = true;
+       } else if (strcmp(argv[idx]->arg, "down")) {
+               peer_state = false;
+       } else {
+               vty_out(vty, "unknown MLAG state %s\n", argv[idx]->arg);
+               return CMD_WARNING;
+       }
+
+       idx += 2;
+       result = inet_pton(AF_INET, argv[idx]->arg, &reg_addr);
+       if (result <= 0) {
+               vty_out(vty, "%% Bad reg address %s: errno=%d: %s\n",
+                       argv[idx]->arg,
+                       errno, safe_strerror(errno));
+               return CMD_WARNING_CONFIG_FAILED;
+       }
+       pim_vxlan_mlag_update(true, peer_state, role, ifp, &reg_addr);
+
+       return CMD_SUCCESS;
+}
+
 void pim_cmd_init(void)
 {
        install_node(&interface_node,
@@ -8793,6 +9278,8 @@ void pim_cmd_init(void)
        install_element(VRF_NODE, &ip_pim_ecmp_rebalance_cmd);
        install_element(CONFIG_NODE, &no_ip_pim_ecmp_rebalance_cmd);
        install_element(VRF_NODE, &no_ip_pim_ecmp_rebalance_cmd);
+       install_element(CONFIG_NODE, &ip_pim_mlag_cmd);
+       install_element(CONFIG_NODE, &no_ip_pim_mlag_cmd);
 
        install_element(INTERFACE_NODE, &interface_ip_igmp_cmd);
        install_element(INTERFACE_NODE, &interface_no_ip_igmp_cmd);
@@ -8895,8 +9382,8 @@ void pim_cmd_init(void)
        install_element(ENABLE_NODE, &debug_mroute_detail_cmd);
        install_element(ENABLE_NODE, &no_debug_mroute_cmd);
        install_element(ENABLE_NODE, &no_debug_mroute_detail_cmd);
-       install_element(ENABLE_NODE, &debug_static_cmd);
-       install_element(ENABLE_NODE, &no_debug_static_cmd);
+       install_element(ENABLE_NODE, &debug_pim_static_cmd);
+       install_element(ENABLE_NODE, &no_debug_pim_static_cmd);
        install_element(ENABLE_NODE, &debug_pim_cmd);
        install_element(ENABLE_NODE, &no_debug_pim_cmd);
        install_element(ENABLE_NODE, &debug_pim_nht_cmd);
@@ -8919,15 +9406,14 @@ void pim_cmd_init(void)
        install_element(ENABLE_NODE, &no_debug_ssmpingd_cmd);
        install_element(ENABLE_NODE, &debug_pim_zebra_cmd);
        install_element(ENABLE_NODE, &no_debug_pim_zebra_cmd);
+       install_element(ENABLE_NODE, &debug_pim_vxlan_cmd);
+       install_element(ENABLE_NODE, &no_debug_pim_vxlan_cmd);
        install_element(ENABLE_NODE, &debug_msdp_cmd);
        install_element(ENABLE_NODE, &no_debug_msdp_cmd);
-       install_element(ENABLE_NODE, &undebug_msdp_cmd);
        install_element(ENABLE_NODE, &debug_msdp_events_cmd);
        install_element(ENABLE_NODE, &no_debug_msdp_events_cmd);
-       install_element(ENABLE_NODE, &undebug_msdp_events_cmd);
        install_element(ENABLE_NODE, &debug_msdp_packets_cmd);
        install_element(ENABLE_NODE, &no_debug_msdp_packets_cmd);
-       install_element(ENABLE_NODE, &undebug_msdp_packets_cmd);
        install_element(ENABLE_NODE, &debug_mtrace_cmd);
        install_element(ENABLE_NODE, &no_debug_mtrace_cmd);
 
@@ -8943,8 +9429,8 @@ void pim_cmd_init(void)
        install_element(CONFIG_NODE, &debug_mroute_detail_cmd);
        install_element(CONFIG_NODE, &no_debug_mroute_cmd);
        install_element(CONFIG_NODE, &no_debug_mroute_detail_cmd);
-       install_element(CONFIG_NODE, &debug_static_cmd);
-       install_element(CONFIG_NODE, &no_debug_static_cmd);
+       install_element(CONFIG_NODE, &debug_pim_static_cmd);
+       install_element(CONFIG_NODE, &no_debug_pim_static_cmd);
        install_element(CONFIG_NODE, &debug_pim_cmd);
        install_element(CONFIG_NODE, &no_debug_pim_cmd);
        install_element(CONFIG_NODE, &debug_pim_nht_cmd);
@@ -8963,15 +9449,14 @@ void pim_cmd_init(void)
        install_element(CONFIG_NODE, &no_debug_ssmpingd_cmd);
        install_element(CONFIG_NODE, &debug_pim_zebra_cmd);
        install_element(CONFIG_NODE, &no_debug_pim_zebra_cmd);
+       install_element(CONFIG_NODE, &debug_pim_vxlan_cmd);
+       install_element(CONFIG_NODE, &no_debug_pim_vxlan_cmd);
        install_element(CONFIG_NODE, &debug_msdp_cmd);
        install_element(CONFIG_NODE, &no_debug_msdp_cmd);
-       install_element(CONFIG_NODE, &undebug_msdp_cmd);
        install_element(CONFIG_NODE, &debug_msdp_events_cmd);
        install_element(CONFIG_NODE, &no_debug_msdp_events_cmd);
-       install_element(CONFIG_NODE, &undebug_msdp_events_cmd);
        install_element(CONFIG_NODE, &debug_msdp_packets_cmd);
        install_element(CONFIG_NODE, &no_debug_msdp_packets_cmd);
-       install_element(CONFIG_NODE, &undebug_msdp_packets_cmd);
        install_element(CONFIG_NODE, &debug_mtrace_cmd);
        install_element(CONFIG_NODE, &no_debug_mtrace_cmd);
 
@@ -8993,6 +9478,8 @@ void pim_cmd_init(void)
        install_element(VIEW_NODE, &show_ip_msdp_mesh_group_vrf_all_cmd);
        install_element(VIEW_NODE, &show_ip_pim_ssm_range_cmd);
        install_element(VIEW_NODE, &show_ip_pim_group_type_cmd);
+       install_element(VIEW_NODE, &show_ip_pim_vxlan_sg_cmd);
+       install_element(VIEW_NODE, &show_ip_pim_vxlan_sg_work_cmd);
        install_element(INTERFACE_NODE, &interface_pim_use_source_cmd);
        install_element(INTERFACE_NODE, &interface_no_pim_use_source_cmd);
        /* Install BFD command */