]> git.puffer.fish Git - matthieu/frr.git/commitdiff
pimd: Moving the common functions from pim_cmd.c
authorAbhishek N R <abnr@vmware.com>
Tue, 8 Feb 2022 17:15:06 +0000 (09:15 -0800)
committerAbhishek N R <abnr@vmware.com>
Tue, 29 Mar 2022 06:53:24 +0000 (23:53 -0700)
Moving the functions that are used by both IPV4 and IPV6 to a
common file pim_cmd_common.c file

Signed-off-by: Abhishek N R <abnr@vmware.com>
pimd/pim_cmd.c
pimd/pim_cmd.h
pimd/pim_cmd_common.c
pimd/pim_cmd_common.h

index c34135eaf62d177103d4f6cc58bbddce25427ec2..aa1ff5c925e39f5180aeebd09d7c269a7db5cc60 100644 (file)
@@ -2015,244 +2015,6 @@ static void pim_show_neighbors_single(struct pim_instance *pim, struct vty *vty,
                vty_out(vty, "%% No such interface or neighbor\n");
 }
 
-static void pim_show_state(struct pim_instance *pim, struct vty *vty,
-                          const char *src_or_group, const char *group, bool uj)
-{
-       struct channel_oil *c_oil;
-       json_object *json = NULL;
-       json_object *json_group = NULL;
-       json_object *json_ifp_in = NULL;
-       json_object *json_ifp_out = NULL;
-       json_object *json_source = NULL;
-       time_t now;
-       int first_oif;
-       now = pim_time_monotonic_sec();
-
-       if (uj) {
-               json = json_object_new_object();
-       } else {
-               vty_out(vty,
-                       "Codes: J -> Pim Join, I -> IGMP Report, S -> Source, * -> Inherited from (*,G), V -> VxLAN, M -> Muted");
-               vty_out(vty,
-                       "\nActive Source           Group            RPT  IIF               OIL\n");
-       }
-
-       frr_each (rb_pim_oil, &pim->channel_oil_head, c_oil) {
-               char grp_str[INET_ADDRSTRLEN];
-               char src_str[INET_ADDRSTRLEN];
-               char in_ifname[INTERFACE_NAMSIZ + 1];
-               char out_ifname[INTERFACE_NAMSIZ + 1];
-               int oif_vif_index;
-               struct interface *ifp_in;
-               bool isRpt;
-               first_oif = 1;
-
-               if ((c_oil->up &&
-                    PIM_UPSTREAM_FLAG_TEST_USE_RPT(c_oil->up->flags)) ||
-                   c_oil->oil.mfcc_origin.s_addr == INADDR_ANY)
-                       isRpt = true;
-               else
-                       isRpt = false;
-
-               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,
-                              sizeof(src_str));
-               ifp_in = pim_if_find_by_vif_index(pim, c_oil->oil.mfcc_parent);
-
-               if (ifp_in)
-                       strlcpy(in_ifname, ifp_in->name, sizeof(in_ifname));
-               else
-                       strlcpy(in_ifname, "<iif?>", sizeof(in_ifname));
-
-               if (src_or_group) {
-                       if (strcmp(src_or_group, src_str)
-                           && strcmp(src_or_group, grp_str))
-                               continue;
-
-                       if (group && strcmp(group, grp_str))
-                               continue;
-               }
-
-               if (uj) {
-
-                       /* Find the group, create it if it doesn't exist */
-                       json_object_object_get_ex(json, grp_str, &json_group);
-
-                       if (!json_group) {
-                               json_group = json_object_new_object();
-                               json_object_object_add(json, grp_str,
-                                                      json_group);
-                       }
-
-                       /* Find the source nested under the group, create it if
-                        * it doesn't exist */
-                       json_object_object_get_ex(json_group, src_str,
-                                                 &json_source);
-
-                       if (!json_source) {
-                               json_source = json_object_new_object();
-                               json_object_object_add(json_group, src_str,
-                                                      json_source);
-                       }
-
-                       /* Find the inbound interface nested under the source,
-                        * create it if it doesn't exist */
-                       json_object_object_get_ex(json_source, in_ifname,
-                                                 &json_ifp_in);
-
-                       if (!json_ifp_in) {
-                               json_ifp_in = json_object_new_object();
-                               json_object_object_add(json_source, in_ifname,
-                                                      json_ifp_in);
-                               json_object_int_add(json_source, "Installed",
-                                                   c_oil->installed);
-                               json_object_int_add(json_source, "installed",
-                                                   c_oil->installed);
-                               if (isRpt)
-                                       json_object_boolean_true_add(
-                                               json_source, "isRpt");
-                               else
-                                       json_object_boolean_false_add(
-                                               json_source, "isRpt");
-                               json_object_int_add(json_source, "RefCount",
-                                                   c_oil->oil_ref_count);
-                               json_object_int_add(json_source, "refCount",
-                                                   c_oil->oil_ref_count);
-                               json_object_int_add(json_source, "OilListSize",
-                                                   c_oil->oil_size);
-                               json_object_int_add(json_source, "oilListSize",
-                                                   c_oil->oil_size);
-                               json_object_int_add(
-                                       json_source, "OilRescan",
-                                       c_oil->oil_inherited_rescan);
-                               json_object_int_add(
-                                       json_source, "oilRescan",
-                                       c_oil->oil_inherited_rescan);
-                               json_object_int_add(json_source, "LastUsed",
-                                                   c_oil->cc.lastused);
-                               json_object_int_add(json_source, "lastUsed",
-                                                   c_oil->cc.lastused);
-                               json_object_int_add(json_source, "PacketCount",
-                                                   c_oil->cc.pktcnt);
-                               json_object_int_add(json_source, "packetCount",
-                                                   c_oil->cc.pktcnt);
-                               json_object_int_add(json_source, "ByteCount",
-                                                   c_oil->cc.bytecnt);
-                               json_object_int_add(json_source, "byteCount",
-                                                   c_oil->cc.bytecnt);
-                               json_object_int_add(json_source,
-                                                   "WrongInterface",
-                                                   c_oil->cc.wrong_if);
-                               json_object_int_add(json_source,
-                                                   "wrongInterface",
-                                                   c_oil->cc.wrong_if);
-                       }
-               } else {
-                       vty_out(vty, "%-6d %-15s  %-15s  %-3s  %-16s  ",
-                               c_oil->installed, src_str, grp_str,
-                               isRpt ? "y" : "n", in_ifname);
-               }
-
-               for (oif_vif_index = 0; oif_vif_index < MAXVIFS;
-                    ++oif_vif_index) {
-                       struct interface *ifp_out;
-                       char oif_uptime[10];
-                       int ttl;
-
-                       ttl = c_oil->oil.mfcc_ttls[oif_vif_index];
-                       if (ttl < 1)
-                               continue;
-
-                       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]);
-
-                       if (ifp_out)
-                               strlcpy(out_ifname, ifp_out->name, sizeof(out_ifname));
-                       else
-                               strlcpy(out_ifname, "<oif?>", sizeof(out_ifname));
-
-                       if (uj) {
-                               json_ifp_out = json_object_new_object();
-                               json_object_string_add(json_ifp_out, "source",
-                                                      src_str);
-                               json_object_string_add(json_ifp_out, "group",
-                                                      grp_str);
-                               json_object_string_add(json_ifp_out,
-                                                      "inboundInterface",
-                                                      in_ifname);
-                               json_object_string_add(json_ifp_out,
-                                                      "outboundInterface",
-                                                      out_ifname);
-                               json_object_int_add(json_ifp_out, "installed",
-                                                   c_oil->installed);
-
-                               json_object_object_add(json_ifp_in, out_ifname,
-                                                      json_ifp_out);
-                       } else {
-                               if (first_oif) {
-                                       first_oif = 0;
-                                       vty_out(vty, "%s(%c%c%c%c%c)",
-                                               out_ifname,
-                                               (c_oil->oif_flags[oif_vif_index]
-                                                & PIM_OIF_FLAG_PROTO_IGMP)
-                                               ? 'I'
-                                               : ' ',
-                                               (c_oil->oif_flags[oif_vif_index]
-                                                & 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_STAR)
-                                               ? '*'
-                                               : ' ',
-                                               (c_oil->oif_flags[oif_vif_index]
-                                                & PIM_OIF_FLAG_MUTE)
-                                               ? 'M'
-                                               : ' ');
-                               } else
-                                       vty_out(vty, ", %s(%c%c%c%c%c)",
-                                               out_ifname,
-                                               (c_oil->oif_flags[oif_vif_index]
-                                                & PIM_OIF_FLAG_PROTO_IGMP)
-                                               ? 'I'
-                                               : ' ',
-                                               (c_oil->oif_flags[oif_vif_index]
-                                                & 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_STAR)
-                                               ? '*'
-                                               : ' ',
-                                               (c_oil->oif_flags[oif_vif_index]
-                                                & PIM_OIF_FLAG_MUTE)
-                                               ? 'M'
-                                               : ' ');
-                       }
-               }
-
-               if (!uj)
-                       vty_out(vty, "\n");
-       }
-
-
-       if (uj)
-               vty_json(vty, json);
-       else
-               vty_out(vty, "\n");
-}
-
 static void pim_show_neighbors(struct pim_instance *pim, struct vty *vty,
                               bool uj)
 {
@@ -2332,307 +2094,10 @@ static void pim_show_neighbors(struct pim_instance *pim, struct vty *vty,
                vty_json(vty, json);
 }
 
-static void pim_show_neighbors_secondary(struct pim_instance *pim,
-                                        struct vty *vty)
-{
-       struct interface *ifp;
-
-       vty_out(vty,
-               "Interface        Address         Neighbor        Secondary      \n");
-
-       FOR_ALL_INTERFACES (pim->vrf, ifp) {
-               struct pim_interface *pim_ifp;
-               struct in_addr ifaddr;
-               struct listnode *neighnode;
-               struct pim_neighbor *neigh;
-               char buf[PREFIX_STRLEN];
-
-               pim_ifp = ifp->info;
-
-               if (!pim_ifp)
-                       continue;
-
-               if (pim_ifp->pim_sock_fd < 0)
-                       continue;
-
-               ifaddr = pim_ifp->primary_address;
-
-               for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode,
-                                         neigh)) {
-                       char neigh_src_str[INET_ADDRSTRLEN];
-                       struct listnode *prefix_node;
-                       struct prefix *p;
-
-                       if (!neigh->prefix_list)
-                               continue;
-
-                       pim_inet4_dump("<src?>", neigh->source_addr,
-                                      neigh_src_str, sizeof(neigh_src_str));
-
-                       for (ALL_LIST_ELEMENTS_RO(neigh->prefix_list,
-                                                 prefix_node, p))
-                               vty_out(vty, "%-16s %-15s %-15s %-15pFX\n",
-                                       ifp->name,
-                                       inet_ntop(AF_INET, &ifaddr,
-                                                 buf, sizeof(buf)),
-                                       neigh_src_str, p);
-               }
-       }
-}
-
-static void json_object_pim_upstream_add(json_object *json,
-                                        struct pim_upstream *up)
-{
-       if (up->flags & PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED)
-               json_object_boolean_true_add(json, "drJoinDesired");
-
-       if (up->flags & PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED_UPDATED)
-               json_object_boolean_true_add(json, "drJoinDesiredUpdated");
-
-       if (up->flags & PIM_UPSTREAM_FLAG_MASK_FHR)
-               json_object_boolean_true_add(json, "firstHopRouter");
-
-       if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP)
-               json_object_boolean_true_add(json, "sourceIgmp");
-
-       if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_PIM)
-               json_object_boolean_true_add(json, "sourcePim");
-
-       if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_STREAM)
-               json_object_boolean_true_add(json, "sourceStream");
-
-       /* 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 *
-pim_upstream_state2brief_str(enum pim_upstream_state join_state,
-                            char *state_str, size_t state_str_len)
-{
-       switch (join_state) {
-       case PIM_UPSTREAM_NOTJOINED:
-               strlcpy(state_str, "NotJ", state_str_len);
-               break;
-       case PIM_UPSTREAM_JOINED:
-               strlcpy(state_str, "J", state_str_len);
-               break;
-       default:
-               strlcpy(state_str, "Unk", state_str_len);
-       }
-       return state_str;
-}
-
-static const char *pim_reg_state2brief_str(enum pim_reg_state reg_state,
-                                          char *state_str, size_t state_str_len)
-{
-       switch (reg_state) {
-       case PIM_REG_NOINFO:
-               strlcpy(state_str, "RegNI", state_str_len);
-               break;
-       case PIM_REG_JOIN:
-               strlcpy(state_str, "RegJ", state_str_len);
-               break;
-       case PIM_REG_JOIN_PENDING:
-       case PIM_REG_PRUNE:
-               strlcpy(state_str, "RegP", state_str_len);
-               break;
-       }
-       return state_str;
-}
-
-static void pim_show_upstream(struct pim_instance *pim, struct vty *vty,
-                             pim_sgaddr *sg, bool uj)
-{
-       struct pim_upstream *up;
-       time_t now;
-       json_object *json = NULL;
-       json_object *json_group = NULL;
-       json_object *json_row = NULL;
-
-       now = pim_time_monotonic_sec();
-
-       if (uj)
-               json = json_object_new_object();
-       else
-               vty_out(vty,
-                       "Iif             Source          Group           State       Uptime   JoinTimer RSTimer   KATimer   RefCnt\n");
-
-       frr_each (rb_pim_upstream, &pim->upstream_head, up) {
-               char uptime[10];
-               char join_timer[10];
-               char rs_timer[10];
-               char ka_timer[10];
-               char msdp_reg_timer[10];
-               char state_str[PIM_REG_STATE_STR_LEN];
-
-               if (!pim_sgaddr_match(up->sg, *sg))
-                       continue;
-
-               pim_time_uptime(uptime, sizeof(uptime),
-                               now - up->state_transition);
-               pim_time_timer_to_hhmmss(join_timer, sizeof(join_timer),
-                                        up->t_join_timer);
-
-               /*
-                * If the upstream is not dummy and it has a J/P timer for the
-                * neighbor display that
-                */
-               if (!up->t_join_timer && up->rpf.source_nexthop.interface) {
-                       struct pim_neighbor *nbr;
-
-                       nbr = pim_neighbor_find_prefix(
-                               up->rpf.source_nexthop.interface,
-                               &up->rpf.rpf_addr);
-                       if (nbr)
-                               pim_time_timer_to_hhmmss(join_timer,
-                                                        sizeof(join_timer),
-                                                        nbr->jp_timer);
-               }
-
-               pim_time_timer_to_hhmmss(rs_timer, sizeof(rs_timer),
-                                        up->t_rs_timer);
-               pim_time_timer_to_hhmmss(ka_timer, sizeof(ka_timer),
-                                        up->t_ka_timer);
-               pim_time_timer_to_hhmmss(msdp_reg_timer, sizeof(msdp_reg_timer),
-                                        up->t_msdp_reg_timer);
-
-               pim_upstream_state2brief_str(up->join_state, state_str, sizeof(state_str));
-               if (up->reg_state != PIM_REG_NOINFO) {
-                       char tmp_str[PIM_REG_STATE_STR_LEN];
-                       char tmp[sizeof(state_str) + 1];
-
-                       snprintf(tmp, sizeof(tmp), ",%s",
-                                pim_reg_state2brief_str(up->reg_state, tmp_str,
-                                                        sizeof(tmp_str)));
-                       strlcat(state_str, tmp, sizeof(state_str));
-               }
-
-               if (uj) {
-                       char grp_str[PIM_ADDRSTRLEN];
-                       char src_str[PIM_ADDRSTRLEN];
-
-                       snprintfrr(grp_str, sizeof(grp_str), "%pPAs",
-                                  &up->sg.grp);
-                       snprintfrr(src_str, sizeof(src_str), "%pPAs",
-                                  &up->sg.src);
-
-                       json_object_object_get_ex(json, grp_str, &json_group);
-
-                       if (!json_group) {
-                               json_group = json_object_new_object();
-                               json_object_object_add(json, grp_str,
-                                                      json_group);
-                       }
-
-                       json_row = json_object_new_object();
-                       json_object_pim_upstream_add(json_row, up);
-                       json_object_string_add(
-                               json_row, "inboundInterface",
-                               up->rpf.source_nexthop.interface
-                               ? up->rpf.source_nexthop.interface->name
-                               : "Unknown");
-
-                       /*
-                        * The RPF address we use is slightly different
-                        * based upon what we are looking up.
-                        * If we have a S, list that unless
-                        * we are the FHR, else we just put
-                        * the RP as the rpfAddress
-                        */
-                       if (up->flags & PIM_UPSTREAM_FLAG_MASK_FHR ||
-                           pim_addr_is_any(up->sg.src)) {
-                               char rpf[PREFIX_STRLEN];
-                               struct pim_rpf *rpg;
-
-                               rpg = RP(pim, up->sg.grp);
-                               pim_inet4_dump("<rpf?>",
-                                              rpg->rpf_addr.u.prefix4, rpf,
-                                              sizeof(rpf));
-                               json_object_string_add(json_row, "rpfAddress",
-                                                      rpf);
-                       } else {
-                               json_object_string_add(json_row, "rpfAddress",
-                                                      src_str);
-                       }
-
-                       json_object_string_add(json_row, "source", src_str);
-                       json_object_string_add(json_row, "group", grp_str);
-                       json_object_string_add(json_row, "state", state_str);
-                       json_object_string_add(
-                               json_row, "joinState",
-                               pim_upstream_state2str(up->join_state));
-                       json_object_string_add(
-                               json_row, "regState",
-                               pim_reg_state2str(up->reg_state, state_str, sizeof(state_str)));
-                       json_object_string_add(json_row, "upTime", uptime);
-                       json_object_string_add(json_row, "joinTimer",
-                                              join_timer);
-                       json_object_string_add(json_row, "resetTimer",
-                                              rs_timer);
-                       json_object_string_add(json_row, "keepaliveTimer",
-                                              ka_timer);
-                       json_object_string_add(json_row, "msdpRegTimer",
-                                              msdp_reg_timer);
-                       json_object_int_add(json_row, "refCount",
-                                           up->ref_count);
-                       json_object_int_add(json_row, "sptBit", up->sptbit);
-                       json_object_object_add(json_group, src_str, json_row);
-               } else {
-                       vty_out(vty,
-                               "%-16s%-15pPAs %-15pPAs %-11s %-8s %-9s %-9s %-9s %6d\n",
-                               up->rpf.source_nexthop.interface
-                               ? up->rpf.source_nexthop.interface->name
-                               : "Unknown",
-                               &up->sg.src, &up->sg.grp, state_str, uptime,
-                               join_timer, rs_timer, ka_timer, up->ref_count);
-               }
-       }
-
-       if (uj)
-               vty_json(vty, json);
-}
-
-static void pim_show_channel_helper(struct pim_instance *pim,
-                                   struct vty *vty,
+static void pim_show_channel_helper(struct pim_instance *pim, struct vty *vty,
                                    struct pim_interface *pim_ifp,
-                                   struct pim_ifchannel *ch,
-                                   json_object *json, bool uj)
+                                   struct pim_ifchannel *ch, json_object *json,
+                                   bool uj)
 {
        struct pim_upstream *up = ch->upstream;
        json_object *json_group = NULL;
@@ -2721,181 +2186,6 @@ static void pim_show_channel(struct pim_instance *pim, struct vty *vty,
                vty_json(vty, json);
 }
 
-static void pim_show_join_desired_helper(struct pim_instance *pim,
-                                        struct vty *vty,
-                                        struct pim_upstream *up,
-                                        json_object *json, bool uj)
-{
-       json_object *json_group = NULL;
-       json_object *json_row = NULL;
-
-       if (uj) {
-               char grp_str[PIM_ADDRSTRLEN];
-               char src_str[PIM_ADDRSTRLEN];
-
-               snprintfrr(grp_str, sizeof(grp_str), "%pPAs", &up->sg.grp);
-               snprintfrr(src_str, sizeof(src_str), "%pPAs", &up->sg.src);
-
-               json_object_object_get_ex(json, grp_str, &json_group);
-
-               if (!json_group) {
-                       json_group = json_object_new_object();
-                       json_object_object_add(json, grp_str, json_group);
-               }
-
-               json_row = json_object_new_object();
-               json_object_pim_upstream_add(json_row, up);
-               json_object_string_add(json_row, "source", src_str);
-               json_object_string_add(json_row, "group", grp_str);
-
-               if (pim_upstream_evaluate_join_desired(pim, up))
-                       json_object_boolean_true_add(json_row,
-                                                    "evaluateJoinDesired");
-
-               json_object_object_add(json_group, src_str, json_row);
-
-       } else {
-               vty_out(vty, "%-15pPAs %-15pPAs %-6s\n",
-                       &up->sg.src, &up->sg.grp,
-                       pim_upstream_evaluate_join_desired(pim, up) ? "yes"
-                       : "no");
-       }
-}
-
-static void pim_show_join_desired(struct pim_instance *pim, struct vty *vty,
-                                 bool uj)
-{
-       struct pim_upstream *up;
-
-       json_object *json = NULL;
-
-       if (uj)
-               json = json_object_new_object();
-       else
-               vty_out(vty,
-                       "Source          Group           EvalJD\n");
-
-       frr_each (rb_pim_upstream, &pim->upstream_head, up) {
-               /* scan all interfaces */
-               pim_show_join_desired_helper(pim, vty, up,
-                                            json, uj);
-       }
-
-       if (uj)
-               vty_json(vty, json);
-}
-
-static void pim_show_upstream_rpf(struct pim_instance *pim, struct vty *vty,
-                                 bool uj)
-{
-       struct pim_upstream *up;
-       json_object *json = NULL;
-       json_object *json_group = NULL;
-       json_object *json_row = NULL;
-
-       if (uj)
-               json = json_object_new_object();
-       else
-               vty_out(vty,
-                       "Source          Group           RpfIface         RibNextHop      RpfAddress     \n");
-
-       frr_each (rb_pim_upstream, &pim->upstream_head, up) {
-               char rpf_nexthop_str[PREFIX_STRLEN];
-               char rpf_addr_str[PREFIX_STRLEN];
-               struct pim_rpf *rpf;
-               const char *rpf_ifname;
-
-               rpf = &up->rpf;
-
-               pim_addr_dump("<nexthop?>",
-                             &rpf->source_nexthop.mrib_nexthop_addr,
-                             rpf_nexthop_str, sizeof(rpf_nexthop_str));
-               pim_addr_dump("<rpf?>", &rpf->rpf_addr, rpf_addr_str,
-                             sizeof(rpf_addr_str));
-
-               rpf_ifname = rpf->source_nexthop.interface ? rpf->source_nexthop.interface->name : "<ifname?>";
-
-               if (uj) {
-                       char grp_str[PIM_ADDRSTRLEN];
-                       char src_str[PIM_ADDRSTRLEN];
-
-                       snprintfrr(grp_str, sizeof(grp_str), "%pPAs",
-                                  &up->sg.grp);
-                       snprintfrr(src_str, sizeof(src_str), "%pPAs",
-                                  &up->sg.src);
-
-                       json_object_object_get_ex(json, grp_str, &json_group);
-
-                       if (!json_group) {
-                               json_group = json_object_new_object();
-                               json_object_object_add(json, grp_str,
-                                                      json_group);
-                       }
-
-                       json_row = json_object_new_object();
-                       json_object_pim_upstream_add(json_row, up);
-                       json_object_string_add(json_row, "source", src_str);
-                       json_object_string_add(json_row, "group", grp_str);
-                       json_object_string_add(json_row, "rpfInterface",
-                                              rpf_ifname);
-                       json_object_string_add(json_row, "ribNexthop",
-                                              rpf_nexthop_str);
-                       json_object_string_add(json_row, "rpfAddress",
-                                              rpf_addr_str);
-                       json_object_object_add(json_group, src_str, json_row);
-               } else {
-                       vty_out(vty, "%-15pPAs %-15pPAs %-16s %-15s %-15s\n",
-                               &up->sg.src, &up->sg.grp, rpf_ifname,
-                               rpf_nexthop_str, rpf_addr_str);
-               }
-       }
-
-       if (uj)
-               vty_json(vty, json);
-}
-
-static void show_rpf_refresh_stats(struct vty *vty, struct pim_instance *pim,
-                                  time_t now, json_object *json)
-{
-       char refresh_uptime[10];
-
-       pim_time_uptime_begin(refresh_uptime, sizeof(refresh_uptime), now,
-                             pim->rpf_cache_refresh_last);
-
-       if (json) {
-               json_object_int_add(json, "rpfCacheRefreshDelayMsecs",
-                                   router->rpf_cache_refresh_delay_msec);
-               json_object_int_add(
-                       json, "rpfCacheRefreshTimer",
-                       pim_time_timer_remain_msec(pim->rpf_cache_refresher));
-               json_object_int_add(json, "rpfCacheRefreshRequests",
-                                   pim->rpf_cache_refresh_requests);
-               json_object_int_add(json, "rpfCacheRefreshEvents",
-                                   pim->rpf_cache_refresh_events);
-               json_object_string_add(json, "rpfCacheRefreshLast",
-                                      refresh_uptime);
-               json_object_int_add(json, "nexthopLookups",
-                                   pim->nexthop_lookups);
-               json_object_int_add(json, "nexthopLookupsAvoided",
-                                   pim->nexthop_lookups_avoided);
-       } else {
-               vty_out(vty,
-                       "RPF Cache Refresh Delay:    %ld msecs\n"
-                       "RPF Cache Refresh Timer:    %ld msecs\n"
-                       "RPF Cache Refresh Requests: %lld\n"
-                       "RPF Cache Refresh Events:   %lld\n"
-                       "RPF Cache Refresh Last:     %s\n"
-                       "Nexthop Lookups:            %lld\n"
-                       "Nexthop Lookups Avoided:    %lld\n",
-                       router->rpf_cache_refresh_delay_msec,
-                       pim_time_timer_remain_msec(pim->rpf_cache_refresher),
-                       (long long)pim->rpf_cache_refresh_requests,
-                       (long long)pim->rpf_cache_refresh_events,
-                       refresh_uptime, (long long)pim->nexthop_lookups,
-                       (long long)pim->nexthop_lookups_avoided);
-       }
-}
-
 static void show_scan_oil_stats(struct pim_instance *pim, struct vty *vty,
                                time_t now)
 {
@@ -2919,85 +2209,6 @@ static void show_scan_oil_stats(struct pim_instance *pim, struct vty *vty,
                uptime_mroute_del, (long long)pim->mroute_del_events);
 }
 
-static void pim_show_rpf(struct pim_instance *pim, struct vty *vty, bool uj)
-{
-       struct pim_upstream *up;
-       time_t now = pim_time_monotonic_sec();
-       json_object *json = NULL;
-       json_object *json_group = NULL;
-       json_object *json_row = NULL;
-
-       if (uj) {
-               json = json_object_new_object();
-               show_rpf_refresh_stats(vty, pim, now, json);
-       } else {
-               show_rpf_refresh_stats(vty, pim, now, json);
-               vty_out(vty, "\n");
-               vty_out(vty,
-                       "Source          Group           RpfIface         RpfAddress      RibNextHop      Metric Pref\n");
-       }
-
-       frr_each (rb_pim_upstream, &pim->upstream_head, up) {
-               char rpf_addr_str[PREFIX_STRLEN];
-               char rib_nexthop_str[PREFIX_STRLEN];
-               const char *rpf_ifname;
-               struct pim_rpf *rpf = &up->rpf;
-
-               pim_addr_dump("<rpf?>", &rpf->rpf_addr, rpf_addr_str,
-                             sizeof(rpf_addr_str));
-               pim_addr_dump("<nexthop?>",
-                             &rpf->source_nexthop.mrib_nexthop_addr,
-                             rib_nexthop_str, sizeof(rib_nexthop_str));
-
-               rpf_ifname = rpf->source_nexthop.interface ? rpf->source_nexthop.interface->name : "<ifname?>";
-
-               if (uj) {
-                       char grp_str[PIM_ADDRSTRLEN];
-                       char src_str[PIM_ADDRSTRLEN];
-
-                       snprintfrr(grp_str, sizeof(grp_str), "%pPAs",
-                                  &up->sg.grp);
-                       snprintfrr(src_str, sizeof(src_str), "%pPAs",
-                                  &up->sg.src);
-
-                       json_object_object_get_ex(json, grp_str, &json_group);
-
-                       if (!json_group) {
-                               json_group = json_object_new_object();
-                               json_object_object_add(json, grp_str,
-                                                      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, "rpfInterface",
-                                              rpf_ifname);
-                       json_object_string_add(json_row, "rpfAddress",
-                                              rpf_addr_str);
-                       json_object_string_add(json_row, "ribNexthop",
-                                              rib_nexthop_str);
-                       json_object_int_add(
-                               json_row, "routeMetric",
-                               rpf->source_nexthop.mrib_route_metric);
-                       json_object_int_add(
-                               json_row, "routePreference",
-                               rpf->source_nexthop.mrib_metric_preference);
-                       json_object_object_add(json_group, src_str, json_row);
-
-               } else {
-                       vty_out(vty, "%-15pPAs %-15pPAs %-16s %-15s %-15s %6d %4d\n",
-                               &up->sg.src, &up->sg.grp, rpf_ifname,
-                               rpf_addr_str, rib_nexthop_str,
-                               rpf->source_nexthop.mrib_route_metric,
-                               rpf->source_nexthop.mrib_metric_preference);
-               }
-       }
-
-       if (uj)
-               vty_json(vty, json);
-}
-
 struct pnc_cache_walk_data {
        struct vty *vty;
        struct pim_instance *pim;
@@ -3325,78 +2536,6 @@ static void pim_show_group_rp_mappings_info(struct pim_instance *pim,
                vty_json(vty, json);
 }
 
-/* pim statistics - just adding only bsm related now.
- * We can continue to add all pim related stats here.
- */
-static void pim_show_statistics(struct pim_instance *pim, struct vty *vty,
-                               const char *ifname, bool uj)
-{
-       json_object *json = NULL;
-       struct interface *ifp;
-
-       if (uj) {
-               json = json_object_new_object();
-               json_object_int_add(json, "bsmRx", pim->bsm_rcvd);
-               json_object_int_add(json, "bsmTx", pim->bsm_sent);
-               json_object_int_add(json, "bsmDropped", pim->bsm_dropped);
-       } else {
-               vty_out(vty, "BSM Statistics :\n");
-               vty_out(vty, "----------------\n");
-               vty_out(vty, "Number of Received BSMs : %" PRIu64 "\n",
-                       pim->bsm_rcvd);
-               vty_out(vty, "Number of Forwared BSMs : %" PRIu64 "\n",
-                       pim->bsm_sent);
-               vty_out(vty, "Number of Dropped BSMs  : %" PRIu64 "\n",
-                       pim->bsm_dropped);
-       }
-
-       vty_out(vty, "\n");
-
-       /* scan interfaces */
-       FOR_ALL_INTERFACES (pim->vrf, ifp) {
-               struct pim_interface *pim_ifp = ifp->info;
-
-               if (ifname && strcmp(ifname, ifp->name))
-                       continue;
-
-               if (!pim_ifp)
-                       continue;
-
-               if (!uj) {
-                       vty_out(vty, "Interface : %s\n", ifp->name);
-                       vty_out(vty, "-------------------\n");
-                       vty_out(vty,
-                               "Number of BSMs dropped due to config miss : %u\n",
-                               pim_ifp->pim_ifstat_bsm_cfg_miss);
-                       vty_out(vty, "Number of unicast BSMs dropped : %u\n",
-                               pim_ifp->pim_ifstat_ucast_bsm_cfg_miss);
-                       vty_out(vty,
-                               "Number of BSMs dropped due to invalid scope zone : %u\n",
-                               pim_ifp->pim_ifstat_bsm_invalid_sz);
-               } else {
-
-                       json_object *json_row = NULL;
-
-                       json_row = json_object_new_object();
-
-                       json_object_string_add(json_row, "If Name", ifp->name);
-                       json_object_int_add(json_row, "bsmDroppedConfig",
-                                           pim_ifp->pim_ifstat_bsm_cfg_miss);
-                       json_object_int_add(
-                               json_row, "bsmDroppedUnicast",
-                               pim_ifp->pim_ifstat_ucast_bsm_cfg_miss);
-                       json_object_int_add(json_row,
-                                           "bsmDroppedInvalidScopeZone",
-                                           pim_ifp->pim_ifstat_bsm_invalid_sz);
-                       json_object_object_add(json, ifp->name, json_row);
-               }
-               vty_out(vty, "\n");
-       }
-
-       if (uj)
-               vty_json(vty, json);
-}
-
 static void clear_pim_statistics(struct pim_instance *pim)
 {
        struct interface *ifp;
index 89a4e6e69903f82472759348f7658b3244aa0066..8022eeea0ecfe474bac74bcf61f585b849474631 100644 (file)
 
 void pim_cmd_init(void);
 
-/*
- * Special Macro to allow us to get the correct pim_instance;
- */
-#define PIM_DECLVAR_CONTEXT(A, B)                                              \
-       struct vrf *A = VTY_GET_CONTEXT(vrf);                                  \
-       struct pim_instance *B =                                               \
-               (vrf) ? vrf->info : pim_get_pim_instance(VRF_DEFAULT);         \
-       vrf = (vrf) ? vrf : pim->vrf;
-
 #endif /* PIM_CMD_H */
index c5d89f80650e691d419a233eecf8be278b61806a..6894556bfab3c5339e4675318d383f9ff6d1b460 100644 (file)
 #include "pim_errors.h"
 #include "pim_nb.h"
 #include "pim_cmd_common.h"
+#include "pim_mroute.h"
+#include "pim_cmd.h"
+#include "pim6_cmd.h"
+#include "pim_cmd_common.h"
+#include "pim_time.h"
+#include "pim_zebra.h"
+#include "pim_zlookup.h"
+#include "pim_iface.h"
+#include "lib/linklist.h"
+#include "pim_neighbor.h"
 
 /**
  * Get current node VRF name.
@@ -653,3 +663,873 @@ int pim_process_no_rp_plist_cmd(struct vty *vty, const char *rp_str,
 
        return nb_cli_apply_changes(vty, NULL);
 }
+
+void json_object_pim_upstream_add(json_object *json, struct pim_upstream *up)
+{
+       if (up->flags & PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED)
+               json_object_boolean_true_add(json, "drJoinDesired");
+
+       if (up->flags & PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED_UPDATED)
+               json_object_boolean_true_add(json, "drJoinDesiredUpdated");
+
+       if (up->flags & PIM_UPSTREAM_FLAG_MASK_FHR)
+               json_object_boolean_true_add(json, "firstHopRouter");
+
+       if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP)
+               json_object_boolean_true_add(json, "sourceIgmp");
+
+       if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_PIM)
+               json_object_boolean_true_add(json, "sourcePim");
+
+       if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_STREAM)
+               json_object_boolean_true_add(json, "sourceStream");
+
+       /* 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 *
+pim_upstream_state2brief_str(enum pim_upstream_state join_state,
+                            char *state_str, size_t state_str_len)
+{
+       switch (join_state) {
+       case PIM_UPSTREAM_NOTJOINED:
+               strlcpy(state_str, "NotJ", state_str_len);
+               break;
+       case PIM_UPSTREAM_JOINED:
+               strlcpy(state_str, "J", state_str_len);
+               break;
+       default:
+               strlcpy(state_str, "Unk", state_str_len);
+       }
+       return state_str;
+}
+
+static const char *pim_reg_state2brief_str(enum pim_reg_state reg_state,
+                                          char *state_str,
+                                          size_t state_str_len)
+{
+       switch (reg_state) {
+       case PIM_REG_NOINFO:
+               strlcpy(state_str, "RegNI", state_str_len);
+               break;
+       case PIM_REG_JOIN:
+               strlcpy(state_str, "RegJ", state_str_len);
+               break;
+       case PIM_REG_JOIN_PENDING:
+       case PIM_REG_PRUNE:
+               strlcpy(state_str, "RegP", state_str_len);
+               break;
+       }
+       return state_str;
+}
+
+void show_rpf_refresh_stats(struct vty *vty, struct pim_instance *pim,
+                           time_t now, json_object *json)
+{
+       char refresh_uptime[10];
+
+       pim_time_uptime_begin(refresh_uptime, sizeof(refresh_uptime), now,
+                             pim->rpf_cache_refresh_last);
+
+       if (json) {
+               json_object_int_add(json, "rpfCacheRefreshDelayMsecs",
+                                   router->rpf_cache_refresh_delay_msec);
+               json_object_int_add(
+                       json, "rpfCacheRefreshTimer",
+                       pim_time_timer_remain_msec(pim->rpf_cache_refresher));
+               json_object_int_add(json, "rpfCacheRefreshRequests",
+                                   pim->rpf_cache_refresh_requests);
+               json_object_int_add(json, "rpfCacheRefreshEvents",
+                                   pim->rpf_cache_refresh_events);
+               json_object_string_add(json, "rpfCacheRefreshLast",
+                                      refresh_uptime);
+               json_object_int_add(json, "nexthopLookups",
+                                   pim->nexthop_lookups);
+               json_object_int_add(json, "nexthopLookupsAvoided",
+                                   pim->nexthop_lookups_avoided);
+       } else {
+               vty_out(vty,
+                       "RPF Cache Refresh Delay:    %ld msecs\n"
+                       "RPF Cache Refresh Timer:    %ld msecs\n"
+                       "RPF Cache Refresh Requests: %lld\n"
+                       "RPF Cache Refresh Events:   %lld\n"
+                       "RPF Cache Refresh Last:     %s\n"
+                       "Nexthop Lookups:            %lld\n"
+                       "Nexthop Lookups Avoided:    %lld\n",
+                       router->rpf_cache_refresh_delay_msec,
+                       pim_time_timer_remain_msec(pim->rpf_cache_refresher),
+                       (long long)pim->rpf_cache_refresh_requests,
+                       (long long)pim->rpf_cache_refresh_events,
+                       refresh_uptime, (long long)pim->nexthop_lookups,
+                       (long long)pim->nexthop_lookups_avoided);
+       }
+}
+
+void pim_show_rpf(struct pim_instance *pim, struct vty *vty, bool uj)
+{
+       struct pim_upstream *up;
+       time_t now = pim_time_monotonic_sec();
+       json_object *json = NULL;
+       json_object *json_group = NULL;
+       json_object *json_row = NULL;
+
+       if (uj) {
+               json = json_object_new_object();
+               show_rpf_refresh_stats(vty, pim, now, json);
+       } else {
+               show_rpf_refresh_stats(vty, pim, now, json);
+               vty_out(vty, "\n");
+               vty_out(vty,
+                       "Source          Group           RpfIface         RpfAddress      RibNextHop      Metric Pref\n");
+       }
+
+       frr_each (rb_pim_upstream, &pim->upstream_head, up) {
+               char rpf_addr_str[PREFIX_STRLEN];
+               char rib_nexthop_str[PREFIX_STRLEN];
+               const char *rpf_ifname;
+               struct pim_rpf *rpf = &up->rpf;
+
+               pim_addr_dump("<rpf?>", &rpf->rpf_addr, rpf_addr_str,
+                             sizeof(rpf_addr_str));
+               pim_addr_dump("<nexthop?>",
+                             &rpf->source_nexthop.mrib_nexthop_addr,
+                             rib_nexthop_str, sizeof(rib_nexthop_str));
+
+               rpf_ifname = rpf->source_nexthop.interface ? rpf->source_nexthop.interface->name : "<ifname?>";
+
+               if (uj) {
+                       char grp_str[PIM_ADDRSTRLEN];
+                       char src_str[PIM_ADDRSTRLEN];
+
+                       snprintfrr(grp_str, sizeof(grp_str), "%pPAs",
+                                  &up->sg.grp);
+                       snprintfrr(src_str, sizeof(src_str), "%pPAs",
+                                  &up->sg.src);
+
+                       json_object_object_get_ex(json, grp_str, &json_group);
+
+                       if (!json_group) {
+                               json_group = json_object_new_object();
+                               json_object_object_add(json, grp_str,
+                                                      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, "rpfInterface",
+                                              rpf_ifname);
+                       json_object_string_add(json_row, "rpfAddress",
+                                              rpf_addr_str);
+                       json_object_string_add(json_row, "ribNexthop",
+                                              rib_nexthop_str);
+                       json_object_int_add(
+                               json_row, "routeMetric",
+                               rpf->source_nexthop.mrib_route_metric);
+                       json_object_int_add(
+                               json_row, "routePreference",
+                               rpf->source_nexthop.mrib_metric_preference);
+                       json_object_object_add(json_group, src_str, json_row);
+
+               } else {
+                       vty_out(vty, "%-15pPAs %-15pPAs %-16s %-15s %-15s %6d %4d\n",
+                               &up->sg.src, &up->sg.grp, rpf_ifname,
+                               rpf_addr_str, rib_nexthop_str,
+                               rpf->source_nexthop.mrib_route_metric,
+                               rpf->source_nexthop.mrib_metric_preference);
+               }
+       }
+
+       if (uj)
+               vty_json(vty, json);
+}
+
+void pim_show_neighbors_secondary(struct pim_instance *pim, struct vty *vty)
+{
+       struct interface *ifp;
+
+       vty_out(vty,
+               "Interface        Address         Neighbor        Secondary      \n");
+
+       FOR_ALL_INTERFACES (pim->vrf, ifp) {
+               struct pim_interface *pim_ifp;
+               struct in_addr ifaddr;
+               struct listnode *neighnode;
+               struct pim_neighbor *neigh;
+               char buf[PREFIX_STRLEN];
+
+               pim_ifp = ifp->info;
+
+               if (!pim_ifp)
+                       continue;
+
+               if (pim_ifp->pim_sock_fd < 0)
+                       continue;
+
+               ifaddr = pim_ifp->primary_address;
+
+               for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode,
+                                         neigh)) {
+                       char neigh_src_str[INET_ADDRSTRLEN];
+                       struct listnode *prefix_node;
+                       struct prefix *p;
+
+                       if (!neigh->prefix_list)
+                               continue;
+
+                       pim_inet4_dump("<src?>", neigh->source_addr,
+                                      neigh_src_str, sizeof(neigh_src_str));
+
+                       for (ALL_LIST_ELEMENTS_RO(neigh->prefix_list,
+                                                 prefix_node, p))
+                               vty_out(vty, "%-16s %-15s %-15s %-15pFX\n",
+                                       ifp->name,
+                                       inet_ntop(AF_INET, &ifaddr, buf,
+                                                 sizeof(buf)),
+                                       neigh_src_str, p);
+               }
+       }
+}
+
+void pim_show_state(struct pim_instance *pim, struct vty *vty,
+                   const char *src_or_group, const char *group, bool uj)
+{
+       struct channel_oil *c_oil;
+       json_object *json = NULL;
+       json_object *json_group = NULL;
+       json_object *json_ifp_in = NULL;
+       json_object *json_ifp_out = NULL;
+       json_object *json_source = NULL;
+       time_t now;
+       int first_oif;
+
+       now = pim_time_monotonic_sec();
+
+       if (uj) {
+               json = json_object_new_object();
+       } else {
+               vty_out(vty,
+                       "Codes: J -> Pim Join, I -> IGMP Report, S -> Source, * -> Inherited from (*,G), V -> VxLAN, M -> Muted");
+               vty_out(vty,
+                       "\nActive Source           Group            RPT  IIF               OIL\n");
+       }
+
+       frr_each (rb_pim_oil, &pim->channel_oil_head, c_oil) {
+               char grp_str[INET_ADDRSTRLEN];
+               char src_str[INET_ADDRSTRLEN];
+               char in_ifname[INTERFACE_NAMSIZ + 1];
+               char out_ifname[INTERFACE_NAMSIZ + 1];
+               int oif_vif_index;
+               struct interface *ifp_in;
+               bool isRpt;
+
+               first_oif = 1;
+
+               if ((c_oil->up &&
+                    PIM_UPSTREAM_FLAG_TEST_USE_RPT(c_oil->up->flags)) ||
+                   c_oil->oil.mfcc_origin.s_addr == INADDR_ANY)
+                       isRpt = true;
+               else
+                       isRpt = false;
+
+               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,
+                              sizeof(src_str));
+               ifp_in = pim_if_find_by_vif_index(pim, c_oil->oil.mfcc_parent);
+
+               if (ifp_in)
+                       strlcpy(in_ifname, ifp_in->name, sizeof(in_ifname));
+               else
+                       strlcpy(in_ifname, "<iif?>", sizeof(in_ifname));
+
+               if (src_or_group) {
+                       if (strcmp(src_or_group, src_str) &&
+                           strcmp(src_or_group, grp_str))
+                               continue;
+
+                       if (group && strcmp(group, grp_str))
+                               continue;
+               }
+
+               if (uj) {
+
+                       /* Find the group, create it if it doesn't exist */
+                       json_object_object_get_ex(json, grp_str, &json_group);
+
+                       if (!json_group) {
+                               json_group = json_object_new_object();
+                               json_object_object_add(json, grp_str,
+                                                      json_group);
+                       }
+
+                       /* Find the source nested under the group, create it if
+                        * it doesn't exist
+                        */
+                       json_object_object_get_ex(json_group, src_str,
+                                                 &json_source);
+
+                       if (!json_source) {
+                               json_source = json_object_new_object();
+                               json_object_object_add(json_group, src_str,
+                                                      json_source);
+                       }
+
+                       /* Find the inbound interface nested under the source,
+                        * create it if it doesn't exist
+                        */
+                       json_object_object_get_ex(json_source, in_ifname,
+                                                 &json_ifp_in);
+
+                       if (!json_ifp_in) {
+                               json_ifp_in = json_object_new_object();
+                               json_object_object_add(json_source, in_ifname,
+                                                      json_ifp_in);
+                               json_object_int_add(json_source, "Installed",
+                                                   c_oil->installed);
+                               json_object_int_add(json_source, "installed",
+                                                   c_oil->installed);
+                               if (isRpt)
+                                       json_object_boolean_true_add(
+                                               json_source, "isRpt");
+                               else
+                                       json_object_boolean_false_add(
+                                               json_source, "isRpt");
+                               json_object_int_add(json_source, "RefCount",
+                                                   c_oil->oil_ref_count);
+                               json_object_int_add(json_source, "refCount",
+                                                   c_oil->oil_ref_count);
+                               json_object_int_add(json_source, "OilListSize",
+                                                   c_oil->oil_size);
+                               json_object_int_add(json_source, "oilListSize",
+                                                   c_oil->oil_size);
+                               json_object_int_add(
+                                       json_source, "OilRescan",
+                                       c_oil->oil_inherited_rescan);
+                               json_object_int_add(
+                                       json_source, "oilRescan",
+                                       c_oil->oil_inherited_rescan);
+                               json_object_int_add(json_source, "LastUsed",
+                                                   c_oil->cc.lastused);
+                               json_object_int_add(json_source, "lastUsed",
+                                                   c_oil->cc.lastused);
+                               json_object_int_add(json_source, "PacketCount",
+                                                   c_oil->cc.pktcnt);
+                               json_object_int_add(json_source, "packetCount",
+                                                   c_oil->cc.pktcnt);
+                               json_object_int_add(json_source, "ByteCount",
+                                                   c_oil->cc.bytecnt);
+                               json_object_int_add(json_source, "byteCount",
+                                                   c_oil->cc.bytecnt);
+                               json_object_int_add(json_source,
+                                                   "WrongInterface",
+                                                   c_oil->cc.wrong_if);
+                               json_object_int_add(json_source,
+                                                   "wrongInterface",
+                                                   c_oil->cc.wrong_if);
+                       }
+               } else {
+                       vty_out(vty, "%-6d %-15s  %-15s  %-3s  %-16s  ",
+                               c_oil->installed, src_str, grp_str,
+                               isRpt ? "y" : "n", in_ifname);
+               }
+
+               for (oif_vif_index = 0; oif_vif_index < MAXVIFS;
+                    ++oif_vif_index) {
+                       struct interface *ifp_out;
+                       char oif_uptime[10];
+                       int ttl;
+
+                       ttl = c_oil->oil.mfcc_ttls[oif_vif_index];
+                       if (ttl < 1)
+                               continue;
+
+                       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]);
+
+                       if (ifp_out)
+                               strlcpy(out_ifname, ifp_out->name,
+                                       sizeof(out_ifname));
+                       else
+                               strlcpy(out_ifname, "<oif?>",
+                                       sizeof(out_ifname));
+
+                       if (uj) {
+                               json_ifp_out = json_object_new_object();
+                               json_object_string_add(json_ifp_out, "source",
+                                                      src_str);
+                               json_object_string_add(json_ifp_out, "group",
+                                                      grp_str);
+                               json_object_string_add(json_ifp_out,
+                                                      "inboundInterface",
+                                                      in_ifname);
+                               json_object_string_add(json_ifp_out,
+                                                      "outboundInterface",
+                                                      out_ifname);
+                               json_object_int_add(json_ifp_out, "installed",
+                                                   c_oil->installed);
+
+                               json_object_object_add(json_ifp_in, out_ifname,
+                                                      json_ifp_out);
+                       } else {
+                               if (first_oif) {
+                                       first_oif = 0;
+                                       vty_out(vty, "%s(%c%c%c%c%c)",
+                                               out_ifname,
+                                               (c_oil->oif_flags
+                                                        [oif_vif_index] &
+                                                PIM_OIF_FLAG_PROTO_IGMP)
+                                                       ? 'I'
+                                                       : ' ',
+                                               (c_oil->oif_flags
+                                                        [oif_vif_index] &
+                                                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_STAR)
+                                                       ? '*'
+                                                       : ' ',
+                                               (c_oil->oif_flags
+                                                        [oif_vif_index] &
+                                                PIM_OIF_FLAG_MUTE)
+                                                       ? 'M'
+                                                       : ' ');
+                               } else
+                                       vty_out(vty, ", %s(%c%c%c%c%c)",
+                                               out_ifname,
+                                               (c_oil->oif_flags
+                                                        [oif_vif_index] &
+                                                PIM_OIF_FLAG_PROTO_IGMP)
+                                                       ? 'I'
+                                                       : ' ',
+                                               (c_oil->oif_flags
+                                                        [oif_vif_index] &
+                                                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_STAR)
+                                                       ? '*'
+                                                       : ' ',
+                                               (c_oil->oif_flags
+                                                        [oif_vif_index] &
+                                                PIM_OIF_FLAG_MUTE)
+                                                       ? 'M'
+                                                       : ' ');
+                       }
+               }
+
+               if (!uj)
+                       vty_out(vty, "\n");
+       }
+
+
+       if (uj)
+               vty_json(vty, json);
+       else
+               vty_out(vty, "\n");
+}
+
+/* pim statistics - just adding only bsm related now.
+ * We can continue to add all pim related stats here.
+ */
+void pim_show_statistics(struct pim_instance *pim, struct vty *vty,
+                        const char *ifname, bool uj)
+{
+       json_object *json = NULL;
+       struct interface *ifp;
+
+       if (uj) {
+               json = json_object_new_object();
+               json_object_int_add(json, "bsmRx", pim->bsm_rcvd);
+               json_object_int_add(json, "bsmTx", pim->bsm_sent);
+               json_object_int_add(json, "bsmDropped", pim->bsm_dropped);
+       } else {
+               vty_out(vty, "BSM Statistics :\n");
+               vty_out(vty, "----------------\n");
+               vty_out(vty, "Number of Received BSMs : %" PRIu64 "\n",
+                       pim->bsm_rcvd);
+               vty_out(vty, "Number of Forwared BSMs : %" PRIu64 "\n",
+                       pim->bsm_sent);
+               vty_out(vty, "Number of Dropped BSMs  : %" PRIu64 "\n",
+                       pim->bsm_dropped);
+       }
+
+       vty_out(vty, "\n");
+
+       /* scan interfaces */
+       FOR_ALL_INTERFACES (pim->vrf, ifp) {
+               struct pim_interface *pim_ifp = ifp->info;
+
+               if (ifname && strcmp(ifname, ifp->name))
+                       continue;
+
+               if (!pim_ifp)
+                       continue;
+
+               if (!uj) {
+                       vty_out(vty, "Interface : %s\n", ifp->name);
+                       vty_out(vty, "-------------------\n");
+                       vty_out(vty,
+                               "Number of BSMs dropped due to config miss : %u\n",
+                               pim_ifp->pim_ifstat_bsm_cfg_miss);
+                       vty_out(vty, "Number of unicast BSMs dropped : %u\n",
+                               pim_ifp->pim_ifstat_ucast_bsm_cfg_miss);
+                       vty_out(vty,
+                               "Number of BSMs dropped due to invalid scope zone : %u\n",
+                               pim_ifp->pim_ifstat_bsm_invalid_sz);
+               } else {
+
+                       json_object *json_row = NULL;
+
+                       json_row = json_object_new_object();
+
+                       json_object_string_add(json_row, "If Name", ifp->name);
+                       json_object_int_add(json_row, "bsmDroppedConfig",
+                                           pim_ifp->pim_ifstat_bsm_cfg_miss);
+                       json_object_int_add(
+                               json_row, "bsmDroppedUnicast",
+                               pim_ifp->pim_ifstat_ucast_bsm_cfg_miss);
+                       json_object_int_add(json_row,
+                                           "bsmDroppedInvalidScopeZone",
+                                           pim_ifp->pim_ifstat_bsm_invalid_sz);
+                       json_object_object_add(json, ifp->name, json_row);
+               }
+               vty_out(vty, "\n");
+       }
+
+       if (uj)
+               vty_json(vty, json);
+}
+
+void pim_show_upstream(struct pim_instance *pim, struct vty *vty,
+                      pim_sgaddr *sg, bool uj)
+{
+       struct pim_upstream *up;
+       time_t now;
+       json_object *json = NULL;
+       json_object *json_group = NULL;
+       json_object *json_row = NULL;
+
+       now = pim_time_monotonic_sec();
+
+       if (uj)
+               json = json_object_new_object();
+       else
+               vty_out(vty,
+                       "Iif             Source          Group           State       Uptime   JoinTimer RSTimer   KATimer   RefCnt\n");
+
+       frr_each (rb_pim_upstream, &pim->upstream_head, up) {
+               char src_str[INET_ADDRSTRLEN];
+               char grp_str[INET_ADDRSTRLEN];
+               char uptime[10];
+               char join_timer[10];
+               char rs_timer[10];
+               char ka_timer[10];
+               char msdp_reg_timer[10];
+               char state_str[PIM_REG_STATE_STR_LEN];
+
+               if (sg->grp.s_addr != INADDR_ANY &&
+                   sg->grp.s_addr != up->sg.grp.s_addr)
+                       continue;
+               if (sg->src.s_addr != INADDR_ANY &&
+                   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),
+                               now - up->state_transition);
+               pim_time_timer_to_hhmmss(join_timer, sizeof(join_timer),
+                                        up->t_join_timer);
+
+               /*
+                * If the upstream is not dummy and it has a J/P timer for the
+                * neighbor display that
+                */
+               if (!up->t_join_timer && up->rpf.source_nexthop.interface) {
+                       struct pim_neighbor *nbr;
+
+                       nbr = pim_neighbor_find(
+                               up->rpf.source_nexthop.interface,
+                               up->rpf.rpf_addr.u.prefix4);
+                       if (nbr)
+                               pim_time_timer_to_hhmmss(join_timer,
+                                                        sizeof(join_timer),
+                                                        nbr->jp_timer);
+               }
+
+               pim_time_timer_to_hhmmss(rs_timer, sizeof(rs_timer),
+                                        up->t_rs_timer);
+               pim_time_timer_to_hhmmss(ka_timer, sizeof(ka_timer),
+                                        up->t_ka_timer);
+               pim_time_timer_to_hhmmss(msdp_reg_timer, sizeof(msdp_reg_timer),
+                                        up->t_msdp_reg_timer);
+
+               pim_upstream_state2brief_str(up->join_state, state_str,
+                                            sizeof(state_str));
+               if (up->reg_state != PIM_REG_NOINFO) {
+                       char tmp_str[PIM_REG_STATE_STR_LEN];
+                       char tmp[sizeof(state_str) + 1];
+
+                       snprintf(tmp, sizeof(tmp), ",%s",
+                                pim_reg_state2brief_str(up->reg_state, tmp_str,
+                                                        sizeof(tmp_str)));
+                       strlcat(state_str, tmp, sizeof(state_str));
+               }
+
+               if (uj) {
+                       json_object_object_get_ex(json, grp_str, &json_group);
+
+                       if (!json_group) {
+                               json_group = json_object_new_object();
+                               json_object_object_add(json, grp_str,
+                                                      json_group);
+                       }
+
+                       json_row = json_object_new_object();
+                       json_object_pim_upstream_add(json_row, up);
+                       json_object_string_add(
+                               json_row, "inboundInterface",
+                               up->rpf.source_nexthop.interface
+                               ? up->rpf.source_nexthop.interface->name
+                               : "Unknown");
+
+                       /*
+                        * The RPF address we use is slightly different
+                        * based upon what we are looking up.
+                        * If we have a S, list that unless
+                        * we are the FHR, else we just put
+                        * the RP as the rpfAddress
+                        */
+                       if (up->flags & PIM_UPSTREAM_FLAG_MASK_FHR ||
+                           up->sg.src.s_addr == INADDR_ANY) {
+                               char rpf[PREFIX_STRLEN];
+                               struct pim_rpf *rpg;
+
+                               rpg = RP(pim, up->sg.grp);
+                               pim_inet4_dump("<rpf?>",
+                                              rpg->rpf_addr.u.prefix4, rpf,
+                                              sizeof(rpf));
+                               json_object_string_add(json_row, "rpfAddress",
+                                                      rpf);
+                       } else {
+                               json_object_string_add(json_row, "rpfAddress",
+                                                      src_str);
+                       }
+
+                       json_object_string_add(json_row, "source", src_str);
+                       json_object_string_add(json_row, "group", grp_str);
+                       json_object_string_add(json_row, "state", state_str);
+                       json_object_string_add(
+                               json_row, "joinState",
+                               pim_upstream_state2str(up->join_state));
+                       json_object_string_add(
+                               json_row, "regState",
+                               pim_reg_state2str(up->reg_state, state_str,
+                                                 sizeof(state_str)));
+                       json_object_string_add(json_row, "upTime", uptime);
+                       json_object_string_add(json_row, "joinTimer",
+                                              join_timer);
+                       json_object_string_add(json_row, "resetTimer",
+                                              rs_timer);
+                       json_object_string_add(json_row, "keepaliveTimer",
+                                              ka_timer);
+                       json_object_string_add(json_row, "msdpRegTimer",
+                                              msdp_reg_timer);
+                       json_object_int_add(json_row, "refCount",
+                                           up->ref_count);
+                       json_object_int_add(json_row, "sptBit", up->sptbit);
+                       json_object_object_add(json_group, src_str, json_row);
+               } else {
+                       vty_out(vty,
+                               "%-16s%-15s %-15s %-11s %-8s %-9s %-9s %-9s %6d\n",
+                               up->rpf.source_nexthop.interface
+                               ? up->rpf.source_nexthop.interface->name
+                               : "Unknown",
+                               src_str, grp_str, state_str, uptime, join_timer,
+                               rs_timer, ka_timer, up->ref_count);
+               }
+       }
+
+       if (uj)
+               vty_json(vty, json);
+}
+
+static void pim_show_join_desired_helper(struct pim_instance *pim,
+                                        struct vty *vty,
+                                        struct pim_upstream *up,
+                                        json_object *json, bool uj)
+{
+       json_object *json_group = NULL;
+       char src_str[INET_ADDRSTRLEN];
+       char grp_str[INET_ADDRSTRLEN];
+       json_object *json_row = NULL;
+
+       pim_inet4_dump("<src?>", up->sg.src, src_str, sizeof(src_str));
+       pim_inet4_dump("<grp?>", up->sg.grp, grp_str, sizeof(grp_str));
+
+       if (uj) {
+               json_object_object_get_ex(json, grp_str, &json_group);
+
+               if (!json_group) {
+                       json_group = json_object_new_object();
+                       json_object_object_add(json, grp_str, json_group);
+               }
+
+               json_row = json_object_new_object();
+               json_object_pim_upstream_add(json_row, up);
+               json_object_string_add(json_row, "source", src_str);
+               json_object_string_add(json_row, "group", grp_str);
+
+               if (pim_upstream_evaluate_join_desired(pim, up))
+                       json_object_boolean_true_add(json_row,
+                                                    "evaluateJoinDesired");
+
+               json_object_object_add(json_group, src_str, json_row);
+
+       } else {
+               vty_out(vty, "%-15s %-15s %-6s\n", src_str, grp_str,
+                       pim_upstream_evaluate_join_desired(pim, up) ? "yes"
+                                                                   : "no");
+       }
+}
+
+void pim_show_join_desired(struct pim_instance *pim, struct vty *vty, bool uj)
+{
+       struct pim_upstream *up;
+
+       json_object *json = NULL;
+
+       if (uj)
+               json = json_object_new_object();
+       else
+               vty_out(vty, "Source          Group           EvalJD\n");
+
+       frr_each (rb_pim_upstream, &pim->upstream_head, up) {
+               /* scan all interfaces */
+               pim_show_join_desired_helper(pim, vty, up, json, uj);
+       }
+
+       if (uj)
+               vty_json(vty, json);
+}
+
+void pim_show_upstream_rpf(struct pim_instance *pim, struct vty *vty, bool uj)
+{
+       struct pim_upstream *up;
+       json_object *json = NULL;
+       json_object *json_group = NULL;
+       json_object *json_row = NULL;
+
+       if (uj)
+               json = json_object_new_object();
+       else
+               vty_out(vty,
+                       "Source          Group           RpfIface         RibNextHop      RpfAddress     \n");
+
+       frr_each (rb_pim_upstream, &pim->upstream_head, up) {
+               char src_str[INET_ADDRSTRLEN];
+               char grp_str[INET_ADDRSTRLEN];
+               char rpf_nexthop_str[PREFIX_STRLEN];
+               char rpf_addr_str[PREFIX_STRLEN];
+               struct pim_rpf *rpf;
+               const char *rpf_ifname;
+
+               rpf = &up->rpf;
+
+               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_addr_dump("<nexthop?>",
+                             &rpf->source_nexthop.mrib_nexthop_addr,
+                             rpf_nexthop_str, sizeof(rpf_nexthop_str));
+               pim_addr_dump("<rpf?>", &rpf->rpf_addr, rpf_addr_str,
+                             sizeof(rpf_addr_str));
+
+               rpf_ifname =
+                       rpf->source_nexthop.interface ? rpf->source_nexthop
+                                                               .interface->name
+                                                     : "<ifname?>";
+
+               if (uj) {
+                       json_object_object_get_ex(json, grp_str, &json_group);
+
+                       if (!json_group) {
+                               json_group = json_object_new_object();
+                               json_object_object_add(json, grp_str,
+                                                      json_group);
+                       }
+
+                       json_row = json_object_new_object();
+                       json_object_pim_upstream_add(json_row, up);
+                       json_object_string_add(json_row, "source", src_str);
+                       json_object_string_add(json_row, "group", grp_str);
+                       json_object_string_add(json_row, "rpfInterface",
+                                              rpf_ifname);
+                       json_object_string_add(json_row, "ribNexthop",
+                                              rpf_nexthop_str);
+                       json_object_string_add(json_row, "rpfAddress",
+                                              rpf_addr_str);
+                       json_object_object_add(json_group, src_str, json_row);
+               } else {
+                       vty_out(vty, "%-15s %-15s %-16s %-15s %-15s\n", src_str,
+                               grp_str, rpf_ifname, rpf_nexthop_str,
+                               rpf_addr_str);
+               }
+       }
+
+       if (uj)
+               vty_json(vty, json);
+}
index b7e6b6ac80885bcc88890a87a874e070e13ab4cd..6034df68283ee8c479af565597e8d358d43c90e6 100644 (file)
@@ -58,5 +58,27 @@ int pim_process_ip_mroute_cmd(struct vty *vty, const char *interface,
                              const char *group_str, const char *source_str);
 int pim_process_no_ip_mroute_cmd(struct vty *vty, const char *interface,
                                 const char *group_str, const char *src_str);
+void json_object_pim_upstream_add(json_object *json, struct pim_upstream *up);
+void pim_show_rpf(struct pim_instance *pim, struct vty *vty, bool uj);
+void pim_show_neighbors_secondary(struct pim_instance *pim, struct vty *vty);
+void pim_show_state(struct pim_instance *pim, struct vty *vty,
+                   const char *src_or_group, const char *group, bool uj);
+void pim_show_statistics(struct pim_instance *pim, struct vty *vty,
+                        const char *ifname, bool uj);
+void pim_show_upstream(struct pim_instance *pim, struct vty *vty,
+                      pim_sgaddr *sg, bool uj);
+void pim_show_join_desired(struct pim_instance *pim, struct vty *vty, bool uj);
+void pim_show_upstream_rpf(struct pim_instance *pim, struct vty *vty, bool uj);
+void show_rpf_refresh_stats(struct vty *vty, struct pim_instance *pim,
+                           time_t now, json_object *json);
+
+/*
+ * Special Macro to allow us to get the correct pim_instance;
+ */
+#define PIM_DECLVAR_CONTEXT(A, B)                                              \
+       struct vrf *A = VTY_GET_CONTEXT(vrf);                                  \
+       struct pim_instance *B =                                               \
+               (vrf) ? vrf->info : pim_get_pim_instance(VRF_DEFAULT);         \
+       vrf = (vrf) ? vrf : pim->vrf
 
 #endif /* PIM_CMD_COMMON_H */