back to topotato report
topotato coverage report
Current view: top level - pimd - pim_nb_config.c (source / functions) Hit Total Coverage
Test: test_pim_basic2.py::PIMTopo2Test Lines: 101 1193 8.5 %
Date: 2023-02-24 18:39:36 Functions: 11 106 10.4 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (C) 2020 VmWare
       3             :  *                    Sarita Patra
       4             :  *
       5             :  * This program is free software; you can redistribute it and/or modify it
       6             :  * under the terms of the GNU General Public License as published by the Free
       7             :  * Software Foundation; either version 2 of the License, or (at your option)
       8             :  * any later version.
       9             :  *
      10             :  * This program is distributed in the hope that it will be useful, but WITHOUT
      11             :  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
      12             :  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
      13             :  * more details.
      14             :  *
      15             :  * You should have received a copy of the GNU General Public License along
      16             :  * with this program; see the file COPYING; if not, write to the Free Software
      17             :  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
      18             :  */
      19             : 
      20             : #include <zebra.h>
      21             : 
      22             : #include "pimd.h"
      23             : #include "pim_nb.h"
      24             : #include "lib/northbound_cli.h"
      25             : #include "pim_igmpv3.h"
      26             : #include "pim_neighbor.h"
      27             : #include "pim_nht.h"
      28             : #include "pim_pim.h"
      29             : #include "pim_mlag.h"
      30             : #include "pim_bfd.h"
      31             : #include "pim_static.h"
      32             : #include "pim_ssm.h"
      33             : #include "pim_ssmpingd.h"
      34             : #include "pim_vxlan.h"
      35             : #include "pim_util.h"
      36             : #include "log.h"
      37             : #include "lib_errors.h"
      38             : #include "pim_util.h"
      39             : #include "pim6_mld.h"
      40             : 
      41             : #if PIM_IPV == 6
      42             : #define pim6_msdp_err(funcname, argtype)                                       \
      43             : int funcname(struct argtype *args)                                             \
      44             : {                                                                              \
      45             :         snprintf(args->errmsg, args->errmsg_len,                               \
      46             :                  "Trying to configure MSDP in pim6d.  "                        \
      47             :                  "MSDP does not exist for IPv6.");                             \
      48             :         return NB_ERR_VALIDATION;                                              \
      49             : }                                                                              \
      50             : MACRO_REQUIRE_SEMICOLON()
      51             : 
      52             : #define yang_dnode_get_pimaddr yang_dnode_get_ipv6
      53             : 
      54             : #else /* PIM_IPV != 6 */
      55             : #define pim6_msdp_err(funcname, argtype)                                       \
      56             : MACRO_REQUIRE_SEMICOLON()
      57             : 
      58             : #define yang_dnode_get_pimaddr yang_dnode_get_ipv4
      59             : #endif /* PIM_IPV != 6 */
      60             : 
      61           0 : static void pim_if_membership_clear(struct interface *ifp)
      62             : {
      63           0 :         struct pim_interface *pim_ifp;
      64             : 
      65           0 :         pim_ifp = ifp->info;
      66           0 :         assert(pim_ifp);
      67             : 
      68           0 :         if (pim_ifp->pim_enable && pim_ifp->gm_enable) {
      69             :                 return;
      70             :         }
      71             : 
      72           0 :         pim_ifchannel_membership_clear(ifp);
      73             : }
      74             : 
      75             : /*
      76             :  * When PIM is disabled on interface, IGMPv3 local membership
      77             :  * information is not injected into PIM interface state.
      78             : 
      79             :  * The function pim_if_membership_refresh() fetches all IGMPv3 local
      80             :  * membership information into PIM. It is intented to be called
      81             :  * whenever PIM is enabled on the interface in order to collect missed
      82             :  * local membership information.
      83             :  */
      84           6 : static void pim_if_membership_refresh(struct interface *ifp)
      85             : {
      86           6 :         struct pim_interface *pim_ifp;
      87           6 :         struct listnode *grpnode;
      88           6 :         struct gm_group *grp;
      89             : 
      90             : 
      91           6 :         pim_ifp = ifp->info;
      92           6 :         assert(pim_ifp);
      93             : 
      94           6 :         if (!pim_ifp->pim_enable)
      95             :                 return;
      96           6 :         if (!pim_ifp->gm_enable)
      97             :                 return;
      98             : 
      99             :         /*
     100             :          * First clear off membership from all PIM (S,G) entries on the
     101             :          * interface
     102             :          */
     103             : 
     104           0 :         pim_ifchannel_membership_clear(ifp);
     105             : 
     106             :         /*
     107             :          * Then restore PIM (S,G) membership from all IGMPv3 (S,G) entries on
     108             :          * the interface
     109             :          */
     110             : 
     111             :         /* scan igmp groups */
     112           0 :         for (ALL_LIST_ELEMENTS_RO(pim_ifp->gm_group_list, grpnode, grp)) {
     113           0 :                 struct listnode *srcnode;
     114           0 :                 struct gm_source *src;
     115             : 
     116             :                 /* scan group sources */
     117           0 :                 for (ALL_LIST_ELEMENTS_RO(grp->group_source_list, srcnode,
     118             :                                           src)) {
     119             : 
     120           0 :                         if (IGMP_SOURCE_TEST_FORWARDING(src->source_flags)) {
     121           0 :                                 pim_sgaddr sg;
     122             : 
     123           0 :                                 memset(&sg, 0, sizeof(sg));
     124           0 :                                 sg.src = src->source_addr;
     125           0 :                                 sg.grp = grp->group_addr;
     126           0 :                                 pim_ifchannel_local_membership_add(
     127             :                                         ifp, &sg, false /*is_vxlan*/);
     128             :                         }
     129             : 
     130             :                 } /* scan group sources */
     131             :         }        /* scan igmp groups */
     132             : 
     133             :         /*
     134             :          * Finally delete every PIM (S,G) entry lacking all state info
     135             :          */
     136             : 
     137           0 :         pim_ifchannel_delete_on_noinfo(ifp);
     138             : }
     139             : 
     140           6 : static int pim_cmd_interface_add(struct interface *ifp)
     141             : {
     142           6 :         struct pim_interface *pim_ifp = ifp->info;
     143             : 
     144           6 :         if (!pim_ifp)
     145           6 :                 pim_ifp = pim_if_new(ifp, false, true, false, false);
     146             :         else
     147           0 :                 pim_ifp->pim_enable = true;
     148             : 
     149           6 :         pim_if_addr_add_all(ifp);
     150           6 :         pim_upstream_nh_if_update(pim_ifp->pim, ifp);
     151           6 :         pim_if_membership_refresh(ifp);
     152             : 
     153           6 :         pim_if_create_pimreg(pim_ifp->pim);
     154           6 :         return 1;
     155             : }
     156             : 
     157           0 : static int pim_cmd_interface_delete(struct interface *ifp)
     158             : {
     159           0 :         struct pim_interface *pim_ifp = ifp->info;
     160             : 
     161           0 :         if (!pim_ifp)
     162             :                 return 1;
     163             : 
     164           0 :         pim_ifp->pim_enable = false;
     165             : 
     166           0 :         pim_if_membership_clear(ifp);
     167             : 
     168             :         /*
     169             :          * pim_sock_delete() removes all neighbors from
     170             :          * pim_ifp->pim_neighbor_list.
     171             :          */
     172           0 :         pim_sock_delete(ifp, "pim unconfigured on interface");
     173             : 
     174           0 :         if (!pim_ifp->gm_enable) {
     175           0 :                 pim_if_addr_del_all(ifp);
     176           0 :                 pim_upstream_nh_if_update(pim_ifp->pim, ifp);
     177           0 :                 pim_if_delete(ifp);
     178             :         }
     179             : 
     180             :         return 1;
     181             : }
     182             : 
     183           0 : static int interface_pim_use_src_cmd_worker(struct interface *ifp,
     184             :                 pim_addr source_addr, char *errmsg, size_t errmsg_len)
     185             : {
     186           0 :         int result;
     187           0 :         int ret = NB_OK;
     188             : 
     189           0 :         result = pim_update_source_set(ifp, source_addr);
     190             : 
     191           0 :         switch (result) {
     192             :         case PIM_SUCCESS:
     193             :                 break;
     194           0 :         case PIM_IFACE_NOT_FOUND:
     195           0 :                 ret = NB_ERR;
     196           0 :                 snprintf(errmsg, errmsg_len,
     197             :                          "Pim not enabled on this interface %s",
     198           0 :                          ifp->name);
     199           0 :                         break;
     200           0 :         case PIM_UPDATE_SOURCE_DUP:
     201           0 :                 ret = NB_ERR;
     202           0 :                 snprintf(errmsg, errmsg_len, "Source already set");
     203           0 :                 break;
     204           0 :         default:
     205           0 :                 ret = NB_ERR;
     206           0 :                 snprintf(errmsg, errmsg_len, "Source set failed");
     207             :         }
     208             : 
     209           0 :         return ret;
     210             : }
     211             : 
     212           0 : static int pim_cmd_spt_switchover(struct pim_instance *pim,
     213             :                 enum pim_spt_switchover spt,
     214             :                 const char *plist)
     215             : {
     216           0 :         pim->spt.switchover = spt;
     217             : 
     218           0 :         switch (pim->spt.switchover) {
     219           0 :         case PIM_SPT_IMMEDIATE:
     220           0 :                 XFREE(MTYPE_PIM_PLIST_NAME, pim->spt.plist);
     221             : 
     222           0 :                 pim_upstream_add_lhr_star_pimreg(pim);
     223           0 :                 break;
     224           0 :         case PIM_SPT_INFINITY:
     225           0 :                 pim_upstream_remove_lhr_star_pimreg(pim, plist);
     226             : 
     227           0 :                 XFREE(MTYPE_PIM_PLIST_NAME, pim->spt.plist);
     228             : 
     229           0 :                 if (plist)
     230           0 :                         pim->spt.plist = XSTRDUP(MTYPE_PIM_PLIST_NAME, plist);
     231             :                 break;
     232             :         }
     233             : 
     234           0 :         return NB_OK;
     235             : }
     236             : 
     237           0 : static int pim_ssm_cmd_worker(struct pim_instance *pim, const char *plist,
     238             :                 char *errmsg, size_t errmsg_len)
     239             : {
     240           0 :         int result = pim_ssm_range_set(pim, pim->vrf->vrf_id, plist);
     241           0 :         int ret = NB_ERR;
     242             : 
     243           0 :         if (result == PIM_SSM_ERR_NONE)
     244             :                 return NB_OK;
     245             : 
     246           0 :         switch (result) {
     247           0 :         case PIM_SSM_ERR_NO_VRF:
     248           0 :                 snprintf(errmsg, errmsg_len,
     249             :                          "VRF doesn't exist");
     250           0 :                 break;
     251           0 :         case PIM_SSM_ERR_DUP:
     252           0 :                 snprintf(errmsg, errmsg_len,
     253             :                          "duplicate config");
     254           0 :                 break;
     255           0 :         default:
     256           0 :                 snprintf(errmsg, errmsg_len,
     257             :                          "ssm range config failed");
     258             :         }
     259             : 
     260             :         return ret;
     261             : }
     262             : 
     263           0 : static int pim_rp_cmd_worker(struct pim_instance *pim, pim_addr rp_addr,
     264             :                              struct prefix group, const char *plist,
     265             :                              char *errmsg, size_t errmsg_len)
     266             : {
     267           0 :         int result;
     268             : 
     269           0 :         result = pim_rp_new(pim, rp_addr, group, plist, RP_SRC_STATIC);
     270             : 
     271           0 :         if (result == PIM_RP_NO_PATH) {
     272           0 :                 snprintfrr(errmsg, errmsg_len,
     273             :                            "No Path to RP address specified: %pPA", &rp_addr);
     274           0 :                 return NB_ERR_INCONSISTENCY;
     275             :         }
     276             : 
     277           0 :         if (result == PIM_GROUP_OVERLAP) {
     278           0 :                 snprintf(errmsg, errmsg_len,
     279             :                          "Group range specified cannot exact match another");
     280           0 :                 return NB_ERR_INCONSISTENCY;
     281             :         }
     282             : 
     283           0 :         if (result == PIM_GROUP_PFXLIST_OVERLAP) {
     284           0 :                 snprintf(errmsg, errmsg_len,
     285             :                          "This group is already covered by a RP prefix-list");
     286           0 :                 return NB_ERR_INCONSISTENCY;
     287             :         }
     288             : 
     289           0 :         if (result == PIM_RP_PFXLIST_IN_USE) {
     290           0 :                 snprintf(errmsg, errmsg_len,
     291             :                          "The same prefix-list cannot be applied to multiple RPs");
     292           0 :                 return NB_ERR_INCONSISTENCY;
     293             :         }
     294             : 
     295             :         return NB_OK;
     296             : }
     297             : 
     298           0 : static int pim_no_rp_cmd_worker(struct pim_instance *pim, pim_addr rp_addr,
     299             :                                 struct prefix group, const char *plist,
     300             :                                 char *errmsg, size_t errmsg_len)
     301             : {
     302           0 :         char group_str[PREFIX2STR_BUFFER];
     303           0 :         int result;
     304             : 
     305           0 :         prefix2str(&group, group_str, sizeof(group_str));
     306             : 
     307           0 :         result = pim_rp_del(pim, rp_addr, group, plist, RP_SRC_STATIC);
     308             : 
     309           0 :         if (result == PIM_GROUP_BAD_ADDRESS) {
     310           0 :                 snprintf(errmsg, errmsg_len,
     311             :                          "Bad group address specified: %s", group_str);
     312           0 :                 return NB_ERR_INCONSISTENCY;
     313             :         }
     314             : 
     315           0 :         if (result == PIM_RP_BAD_ADDRESS) {
     316           0 :                 snprintfrr(errmsg, errmsg_len, "Bad RP address specified: %pPA",
     317             :                            &rp_addr);
     318           0 :                 return NB_ERR_INCONSISTENCY;
     319             :         }
     320             : 
     321           0 :         if (result == PIM_RP_NOT_FOUND) {
     322           0 :                 snprintf(errmsg, errmsg_len,
     323             :                          "Unable to find specified RP");
     324           0 :                 return NB_ERR_INCONSISTENCY;
     325             :         }
     326             : 
     327             :         return NB_OK;
     328             : }
     329             : 
     330           0 : static bool is_pim_interface(const struct lyd_node *dnode)
     331             : {
     332           0 :         char if_xpath[XPATH_MAXLEN];
     333           0 :         const struct lyd_node *pim_enable_dnode;
     334           0 :         const struct lyd_node *igmp_enable_dnode;
     335             : 
     336           0 :         yang_dnode_get_path(dnode, if_xpath, sizeof(if_xpath));
     337           0 :         pim_enable_dnode =
     338           0 :                 yang_dnode_getf(dnode,
     339             :                                 "%s/frr-pim:pim/address-family[address-family='%s']/pim-enable",
     340             :                                 if_xpath, FRR_PIM_AF_XPATH_VAL);
     341           0 :         igmp_enable_dnode = yang_dnode_getf(dnode,
     342             :                         "%s/frr-gmp:gmp/address-family[address-family='%s']/enable",
     343             :                         if_xpath, FRR_PIM_AF_XPATH_VAL);
     344             : 
     345           0 :         if (((pim_enable_dnode) &&
     346           0 :              (yang_dnode_get_bool(pim_enable_dnode, "."))) ||
     347           0 :              ((igmp_enable_dnode) &&
     348           0 :              (yang_dnode_get_bool(igmp_enable_dnode, "."))))
     349           0 :                 return true;
     350             : 
     351             :         return false;
     352             : }
     353             : 
     354           0 : static int pim_cmd_gm_start(struct interface *ifp)
     355             : {
     356           0 :         struct pim_interface *pim_ifp;
     357           0 :         uint8_t need_startup = 0;
     358             : 
     359           0 :         pim_ifp = ifp->info;
     360             : 
     361           0 :         if (!pim_ifp) {
     362           0 :                 pim_ifp = pim_if_new(ifp, true, false, false, false);
     363           0 :                 need_startup = 1;
     364             :         } else {
     365           0 :                 if (!pim_ifp->gm_enable) {
     366           0 :                         pim_ifp->gm_enable = true;
     367           0 :                         need_startup = 1;
     368             :                 }
     369             :         }
     370           0 :         pim_if_create_pimreg(pim_ifp->pim);
     371             : 
     372             :         /* 'ip igmp' executed multiple times, with need_startup
     373             :          * avoid multiple if add all and membership refresh
     374             :          */
     375           0 :         if (need_startup) {
     376           0 :                 pim_if_addr_add_all(ifp);
     377           0 :                 pim_if_membership_refresh(ifp);
     378             :         }
     379             : 
     380           0 :         return NB_OK;
     381             : }
     382             : 
     383             : /*
     384             :  * CLI reconfiguration affects the interface level (struct pim_interface).
     385             :  * This function propagates the reconfiguration to every active socket
     386             :  * for that interface.
     387             :  */
     388             : #if PIM_IPV == 4
     389           0 : static void igmp_sock_query_interval_reconfig(struct gm_sock *igmp)
     390             : {
     391           0 :         struct interface *ifp;
     392           0 :         struct pim_interface *pim_ifp;
     393             : 
     394           0 :         assert(igmp);
     395           0 :         assert(igmp->interface);
     396           0 :         assert(igmp->interface->info);
     397             : 
     398           0 :         ifp = igmp->interface;
     399           0 :         pim_ifp = ifp->info;
     400             : 
     401           0 :         if (PIM_DEBUG_GM_TRACE)
     402           0 :                 zlog_debug("%s: Querier %pPAs on %s reconfig query_interval=%d",
     403             :                            __func__, &igmp->ifaddr, ifp->name,
     404             :                            pim_ifp->gm_default_query_interval);
     405             : 
     406             :         /*
     407             :          * igmp_startup_mode_on() will reset QQI:
     408             : 
     409             :          * igmp->querier_query_interval = pim_ifp->gm_default_query_interval;
     410             :          */
     411           0 :         igmp_startup_mode_on(igmp);
     412           0 : }
     413             : 
     414           0 : static void igmp_sock_query_reschedule(struct gm_sock *igmp)
     415             : {
     416           0 :         if (igmp->mtrace_only)
     417             :                 return;
     418             : 
     419           0 :         if (igmp->t_igmp_query_timer) {
     420             :                 /* other querier present */
     421           0 :                 assert(igmp->t_igmp_query_timer);
     422           0 :                 assert(!igmp->t_other_querier_timer);
     423             : 
     424           0 :                 pim_igmp_general_query_off(igmp);
     425           0 :                 pim_igmp_general_query_on(igmp);
     426             : 
     427           0 :                 assert(igmp->t_igmp_query_timer);
     428           0 :                 assert(!igmp->t_other_querier_timer);
     429             :         } else {
     430             :                 /* this is the querier */
     431             : 
     432           0 :                 assert(!igmp->t_igmp_query_timer);
     433           0 :                 assert(igmp->t_other_querier_timer);
     434             : 
     435           0 :                 pim_igmp_other_querier_timer_off(igmp);
     436           0 :                 pim_igmp_other_querier_timer_on(igmp);
     437             : 
     438           0 :                 assert(!igmp->t_igmp_query_timer);
     439           0 :                 assert(igmp->t_other_querier_timer);
     440             :         }
     441             : }
     442             : #endif /* PIM_IPV == 4 */
     443             : 
     444             : #if PIM_IPV == 4
     445           0 : static void change_query_interval(struct pim_interface *pim_ifp,
     446             :                 int query_interval)
     447             : {
     448           0 :         struct listnode *sock_node;
     449           0 :         struct gm_sock *igmp;
     450             : 
     451           0 :         pim_ifp->gm_default_query_interval = query_interval;
     452             : 
     453           0 :         for (ALL_LIST_ELEMENTS_RO(pim_ifp->gm_socket_list, sock_node, igmp)) {
     454           0 :                 igmp_sock_query_interval_reconfig(igmp);
     455           0 :                 igmp_sock_query_reschedule(igmp);
     456             :         }
     457           0 : }
     458             : #endif
     459             : 
     460           0 : static void change_query_max_response_time(struct interface *ifp,
     461             :                                            int query_max_response_time_dsec)
     462             : {
     463             : #if PIM_IPV == 4
     464           0 :         struct listnode *sock_node;
     465           0 :         struct gm_sock *igmp;
     466           0 :         struct listnode *grp_node;
     467           0 :         struct gm_group *grp;
     468             : #endif
     469             : 
     470           0 :         struct pim_interface *pim_ifp = ifp->info;
     471             : 
     472           0 :         if (pim_ifp->gm_query_max_response_time_dsec ==
     473             :             query_max_response_time_dsec)
     474             :                 return;
     475             : 
     476           0 :         pim_ifp->gm_query_max_response_time_dsec = query_max_response_time_dsec;
     477             : 
     478             : #if PIM_IPV == 6
     479             :         gm_ifp_update(ifp);
     480             : #else
     481             :         /*
     482             :          * Below we modify socket/group/source timers in order to quickly
     483             :          * reflect the change. Otherwise, those timers would args->eventually
     484             :          * catch up.
     485             :          */
     486             : 
     487             :         /* scan all sockets */
     488           0 :         for (ALL_LIST_ELEMENTS_RO(pim_ifp->gm_socket_list, sock_node, igmp)) {
     489             :                 /* reschedule socket general query */
     490           0 :                 igmp_sock_query_reschedule(igmp);
     491             :         }
     492             : 
     493             :         /* scan socket groups */
     494           0 :         for (ALL_LIST_ELEMENTS_RO(pim_ifp->gm_group_list, grp_node, grp)) {
     495           0 :                 struct listnode *src_node;
     496           0 :                 struct gm_source *src;
     497             : 
     498             :                 /* reset group timers for groups in EXCLUDE mode */
     499           0 :                 if (grp->group_filtermode_isexcl)
     500           0 :                         igmp_group_reset_gmi(grp);
     501             : 
     502             :                 /* scan group sources */
     503           0 :                 for (ALL_LIST_ELEMENTS_RO(grp->group_source_list, src_node,
     504             :                                           src)) {
     505             : 
     506             :                         /* reset source timers for sources with running
     507             :                          * timers
     508             :                          */
     509           0 :                         if (src->t_source_timer)
     510           0 :                                 igmp_source_reset_gmi(grp, src);
     511             :                 }
     512             :         }
     513             : #endif /* PIM_IPV == 4 */
     514             : }
     515             : 
     516           0 : int routing_control_plane_protocols_name_validate(
     517             :         struct nb_cb_create_args *args)
     518             : {
     519           0 :         const char *name;
     520             : 
     521           0 :         name = yang_dnode_get_string(args->dnode, "./name");
     522           0 :         if (!strmatch(name, "pim")) {
     523           0 :                 snprintf(args->errmsg, args->errmsg_len,
     524             :                                 "pim supports only one instance with name pimd");
     525           0 :                 return NB_ERR_VALIDATION;
     526             :         }
     527             :         return NB_OK;
     528             : }
     529             : 
     530             : /*
     531             :  * XPath: /frr-pim:pim/address-family
     532             :  */
     533           3 : int pim_address_family_create(struct nb_cb_create_args *args)
     534             : {
     535           3 :         switch (args->event) {
     536             :         case NB_EV_VALIDATE:
     537             :         case NB_EV_PREPARE:
     538             :         case NB_EV_ABORT:
     539             :         case NB_EV_APPLY:
     540             :                 break;
     541             :         }
     542             : 
     543           3 :         return NB_OK;
     544             : }
     545             : 
     546           0 : int pim_address_family_destroy(struct nb_cb_destroy_args *args)
     547             : {
     548           0 :         switch (args->event) {
     549             :         case NB_EV_VALIDATE:
     550             :         case NB_EV_PREPARE:
     551             :         case NB_EV_ABORT:
     552             :         case NB_EV_APPLY:
     553             :                 break;
     554             :         }
     555             : 
     556           0 :         return NB_OK;
     557             : }
     558             : 
     559             : /*
     560             :  * XPath: /frr-pim:pim/address-family/packets
     561             :  */
     562           0 : int pim_address_family_packets_modify(struct nb_cb_modify_args *args)
     563             : {
     564           0 :         switch (args->event) {
     565             :         case NB_EV_VALIDATE:
     566             :         case NB_EV_PREPARE:
     567             :         case NB_EV_ABORT:
     568             :                 break;
     569           0 :         case NB_EV_APPLY:
     570           0 :                 router->packet_process = yang_dnode_get_uint8(args->dnode,
     571             :                                 NULL);
     572           0 :                 break;
     573             :         }
     574             : 
     575           0 :         return NB_OK;
     576             : }
     577             : 
     578             : /*
     579             :  * XPath: /frr-pim:pim/address-family/join-prune-interval
     580             :  */
     581           3 : int pim_address_family_join_prune_interval_modify(
     582             :         struct nb_cb_modify_args *args)
     583             : {
     584           3 :         switch (args->event) {
     585             :         case NB_EV_VALIDATE:
     586             :         case NB_EV_PREPARE:
     587             :         case NB_EV_ABORT:
     588             :                 break;
     589           1 :         case NB_EV_APPLY:
     590           1 :                 router->t_periodic = yang_dnode_get_uint16(args->dnode, NULL);
     591           1 :                 break;
     592             :         }
     593             : 
     594           3 :         return NB_OK;
     595             : }
     596             : 
     597             : /*
     598             :  * XPath: /frr-pim:pim/address-family/register-suppress-time
     599             :  */
     600           0 : int pim_address_family_register_suppress_time_modify(
     601             :         struct nb_cb_modify_args *args)
     602             : {
     603           0 :         uint16_t value;
     604           0 :         switch (args->event) {
     605           0 :         case NB_EV_VALIDATE:
     606           0 :                 value = yang_dnode_get_uint16(args->dnode, NULL);
     607             :                 /*
     608             :                  * As soon as this is non-constant it needs to be replaced with
     609             :                  * a yang_dnode_get to lookup the candidate value, *not* the
     610             :                  * operational value. Since the code has a field assigned and
     611             :                  * used for this value it should have YANG/CLI to set it too,
     612             :                  * otherwise just use the #define!
     613             :                  */
     614             :                 /* RFC7761: 4.11.  Timer Values */
     615           0 :                 if (value <= router->register_probe_time * 2) {
     616           0 :                         snprintf(
     617             :                                 args->errmsg, args->errmsg_len,
     618             :                                 "Register suppress time (%u) must be more than "
     619             :                                 "twice the register probe time (%u).",
     620             :                                 value, router->register_probe_time);
     621           0 :                         return NB_ERR_VALIDATION;
     622             :                 }
     623             :                 break;
     624             :         case NB_EV_PREPARE:
     625             :         case NB_EV_ABORT:
     626             :                 break;
     627           0 :         case NB_EV_APPLY:
     628           0 :                 pim_update_suppress_timers(
     629           0 :                         yang_dnode_get_uint16(args->dnode, NULL));
     630           0 :                 break;
     631             :         }
     632             : 
     633             :         return NB_OK;
     634             : }
     635             : 
     636             : /*
     637             :  * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/ecmp
     638             :  */
     639           0 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ecmp_modify(
     640             :         struct nb_cb_modify_args *args)
     641             : {
     642           0 :         struct vrf *vrf;
     643           0 :         struct pim_instance *pim;
     644             : 
     645           0 :         switch (args->event) {
     646             :         case NB_EV_VALIDATE:
     647             :         case NB_EV_PREPARE:
     648             :         case NB_EV_ABORT:
     649             :                 break;
     650           0 :         case NB_EV_APPLY:
     651           0 :                 vrf = nb_running_get_entry(args->dnode, NULL, true);
     652           0 :                 pim = vrf->info;
     653           0 :                 pim->ecmp_enable = yang_dnode_get_bool(args->dnode, NULL);
     654             :         }
     655             : 
     656           0 :         return NB_OK;
     657             : }
     658             : 
     659             : /*
     660             :  * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/ecmp-rebalance
     661             :  */
     662           0 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ecmp_rebalance_modify(
     663             :         struct nb_cb_modify_args *args)
     664             : {
     665           0 :         struct vrf *vrf;
     666           0 :         struct pim_instance *pim;
     667             : 
     668           0 :         switch (args->event) {
     669             :         case NB_EV_VALIDATE:
     670             :         case NB_EV_PREPARE:
     671             :         case NB_EV_ABORT:
     672             :                 break;
     673           0 :         case NB_EV_APPLY:
     674           0 :                 vrf = nb_running_get_entry(args->dnode, NULL, true);
     675           0 :                 pim = vrf->info;
     676           0 :                 pim->ecmp_rebalance_enable =
     677           0 :                         yang_dnode_get_bool(args->dnode, NULL);
     678             :         }
     679             : 
     680           0 :         return NB_OK;
     681             : }
     682             : 
     683             : /*
     684             :  * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/keep-alive-timer
     685             :  */
     686           0 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_keep_alive_timer_modify(
     687             :         struct nb_cb_modify_args *args)
     688             : {
     689           0 :         struct vrf *vrf;
     690           0 :         struct pim_instance *pim;
     691             : 
     692           0 :         switch (args->event) {
     693             :         case NB_EV_VALIDATE:
     694             :         case NB_EV_PREPARE:
     695             :         case NB_EV_ABORT:
     696             :                 break;
     697           0 :         case NB_EV_APPLY:
     698           0 :                 vrf = nb_running_get_entry(args->dnode, NULL, true);
     699           0 :                 pim = vrf->info;
     700           0 :                 pim->keep_alive_time = yang_dnode_get_uint16(args->dnode, NULL);
     701           0 :                 break;
     702             :         }
     703             : 
     704           0 :         return NB_OK;
     705             : }
     706             : 
     707             : /*
     708             :  * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/rp-keep-alive-timer
     709             :  */
     710           0 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_keep_alive_timer_modify(
     711             :         struct nb_cb_modify_args *args)
     712             : {
     713           0 :         struct vrf *vrf;
     714           0 :         struct pim_instance *pim;
     715             : 
     716           0 :         switch (args->event) {
     717             :         case NB_EV_VALIDATE:
     718             :         case NB_EV_PREPARE:
     719             :         case NB_EV_ABORT:
     720             :                 break;
     721           0 :         case NB_EV_APPLY:
     722           0 :                 vrf = nb_running_get_entry(args->dnode, NULL, true);
     723           0 :                 pim = vrf->info;
     724           0 :                 pim->rp_keep_alive_time = yang_dnode_get_uint16(args->dnode,
     725             :                                 NULL);
     726           0 :                 break;
     727             :         }
     728             : 
     729           0 :         return NB_OK;
     730             : }
     731             : 
     732             : /*
     733             :  * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family
     734             :  */
     735           0 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_create(
     736             :         struct nb_cb_create_args *args)
     737             : {
     738           0 :         switch (args->event) {
     739             :         case NB_EV_VALIDATE:
     740             :         case NB_EV_PREPARE:
     741             :         case NB_EV_ABORT:
     742             :         case NB_EV_APPLY:
     743             :                 break;
     744             :         }
     745             : 
     746           0 :         return NB_OK;
     747             : }
     748             : 
     749           0 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_destroy(
     750             :         struct nb_cb_destroy_args *args)
     751             : {
     752           0 :         switch (args->event) {
     753             :         case NB_EV_VALIDATE:
     754             :         case NB_EV_PREPARE:
     755             :         case NB_EV_ABORT:
     756             :         case NB_EV_APPLY:
     757             :                 break;
     758             :         }
     759             : 
     760           0 :         return NB_OK;
     761             : }
     762             : 
     763             : /*
     764             :  * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/send-v6-secondary
     765             :  */
     766           0 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_send_v6_secondary_modify(
     767             :         struct nb_cb_modify_args *args)
     768             : {
     769           0 :         struct vrf *vrf;
     770           0 :         struct pim_instance *pim;
     771             : 
     772           0 :         switch (args->event) {
     773             :         case NB_EV_VALIDATE:
     774             :         case NB_EV_PREPARE:
     775             :         case NB_EV_ABORT:
     776             :                 break;
     777           0 :         case NB_EV_APPLY:
     778           0 :                 vrf = nb_running_get_entry(args->dnode, NULL, true);
     779           0 :                 pim = vrf->info;
     780           0 :                 pim->send_v6_secondary = yang_dnode_get_bool(args->dnode, NULL);
     781           0 :                 break;
     782             :         }
     783             : 
     784           0 :         return NB_OK;
     785             : }
     786             : 
     787           0 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_send_v6_secondary_destroy(
     788             :         struct nb_cb_destroy_args *args)
     789             : {
     790           0 :         switch (args->event) {
     791             :         case NB_EV_VALIDATE:
     792             :         case NB_EV_PREPARE:
     793             :         case NB_EV_ABORT:
     794             :         case NB_EV_APPLY:
     795             :                 break;
     796             :         }
     797             : 
     798           0 :         return NB_OK;
     799             : }
     800             : 
     801             : /*
     802             :  * XPath:
     803             :  * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/spt-switchover
     804             :  */
     805           0 : void routing_control_plane_protocols_control_plane_protocol_pim_address_family_spt_switchover_apply_finish(
     806             :         struct nb_cb_apply_finish_args *args)
     807             : {
     808           0 :         struct vrf *vrf;
     809           0 :         struct pim_instance *pim;
     810           0 :         int spt_switch_action;
     811           0 :         const char *prefix_list = NULL;
     812             : 
     813           0 :         vrf = nb_running_get_entry(args->dnode, NULL, true);
     814           0 :         pim = vrf->info;
     815           0 :         spt_switch_action = yang_dnode_get_enum(args->dnode, "./spt-action");
     816             : 
     817           0 :         switch (spt_switch_action) {
     818           0 :         case PIM_SPT_INFINITY:
     819           0 :                 if (yang_dnode_exists(args->dnode,
     820             :                                       "./spt-infinity-prefix-list"))
     821           0 :                         prefix_list = yang_dnode_get_string(
     822             :                                 args->dnode, "./spt-infinity-prefix-list");
     823             : 
     824           0 :                 pim_cmd_spt_switchover(pim, PIM_SPT_INFINITY,
     825             :                                         prefix_list);
     826           0 :                 break;
     827           0 :         case PIM_SPT_IMMEDIATE:
     828           0 :                 pim_cmd_spt_switchover(pim, PIM_SPT_IMMEDIATE, NULL);
     829             :         }
     830           0 : }
     831             : 
     832             : /*
     833             :  * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/spt-switchover/spt-action
     834             :  */
     835           0 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_spt_switchover_spt_action_modify(
     836             :         struct nb_cb_modify_args *args)
     837             : {
     838           0 :         switch (args->event) {
     839             :         case NB_EV_VALIDATE:
     840             :         case NB_EV_PREPARE:
     841             :         case NB_EV_ABORT:
     842             :         case NB_EV_APPLY:
     843             :                 break;
     844             :         }
     845             : 
     846           0 :         return NB_OK;
     847             : }
     848             : 
     849             : /*
     850             :  * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/spt-switchover/spt-infinity-prefix-list
     851             :  */
     852           0 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_spt_switchover_spt_infinity_prefix_list_modify(
     853             :         struct nb_cb_modify_args *args)
     854             : {
     855           0 :         switch (args->event) {
     856             :         case NB_EV_VALIDATE:
     857             :         case NB_EV_PREPARE:
     858             :         case NB_EV_ABORT:
     859             :         case NB_EV_APPLY:
     860             :                 break;
     861             :         }
     862             : 
     863           0 :         return NB_OK;
     864             : }
     865             : 
     866           0 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_spt_switchover_spt_infinity_prefix_list_destroy(
     867             :         struct nb_cb_destroy_args *args)
     868             : {
     869           0 :         switch (args->event) {
     870             :         case NB_EV_VALIDATE:
     871             :         case NB_EV_PREPARE:
     872             :         case NB_EV_ABORT:
     873             :         case NB_EV_APPLY:
     874             :                 break;
     875             :         }
     876             : 
     877           0 :         return NB_OK;
     878             : }
     879             : 
     880             : /*
     881             :  * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/ssm-prefix-list
     882             :  */
     883           0 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ssm_prefix_list_modify(
     884             :         struct nb_cb_modify_args *args)
     885             : {
     886           0 :         struct vrf *vrf;
     887           0 :         struct pim_instance *pim;
     888           0 :         const char *plist_name;
     889           0 :         int result;
     890             : 
     891           0 :         switch (args->event) {
     892             :         case NB_EV_VALIDATE:
     893             :         case NB_EV_PREPARE:
     894             :         case NB_EV_ABORT:
     895             :                 break;
     896           0 :         case NB_EV_APPLY:
     897           0 :                 vrf = nb_running_get_entry(args->dnode, NULL, true);
     898           0 :                 pim = vrf->info;
     899           0 :                 plist_name = yang_dnode_get_string(args->dnode, NULL);
     900           0 :                 result = pim_ssm_cmd_worker(pim, plist_name, args->errmsg,
     901             :                                 args->errmsg_len);
     902             : 
     903           0 :                 if (result)
     904             :                         return NB_ERR_INCONSISTENCY;
     905             : 
     906             :                 break;
     907             :         }
     908             : 
     909             :         return NB_OK;
     910             : }
     911             : 
     912           0 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ssm_prefix_list_destroy(
     913             :         struct nb_cb_destroy_args *args)
     914             : {
     915           0 :         struct vrf *vrf;
     916           0 :         struct pim_instance *pim;
     917           0 :         int result;
     918             : 
     919           0 :         switch (args->event) {
     920             :         case NB_EV_VALIDATE:
     921             :         case NB_EV_PREPARE:
     922             :         case NB_EV_ABORT:
     923             :                 break;
     924           0 :         case NB_EV_APPLY:
     925           0 :                 vrf = nb_running_get_entry(args->dnode, NULL, true);
     926           0 :                 pim = vrf->info;
     927           0 :                 result = pim_ssm_cmd_worker(pim, NULL, args->errmsg,
     928             :                                 args->errmsg_len);
     929             : 
     930           0 :                 if (result)
     931             :                         return NB_ERR_INCONSISTENCY;
     932             : 
     933             :                 break;
     934             :         }
     935             : 
     936             :         return NB_OK;
     937             : }
     938             : 
     939             : /*
     940             :  * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/ssm-pingd-source-ip
     941             :  */
     942           0 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ssm_pingd_source_ip_create(
     943             :         struct nb_cb_create_args *args)
     944             : {
     945           0 :         struct vrf *vrf;
     946           0 :         struct pim_instance *pim;
     947           0 :         int result;
     948           0 :         pim_addr source_addr;
     949             : 
     950           0 :         switch (args->event) {
     951             :         case NB_EV_VALIDATE:
     952             :         case NB_EV_PREPARE:
     953             :         case NB_EV_ABORT:
     954             :                 break;
     955           0 :         case NB_EV_APPLY:
     956           0 :                 vrf = nb_running_get_entry(args->dnode, NULL, true);
     957           0 :                 pim = vrf->info;
     958           0 :                 yang_dnode_get_pimaddr(&source_addr, args->dnode,
     959             :                                        "./source-addr");
     960           0 :                 result = pim_ssmpingd_start(pim, source_addr);
     961           0 :                 if (result) {
     962           0 :                         snprintf(
     963             :                                 args->errmsg, args->errmsg_len,
     964             :                                 "%% Failure starting ssmpingd for source %pPA: %d",
     965             :                                 &source_addr, result);
     966           0 :                         return NB_ERR_INCONSISTENCY;
     967             :                 }
     968             :         }
     969             : 
     970             :         return NB_OK;
     971             : }
     972             : 
     973           0 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ssm_pingd_source_ip_destroy(
     974             :         struct nb_cb_destroy_args *args)
     975             : {
     976           0 :         struct vrf *vrf;
     977           0 :         struct pim_instance *pim;
     978           0 :         int result;
     979           0 :         pim_addr source_addr;
     980             : 
     981           0 :         switch (args->event) {
     982             :         case NB_EV_VALIDATE:
     983             :         case NB_EV_PREPARE:
     984             :         case NB_EV_ABORT:
     985             :                 break;
     986           0 :         case NB_EV_APPLY:
     987           0 :                 vrf = nb_running_get_entry(args->dnode, NULL, true);
     988           0 :                 pim = vrf->info;
     989           0 :                 yang_dnode_get_pimaddr(&source_addr, args->dnode,
     990             :                                        "./source-addr");
     991           0 :                 result = pim_ssmpingd_stop(pim, source_addr);
     992           0 :                 if (result) {
     993           0 :                         snprintf(
     994             :                                 args->errmsg, args->errmsg_len,
     995             :                                 "%% Failure stopping ssmpingd for source %pPA: %d",
     996             :                                 &source_addr, result);
     997           0 :                         return NB_ERR_INCONSISTENCY;
     998             :                 }
     999             : 
    1000             :                 break;
    1001             :         }
    1002             : 
    1003             :         return NB_OK;
    1004             : }
    1005             : 
    1006             : /*
    1007             :  * XPath:
    1008             :  * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp/hold-time
    1009             :  */
    1010           0 : int pim_msdp_hold_time_modify(struct nb_cb_modify_args *args)
    1011             : {
    1012           0 :         struct pim_instance *pim;
    1013           0 :         struct vrf *vrf;
    1014             : 
    1015           0 :         switch (args->event) {
    1016             :         case NB_EV_VALIDATE:
    1017             :         case NB_EV_PREPARE:
    1018             :         case NB_EV_ABORT:
    1019             :                 break;
    1020           0 :         case NB_EV_APPLY:
    1021           0 :                 vrf = nb_running_get_entry(args->dnode, NULL, true);
    1022           0 :                 pim = vrf->info;
    1023           0 :                 pim->msdp.hold_time = yang_dnode_get_uint16(args->dnode, NULL);
    1024           0 :                 break;
    1025             :         }
    1026             : 
    1027           0 :         return NB_OK;
    1028             : }
    1029             : 
    1030             : /*
    1031             :  * XPath:
    1032             :  * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp/keep-alive
    1033             :  */
    1034           0 : int pim_msdp_keep_alive_modify(struct nb_cb_modify_args *args)
    1035             : {
    1036           0 :         struct pim_instance *pim;
    1037           0 :         struct vrf *vrf;
    1038             : 
    1039           0 :         switch (args->event) {
    1040             :         case NB_EV_VALIDATE:
    1041             :         case NB_EV_PREPARE:
    1042             :         case NB_EV_ABORT:
    1043             :                 break;
    1044           0 :         case NB_EV_APPLY:
    1045           0 :                 vrf = nb_running_get_entry(args->dnode, NULL, true);
    1046           0 :                 pim = vrf->info;
    1047           0 :                 pim->msdp.keep_alive = yang_dnode_get_uint16(args->dnode, NULL);
    1048           0 :                 break;
    1049             :         }
    1050             : 
    1051           0 :         return NB_OK;
    1052             : }
    1053             : 
    1054             : /*
    1055             :  * XPath:
    1056             :  * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp/connection-retry
    1057             :  */
    1058           0 : int pim_msdp_connection_retry_modify(struct nb_cb_modify_args *args)
    1059             : {
    1060           0 :         struct pim_instance *pim;
    1061           0 :         struct vrf *vrf;
    1062             : 
    1063           0 :         switch (args->event) {
    1064             :         case NB_EV_VALIDATE:
    1065             :         case NB_EV_PREPARE:
    1066             :         case NB_EV_ABORT:
    1067             :                 break;
    1068           0 :         case NB_EV_APPLY:
    1069           0 :                 vrf = nb_running_get_entry(args->dnode, NULL, true);
    1070           0 :                 pim = vrf->info;
    1071           0 :                 pim->msdp.connection_retry =
    1072           0 :                         yang_dnode_get_uint16(args->dnode, NULL);
    1073           0 :                 break;
    1074             :         }
    1075             : 
    1076           0 :         return NB_OK;
    1077             : }
    1078             : 
    1079             : pim6_msdp_err(pim_msdp_mesh_group_destroy, nb_cb_destroy_args);
    1080             : pim6_msdp_err(pim_msdp_mesh_group_create, nb_cb_create_args);
    1081             : pim6_msdp_err(pim_msdp_mesh_group_source_modify, nb_cb_modify_args);
    1082             : pim6_msdp_err(pim_msdp_mesh_group_source_destroy, nb_cb_destroy_args);
    1083             : pim6_msdp_err(pim_msdp_mesh_group_members_create, nb_cb_create_args);
    1084             : pim6_msdp_err(pim_msdp_mesh_group_members_destroy, nb_cb_destroy_args);
    1085             : pim6_msdp_err(routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_peer_source_ip_modify,
    1086             :               nb_cb_modify_args);
    1087             : pim6_msdp_err(routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_peer_destroy,
    1088             :               nb_cb_destroy_args);
    1089             : pim6_msdp_err(routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_peer_create,
    1090             :               nb_cb_create_args);
    1091             : 
    1092             : #if PIM_IPV != 6
    1093             : /*
    1094             :  * XPath:
    1095             :  * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-mesh-groups
    1096             :  */
    1097           0 : int pim_msdp_mesh_group_create(struct nb_cb_create_args *args)
    1098             : {
    1099           0 :         struct pim_msdp_mg *mg;
    1100           0 :         struct vrf *vrf;
    1101             : 
    1102           0 :         switch (args->event) {
    1103             :         case NB_EV_VALIDATE:
    1104             :         case NB_EV_PREPARE:
    1105             :         case NB_EV_ABORT:
    1106             :                 break;
    1107           0 :         case NB_EV_APPLY:
    1108           0 :                 vrf = nb_running_get_entry(args->dnode, NULL, true);
    1109           0 :                 mg = pim_msdp_mg_new(vrf->info, yang_dnode_get_string(
    1110             :                                                         args->dnode, "./name"));
    1111           0 :                 nb_running_set_entry(args->dnode, mg);
    1112           0 :                 break;
    1113             :         }
    1114             : 
    1115           0 :         return NB_OK;
    1116             : }
    1117             : 
    1118           0 : int pim_msdp_mesh_group_destroy(struct nb_cb_destroy_args *args)
    1119             : {
    1120           0 :         struct pim_msdp_mg *mg;
    1121           0 :         struct vrf *vrf;
    1122             : 
    1123           0 :         switch (args->event) {
    1124             :         case NB_EV_VALIDATE:
    1125             :         case NB_EV_PREPARE:
    1126             :         case NB_EV_ABORT:
    1127             :                 break;
    1128           0 :         case NB_EV_APPLY:
    1129           0 :                 mg = nb_running_unset_entry(args->dnode);
    1130           0 :                 vrf = nb_running_get_entry(args->dnode, NULL, true);
    1131           0 :                 pim_msdp_mg_free(vrf->info, &mg);
    1132           0 :                 break;
    1133             :         }
    1134             : 
    1135           0 :         return NB_OK;
    1136             : }
    1137             : 
    1138             : /*
    1139             :  * XPath:
    1140             :  * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-mesh-groups/source
    1141             :  */
    1142           0 : int pim_msdp_mesh_group_source_modify(struct nb_cb_modify_args *args)
    1143             : {
    1144           0 :         const struct lyd_node *vrf_dnode;
    1145           0 :         struct pim_msdp_mg *mg;
    1146           0 :         struct vrf *vrf;
    1147           0 :         struct ipaddr ip;
    1148             : 
    1149           0 :         switch (args->event) {
    1150             :         case NB_EV_VALIDATE:
    1151             :         case NB_EV_PREPARE:
    1152             :         case NB_EV_ABORT:
    1153             :                 break;
    1154           0 :         case NB_EV_APPLY:
    1155           0 :                 mg = nb_running_get_entry(args->dnode, NULL, true);
    1156           0 :                 vrf_dnode =
    1157           0 :                         yang_dnode_get_parent(args->dnode, "address-family");
    1158           0 :                 vrf = nb_running_get_entry(vrf_dnode, "../../", true);
    1159           0 :                 yang_dnode_get_ip(&ip, args->dnode, NULL);
    1160             : 
    1161           0 :                 pim_msdp_mg_src_add(vrf->info, mg, &ip.ip._v4_addr);
    1162           0 :                 break;
    1163             :         }
    1164           0 :         return NB_OK;
    1165             : }
    1166             : 
    1167           0 : int pim_msdp_mesh_group_source_destroy(struct nb_cb_destroy_args *args)
    1168             : {
    1169           0 :         const struct lyd_node *vrf_dnode;
    1170           0 :         struct pim_msdp_mg *mg;
    1171           0 :         struct vrf *vrf;
    1172           0 :         struct in_addr addr;
    1173             : 
    1174           0 :         switch (args->event) {
    1175             :         case NB_EV_VALIDATE:
    1176             :         case NB_EV_PREPARE:
    1177             :         case NB_EV_ABORT:
    1178             :                 break;
    1179           0 :         case NB_EV_APPLY:
    1180           0 :                 mg = nb_running_get_entry(args->dnode, NULL, true);
    1181           0 :                 vrf_dnode =
    1182           0 :                         yang_dnode_get_parent(args->dnode, "address-family");
    1183           0 :                 vrf = nb_running_get_entry(vrf_dnode, "../../", true);
    1184             : 
    1185           0 :                 addr.s_addr = INADDR_ANY;
    1186           0 :                 pim_msdp_mg_src_add(vrf->info, mg, &addr);
    1187           0 :                 break;
    1188             :         }
    1189           0 :         return NB_OK;
    1190             : }
    1191             : 
    1192             : 
    1193             : /*
    1194             :  * XPath:
    1195             :  * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-mesh-groups/members
    1196             :  */
    1197           0 : int pim_msdp_mesh_group_members_create(struct nb_cb_create_args *args)
    1198             : {
    1199           0 :         const struct lyd_node *vrf_dnode;
    1200           0 :         struct pim_msdp_mg_mbr *mbr;
    1201           0 :         struct pim_msdp_mg *mg;
    1202           0 :         struct vrf *vrf;
    1203           0 :         struct ipaddr ip;
    1204             : 
    1205           0 :         switch (args->event) {
    1206             :         case NB_EV_VALIDATE:
    1207             :         case NB_EV_PREPARE:
    1208             :         case NB_EV_ABORT:
    1209             :                 break;
    1210           0 :         case NB_EV_APPLY:
    1211           0 :                 mg = nb_running_get_entry(args->dnode, NULL, true);
    1212           0 :                 vrf_dnode =
    1213           0 :                         yang_dnode_get_parent(args->dnode, "address-family");
    1214           0 :                 vrf = nb_running_get_entry(vrf_dnode, "../../", true);
    1215           0 :                 yang_dnode_get_ip(&ip, args->dnode, "address");
    1216             : 
    1217           0 :                 mbr = pim_msdp_mg_mbr_add(vrf->info, mg, &ip.ip._v4_addr);
    1218           0 :                 nb_running_set_entry(args->dnode, mbr);
    1219           0 :                 break;
    1220             :         }
    1221             : 
    1222           0 :         return NB_OK;
    1223             : }
    1224             : 
    1225           0 : int pim_msdp_mesh_group_members_destroy(struct nb_cb_destroy_args *args)
    1226             : {
    1227           0 :         struct pim_msdp_mg_mbr *mbr;
    1228           0 :         struct pim_msdp_mg *mg;
    1229           0 :         const struct lyd_node *mg_dnode;
    1230             : 
    1231           0 :         switch (args->event) {
    1232             :         case NB_EV_VALIDATE:
    1233             :         case NB_EV_PREPARE:
    1234             :         case NB_EV_ABORT:
    1235             :                 break;
    1236           0 :         case NB_EV_APPLY:
    1237           0 :                 mbr = nb_running_get_entry(args->dnode, NULL, true);
    1238           0 :                 mg_dnode =
    1239           0 :                         yang_dnode_get_parent(args->dnode, "msdp-mesh-groups");
    1240           0 :                 mg = nb_running_get_entry(mg_dnode, NULL, true);
    1241           0 :                 pim_msdp_mg_mbr_del(mg, mbr);
    1242           0 :                 nb_running_unset_entry(args->dnode);
    1243           0 :                 break;
    1244             :         }
    1245             : 
    1246           0 :         return NB_OK;
    1247             : }
    1248             : 
    1249             : /*
    1250             :  * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-peer
    1251             :  */
    1252           0 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_peer_create(
    1253             :         struct nb_cb_create_args *args)
    1254             : {
    1255           0 :         struct pim_msdp_peer *mp;
    1256           0 :         struct pim_instance *pim;
    1257           0 :         struct vrf *vrf;
    1258           0 :         struct ipaddr peer_ip;
    1259           0 :         struct ipaddr source_ip;
    1260             : 
    1261           0 :         switch (args->event) {
    1262             :         case NB_EV_VALIDATE:
    1263             :         case NB_EV_PREPARE:
    1264             :         case NB_EV_ABORT:
    1265             :                 break;
    1266           0 :         case NB_EV_APPLY:
    1267           0 :                 vrf = nb_running_get_entry(args->dnode, NULL, true);
    1268           0 :                 pim = vrf->info;
    1269           0 :                 yang_dnode_get_ip(&peer_ip, args->dnode, "./peer-ip");
    1270           0 :                 yang_dnode_get_ip(&source_ip, args->dnode, "./source-ip");
    1271           0 :                 mp = pim_msdp_peer_add(pim, &peer_ip.ipaddr_v4,
    1272             :                                        &source_ip.ipaddr_v4, NULL);
    1273           0 :                 nb_running_set_entry(args->dnode, mp);
    1274           0 :                 break;
    1275             :         }
    1276             : 
    1277           0 :         return NB_OK;
    1278             : }
    1279             : 
    1280           0 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_peer_destroy(
    1281             :         struct nb_cb_destroy_args *args)
    1282             : {
    1283           0 :         struct pim_msdp_peer *mp;
    1284             : 
    1285           0 :         switch (args->event) {
    1286             :         case NB_EV_VALIDATE:
    1287             :         case NB_EV_PREPARE:
    1288             :         case NB_EV_ABORT:
    1289             :                 break;
    1290           0 :         case NB_EV_APPLY:
    1291           0 :                 mp = nb_running_unset_entry(args->dnode);
    1292           0 :                 pim_msdp_peer_del(&mp);
    1293           0 :                 break;
    1294             :         }
    1295             : 
    1296           0 :         return NB_OK;
    1297             : }
    1298             : 
    1299             : /*
    1300             :  * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-peer/source-ip
    1301             :  */
    1302           0 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_peer_source_ip_modify(
    1303             :         struct nb_cb_modify_args *args)
    1304             : {
    1305           0 :         struct pim_msdp_peer *mp;
    1306           0 :         struct ipaddr source_ip;
    1307             : 
    1308           0 :         switch (args->event) {
    1309             :         case NB_EV_VALIDATE:
    1310             :         case NB_EV_PREPARE:
    1311             :         case NB_EV_ABORT:
    1312             :                 break;
    1313           0 :         case NB_EV_APPLY:
    1314           0 :                 mp = nb_running_get_entry(args->dnode, NULL, true);
    1315           0 :                 yang_dnode_get_ip(&source_ip, args->dnode, NULL);
    1316           0 :                 pim_msdp_peer_change_source(mp, &source_ip.ipaddr_v4);
    1317           0 :                 break;
    1318             :         }
    1319             : 
    1320           0 :         return NB_OK;
    1321             : }
    1322             : #endif /* PIM_IPV != 6 */
    1323             : 
    1324             : /*
    1325             :  * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/mlag
    1326             :  */
    1327           0 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_create(
    1328             :         struct nb_cb_create_args *args)
    1329             : {
    1330           0 :         switch (args->event) {
    1331             :         case NB_EV_VALIDATE:
    1332             :         case NB_EV_PREPARE:
    1333             :         case NB_EV_ABORT:
    1334             :         case NB_EV_APPLY:
    1335             :                 break;
    1336             :         }
    1337             : 
    1338           0 :         return NB_OK;
    1339             : }
    1340             : 
    1341           0 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_destroy(
    1342             :         struct nb_cb_destroy_args *args)
    1343             : {
    1344           0 :         struct in_addr addr;
    1345             : 
    1346           0 :         switch (args->event) {
    1347             :         case NB_EV_VALIDATE:
    1348             :         case NB_EV_PREPARE:
    1349             :         case NB_EV_ABORT:
    1350             :                 break;
    1351           0 :         case NB_EV_APPLY:
    1352           0 :                 addr.s_addr = 0;
    1353           0 :                 pim_vxlan_mlag_update(true/*mlag_enable*/,
    1354             :                                 false/*peer_state*/, MLAG_ROLE_NONE,
    1355             :                                 NULL/*peerlink*/, &addr);
    1356             :         }
    1357             : 
    1358           0 :         return NB_OK;
    1359             : }
    1360             : 
    1361             : /*
    1362             :  * XPath:
    1363             :  * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/mlag
    1364             :  */
    1365           0 : void routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_apply_finish(
    1366             :         struct nb_cb_apply_finish_args *args)
    1367             : {
    1368           0 :         const char *ifname;
    1369           0 :         uint32_t role;
    1370           0 :         bool peer_state;
    1371           0 :         struct interface *ifp;
    1372           0 :         struct ipaddr reg_addr;
    1373             : 
    1374           0 :         ifname = yang_dnode_get_string(args->dnode, "./peerlink-rif");
    1375           0 :         ifp = if_lookup_by_name(ifname, VRF_DEFAULT);
    1376           0 :         if (!ifp) {
    1377           0 :                 snprintf(args->errmsg, args->errmsg_len,
    1378             :                          "No such interface name %s", ifname);
    1379           0 :                 return;
    1380             :         }
    1381           0 :         role = yang_dnode_get_enum(args->dnode, "./my-role");
    1382           0 :         peer_state = yang_dnode_get_bool(args->dnode, "./peer-state");
    1383           0 :         yang_dnode_get_ip(&reg_addr, args->dnode, "./reg-address");
    1384             : 
    1385           0 :         pim_vxlan_mlag_update(true, peer_state, role, ifp,
    1386             :                         &reg_addr.ip._v4_addr);
    1387             : }
    1388             : 
    1389             : 
    1390             : /*
    1391             :  * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/mlag/peerlink-rif
    1392             :  */
    1393           0 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_peerlink_rif_modify(
    1394             :         struct nb_cb_modify_args *args)
    1395             : {
    1396           0 :         switch (args->event) {
    1397             :         case NB_EV_VALIDATE:
    1398             :         case NB_EV_PREPARE:
    1399             :         case NB_EV_ABORT:
    1400             :         case NB_EV_APPLY:
    1401             :                 break;
    1402             :         }
    1403             : 
    1404           0 :         return NB_OK;
    1405             : }
    1406             : 
    1407           0 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_peerlink_rif_destroy(
    1408             :         struct nb_cb_destroy_args *args)
    1409             : {
    1410           0 :         switch (args->event) {
    1411             :         case NB_EV_VALIDATE:
    1412             :         case NB_EV_PREPARE:
    1413             :         case NB_EV_ABORT:
    1414             :         case NB_EV_APPLY:
    1415             :                 break;
    1416             :         }
    1417             : 
    1418           0 :         return NB_OK;
    1419             : }
    1420             : 
    1421             : /*
    1422             :  * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/mlag/reg-address
    1423             :  */
    1424           0 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_reg_address_modify(
    1425             :         struct nb_cb_modify_args *args)
    1426             : {
    1427           0 :         switch (args->event) {
    1428             :         case NB_EV_VALIDATE:
    1429             :         case NB_EV_PREPARE:
    1430             :         case NB_EV_ABORT:
    1431             :         case NB_EV_APPLY:
    1432             :                 break;
    1433             :         }
    1434             : 
    1435           0 :         return NB_OK;
    1436             : }
    1437             : 
    1438           0 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_reg_address_destroy(
    1439             :         struct nb_cb_destroy_args *args)
    1440             : {
    1441           0 :         switch (args->event) {
    1442             :         case NB_EV_VALIDATE:
    1443             :         case NB_EV_PREPARE:
    1444             :         case NB_EV_ABORT:
    1445             :         case NB_EV_APPLY:
    1446             :                 break;
    1447             :         }
    1448             : 
    1449           0 :         return NB_OK;
    1450             : }
    1451             : 
    1452             : /*
    1453             :  * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/mlag/my-role
    1454             :  */
    1455           0 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_my_role_modify(
    1456             :         struct nb_cb_modify_args *args)
    1457             : {
    1458           0 :         switch (args->event) {
    1459             :         case NB_EV_VALIDATE:
    1460             :         case NB_EV_PREPARE:
    1461             :         case NB_EV_ABORT:
    1462             :         case NB_EV_APPLY:
    1463             :                 break;
    1464             :         }
    1465             : 
    1466           0 :         return NB_OK;
    1467             : }
    1468             : 
    1469             : /*
    1470             :  * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/mlag/peer-state
    1471             :  */
    1472           0 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_peer_state_modify(
    1473             :         struct nb_cb_modify_args *args)
    1474             : {
    1475           0 :         switch (args->event) {
    1476             :         case NB_EV_VALIDATE:
    1477             :         case NB_EV_PREPARE:
    1478             :         case NB_EV_ABORT:
    1479             :         case NB_EV_APPLY:
    1480             :                 break;
    1481             :         }
    1482             : 
    1483           0 :         return NB_OK;
    1484             : }
    1485             : 
    1486             : /*
    1487             :  * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/register-accept-list
    1488             :  */
    1489           0 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_register_accept_list_modify(
    1490             :         struct nb_cb_modify_args *args)
    1491             : {
    1492           0 :         struct vrf *vrf;
    1493           0 :         struct pim_instance *pim;
    1494           0 :         const char *plist;
    1495             : 
    1496           0 :         switch (args->event) {
    1497             :         case NB_EV_VALIDATE:
    1498             :         case NB_EV_PREPARE:
    1499             :         case NB_EV_ABORT:
    1500             :                 break;
    1501           0 :         case NB_EV_APPLY:
    1502           0 :                 vrf = nb_running_get_entry(args->dnode, NULL, true);
    1503           0 :                 pim = vrf->info;
    1504           0 :                 plist = yang_dnode_get_string(args->dnode, NULL);
    1505             : 
    1506           0 :                 XFREE(MTYPE_PIM_PLIST_NAME, pim->register_plist);
    1507           0 :                 pim->register_plist = XSTRDUP(MTYPE_PIM_PLIST_NAME, plist);
    1508             : 
    1509           0 :                 break;
    1510             :         }
    1511             : 
    1512           0 :         return NB_OK;
    1513             : }
    1514             : 
    1515           0 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_register_accept_list_destroy(
    1516             :         struct nb_cb_destroy_args *args)
    1517             : {
    1518           0 :         struct vrf *vrf;
    1519           0 :         struct pim_instance *pim;
    1520             : 
    1521           0 :         switch (args->event) {
    1522             :         case NB_EV_VALIDATE:
    1523             :         case NB_EV_PREPARE:
    1524             :         case NB_EV_ABORT:
    1525             :                 break;
    1526           0 :         case NB_EV_APPLY:
    1527           0 :                 vrf = nb_running_get_entry(args->dnode, NULL, true);
    1528           0 :                 pim = vrf->info;
    1529             : 
    1530           0 :                 XFREE(MTYPE_PIM_PLIST_NAME, pim->register_plist);
    1531           0 :                 break;
    1532             :         }
    1533             : 
    1534           0 :         return NB_OK;
    1535             : }
    1536             : 
    1537             : /*
    1538             :  * XPath: /frr-interface:lib/interface/frr-pim:pim/address-family
    1539             :  */
    1540          18 : int lib_interface_pim_address_family_create(struct nb_cb_create_args *args)
    1541             : {
    1542          18 :         switch (args->event) {
    1543             :         case NB_EV_VALIDATE:
    1544             :         case NB_EV_PREPARE:
    1545             :         case NB_EV_ABORT:
    1546             :         case NB_EV_APPLY:
    1547             :                 break;
    1548             :         }
    1549             : 
    1550          18 :         return NB_OK;
    1551             : }
    1552             : 
    1553           0 : int lib_interface_pim_address_family_destroy(struct nb_cb_destroy_args *args)
    1554             : {
    1555           0 :         struct interface *ifp;
    1556           0 :         struct pim_interface *pim_ifp;
    1557             : 
    1558           0 :         switch (args->event) {
    1559             :         case NB_EV_VALIDATE:
    1560             :         case NB_EV_PREPARE:
    1561             :         case NB_EV_ABORT:
    1562             :                 break;
    1563           0 :         case NB_EV_APPLY:
    1564           0 :                 ifp = nb_running_get_entry(args->dnode, NULL, true);
    1565           0 :                 pim_ifp = ifp->info;
    1566           0 :                 if (!pim_ifp)
    1567             :                         return NB_OK;
    1568             : 
    1569           0 :                 if (!pim_cmd_interface_delete(ifp)) {
    1570           0 :                         snprintf(args->errmsg, args->errmsg_len,
    1571             :                                  "Unable to delete interface information %s",
    1572           0 :                                  ifp->name);
    1573           0 :                         return NB_ERR_INCONSISTENCY;
    1574             :                 }
    1575             :         }
    1576             : 
    1577             :         return NB_OK;
    1578             : }
    1579             : 
    1580             : /*
    1581             :  * XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/pim-enable
    1582             :  */
    1583          18 : int lib_interface_pim_address_family_pim_enable_modify(struct nb_cb_modify_args *args)
    1584             : {
    1585          18 :         struct interface *ifp;
    1586          18 :         struct pim_interface *pim_ifp;
    1587          18 :         int mcast_if_count;
    1588          18 :         const struct lyd_node *if_dnode;
    1589             : 
    1590          18 :         switch (args->event) {
    1591           6 :         case NB_EV_VALIDATE:
    1592           6 :                 if_dnode = yang_dnode_get_parent(args->dnode, "interface");
    1593          12 :                 mcast_if_count =
    1594           6 :                         yang_get_list_elements_count(if_dnode);
    1595             : 
    1596             :                 /* Limiting mcast interfaces to number of VIFs */
    1597           6 :                 if (mcast_if_count == MAXVIFS) {
    1598           0 :                         snprintf(args->errmsg, args->errmsg_len,
    1599             :                                  "Max multicast interfaces(%d) reached.",
    1600             :                                  MAXVIFS);
    1601           0 :                         return NB_ERR_VALIDATION;
    1602             :                 }
    1603             :                 break;
    1604             :         case NB_EV_PREPARE:
    1605             :         case NB_EV_ABORT:
    1606             :                 break;
    1607           6 :         case NB_EV_APPLY:
    1608           6 :                 ifp = nb_running_get_entry(args->dnode, NULL, true);
    1609             : 
    1610           6 :                 if (yang_dnode_get_bool(args->dnode, NULL)) {
    1611           6 :                         if (!pim_cmd_interface_add(ifp)) {
    1612           0 :                                 snprintf(args->errmsg, args->errmsg_len,
    1613             :                                          "Could not enable PIM SM on interface %s",
    1614           0 :                                          ifp->name);
    1615           0 :                                 return NB_ERR_INCONSISTENCY;
    1616             :                         }
    1617             :                 } else {
    1618           0 :                         pim_ifp = ifp->info;
    1619           0 :                         if (!pim_ifp)
    1620             :                                 return NB_ERR_INCONSISTENCY;
    1621             : 
    1622           0 :                         if (!pim_cmd_interface_delete(ifp)) {
    1623           0 :                                 snprintf(args->errmsg, args->errmsg_len,
    1624             :                                          "Unable to delete interface information");
    1625           0 :                                 return NB_ERR_INCONSISTENCY;
    1626             :                         }
    1627             :                 }
    1628             :                 break;
    1629             :         }
    1630             : 
    1631             :         return NB_OK;
    1632             : }
    1633             : 
    1634             : /*
    1635             :  * XPath:
    1636             :  * /frr-interface:lib/interface/frr-pim:pim/address-family/pim-passive-enable
    1637             :  */
    1638           0 : int lib_interface_pim_address_family_pim_passive_enable_modify(
    1639             :         struct nb_cb_modify_args *args)
    1640             : {
    1641           0 :         struct interface *ifp;
    1642           0 :         struct pim_interface *pim_ifp;
    1643             : 
    1644           0 :         switch (args->event) {
    1645             :         case NB_EV_VALIDATE:
    1646             :         case NB_EV_ABORT:
    1647             :         case NB_EV_PREPARE:
    1648             :                 break;
    1649           0 :         case NB_EV_APPLY:
    1650           0 :                 ifp = nb_running_get_entry(args->dnode, NULL, true);
    1651           0 :                 pim_ifp = ifp->info;
    1652           0 :                 pim_ifp->pim_passive_enable =
    1653           0 :                         yang_dnode_get_bool(args->dnode, NULL);
    1654           0 :                 break;
    1655             :         }
    1656             : 
    1657           0 :         return NB_OK;
    1658             : }
    1659             : 
    1660             : /*
    1661             :  * XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/hello-interval
    1662             :  */
    1663          18 : int lib_interface_pim_address_family_hello_interval_modify(
    1664             :         struct nb_cb_modify_args *args)
    1665             : {
    1666          18 :         struct interface *ifp;
    1667          18 :         struct pim_interface *pim_ifp;
    1668             : 
    1669          18 :         switch (args->event) {
    1670             :         case NB_EV_VALIDATE:
    1671             :         case NB_EV_ABORT:
    1672             :         case NB_EV_PREPARE:
    1673             :                 break;
    1674           6 :         case NB_EV_APPLY:
    1675           6 :                 ifp = nb_running_get_entry(args->dnode, NULL, true);
    1676           6 :                 pim_ifp = ifp->info;
    1677          12 :                 pim_ifp->pim_hello_period =
    1678           6 :                         yang_dnode_get_uint8(args->dnode, NULL);
    1679           6 :                 pim_ifp->pim_default_holdtime = -1;
    1680           6 :                 break;
    1681             :         }
    1682             : 
    1683          18 :         return NB_OK;
    1684             : }
    1685             : 
    1686             : /*
    1687             :  * XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/hello-holdtime
    1688             :  */
    1689          18 : int lib_interface_pim_address_family_hello_holdtime_modify(
    1690             :         struct nb_cb_modify_args *args)
    1691             : {
    1692          18 :         struct interface *ifp;
    1693          18 :         struct pim_interface *pim_ifp;
    1694             : 
    1695          18 :         switch (args->event) {
    1696             :         case NB_EV_VALIDATE:
    1697             :         case NB_EV_ABORT:
    1698             :         case NB_EV_PREPARE:
    1699             :                 break;
    1700           6 :         case NB_EV_APPLY:
    1701           6 :                 ifp = nb_running_get_entry(args->dnode, NULL, true);
    1702           6 :                 pim_ifp = ifp->info;
    1703          12 :                 pim_ifp->pim_default_holdtime =
    1704           6 :                         yang_dnode_get_uint16(args->dnode, NULL);
    1705           6 :                 break;
    1706             :         }
    1707             : 
    1708          18 :         return NB_OK;
    1709             : 
    1710             : }
    1711             : 
    1712           0 : int lib_interface_pim_address_family_hello_holdtime_destroy(
    1713             :         struct nb_cb_destroy_args *args)
    1714             : {
    1715           0 :         struct interface *ifp;
    1716           0 :         struct pim_interface *pim_ifp;
    1717             : 
    1718           0 :         switch (args->event) {
    1719             :         case NB_EV_VALIDATE:
    1720             :         case NB_EV_ABORT:
    1721             :         case NB_EV_PREPARE:
    1722             :                 break;
    1723           0 :         case NB_EV_APPLY:
    1724           0 :                 ifp = nb_running_get_entry(args->dnode, NULL, true);
    1725           0 :                 pim_ifp = ifp->info;
    1726           0 :                 pim_ifp->pim_default_holdtime = -1;
    1727           0 :                 break;
    1728             :         }
    1729             : 
    1730           0 :         return NB_OK;
    1731             : }
    1732             : /*
    1733             :  * XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/bfd
    1734             :  */
    1735          18 : int lib_interface_pim_address_family_bfd_create(struct nb_cb_create_args *args)
    1736             : {
    1737          18 :         struct interface *ifp;
    1738          18 :         struct pim_interface *pim_ifp;
    1739             : 
    1740          18 :         switch (args->event) {
    1741             :         case NB_EV_VALIDATE:
    1742             :         case NB_EV_PREPARE:
    1743             :         case NB_EV_ABORT:
    1744             :                 /* NOTHING */
    1745             :                 break;
    1746           6 :         case NB_EV_APPLY:
    1747           6 :                 ifp = nb_running_get_entry(args->dnode, NULL, true);
    1748           6 :                 pim_ifp = ifp->info;
    1749           6 :                 pim_ifp->bfd_config.enabled = true;
    1750           6 :                 break;
    1751             :         }
    1752             : 
    1753          18 :         return NB_OK;
    1754             : }
    1755             : 
    1756           0 : int lib_interface_pim_address_family_bfd_destroy(
    1757             :         struct nb_cb_destroy_args *args)
    1758             : {
    1759           0 :         struct interface *ifp;
    1760           0 :         struct pim_interface *pim_ifp;
    1761           0 :         const struct lyd_node *if_dnode;
    1762             : 
    1763           0 :         switch (args->event) {
    1764           0 :         case NB_EV_VALIDATE:
    1765           0 :                 if_dnode = yang_dnode_get_parent(args->dnode, "interface");
    1766           0 :                 if (!is_pim_interface(if_dnode)) {
    1767           0 :                         snprintf(args->errmsg, args->errmsg_len,
    1768             :                                  "Pim not enabled on this interface");
    1769           0 :                         return NB_ERR_VALIDATION;
    1770             :                 }
    1771             :                 break;
    1772             :         case NB_EV_ABORT:
    1773             :         case NB_EV_PREPARE:
    1774             :                 break;
    1775           0 :         case NB_EV_APPLY:
    1776           0 :                 ifp = nb_running_get_entry(args->dnode, NULL, true);
    1777           0 :                 pim_ifp = ifp->info;
    1778           0 :                 pim_ifp->bfd_config.enabled = false;
    1779           0 :                 pim_bfd_reg_dereg_all_nbr(ifp);
    1780           0 :                 break;
    1781             :         }
    1782             : 
    1783             :         return NB_OK;
    1784             : }
    1785             : 
    1786             : /*
    1787             :  * XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/bfd
    1788             :  */
    1789           6 : void lib_interface_pim_address_family_bfd_apply_finish(
    1790             :         struct nb_cb_apply_finish_args *args)
    1791             : {
    1792           6 :         struct interface *ifp;
    1793           6 :         struct pim_interface *pim_ifp;
    1794             : 
    1795           6 :         ifp = nb_running_get_entry(args->dnode, NULL, true);
    1796           6 :         pim_ifp = ifp->info;
    1797             : 
    1798           6 :         if (!pim_ifp) {
    1799           0 :                 zlog_debug("Pim not enabled on this interface");
    1800           0 :                 return;
    1801             :         }
    1802             : 
    1803          12 :         pim_ifp->bfd_config.detection_multiplier =
    1804           6 :                 yang_dnode_get_uint8(args->dnode, "./detect_mult");
    1805          12 :         pim_ifp->bfd_config.min_rx =
    1806           6 :                 yang_dnode_get_uint16(args->dnode, "./min-rx-interval");
    1807          12 :         pim_ifp->bfd_config.min_tx =
    1808           6 :                 yang_dnode_get_uint16(args->dnode, "./min-tx-interval");
    1809             : 
    1810           6 :         pim_bfd_reg_dereg_all_nbr(ifp);
    1811             : }
    1812             : 
    1813             : /*
    1814             :  * XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/bfd/min-rx-interval
    1815             :  */
    1816           0 : int lib_interface_pim_address_family_bfd_min_rx_interval_modify(
    1817             :         struct nb_cb_modify_args *args)
    1818             : {
    1819           0 :         switch (args->event) {
    1820             :         case NB_EV_VALIDATE:
    1821             :         case NB_EV_PREPARE:
    1822             :         case NB_EV_ABORT:
    1823             :         case NB_EV_APPLY:
    1824             :                 break;
    1825             :         }
    1826             : 
    1827           0 :         return NB_OK;
    1828             : }
    1829             : 
    1830             : /*
    1831             :  * XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/bfd/min-tx-interval
    1832             :  */
    1833           0 : int lib_interface_pim_address_family_bfd_min_tx_interval_modify(
    1834             :         struct nb_cb_modify_args *args)
    1835             : {
    1836           0 :         switch (args->event) {
    1837             :         case NB_EV_VALIDATE:
    1838             :         case NB_EV_PREPARE:
    1839             :         case NB_EV_ABORT:
    1840             :         case NB_EV_APPLY:
    1841             :                 break;
    1842             :         }
    1843             : 
    1844           0 :         return NB_OK;
    1845             : }
    1846             : 
    1847             : /*
    1848             :  * XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/bfd/detect_mult
    1849             :  */
    1850           0 : int lib_interface_pim_address_family_bfd_detect_mult_modify(
    1851             :         struct nb_cb_modify_args *args)
    1852             : {
    1853           0 :         switch (args->event) {
    1854             :         case NB_EV_VALIDATE:
    1855             :         case NB_EV_PREPARE:
    1856             :         case NB_EV_ABORT:
    1857             :         case NB_EV_APPLY:
    1858             :                 break;
    1859             :         }
    1860             : 
    1861           0 :         return NB_OK;
    1862             : }
    1863             : 
    1864             : /*
    1865             :  * XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/bfd/profile
    1866             :  */
    1867           3 : int lib_interface_pim_address_family_bfd_profile_modify(
    1868             :         struct nb_cb_modify_args *args)
    1869             : {
    1870           3 :         struct interface *ifp;
    1871           3 :         struct pim_interface *pim_ifp;
    1872             : 
    1873           3 :         switch (args->event) {
    1874             :         case NB_EV_VALIDATE:
    1875             :         case NB_EV_PREPARE:
    1876             :         case NB_EV_ABORT:
    1877             :                 /* NOTHING */
    1878             :                 break;
    1879           1 :         case NB_EV_APPLY:
    1880           1 :                 ifp = nb_running_get_entry(args->dnode, NULL, true);
    1881           1 :                 pim_ifp = ifp->info;
    1882           1 :                 XFREE(MTYPE_TMP, pim_ifp->bfd_config.profile);
    1883           1 :                 pim_ifp->bfd_config.profile = XSTRDUP(
    1884             :                         MTYPE_TMP, yang_dnode_get_string(args->dnode, NULL));
    1885           1 :                 break;
    1886             :         }
    1887             : 
    1888           3 :         return NB_OK;
    1889             : }
    1890             : 
    1891           0 : int lib_interface_pim_address_family_bfd_profile_destroy(
    1892             :         struct nb_cb_destroy_args *args)
    1893             : {
    1894           0 :         struct interface *ifp;
    1895           0 :         struct pim_interface *pim_ifp;
    1896             : 
    1897           0 :         switch (args->event) {
    1898             :         case NB_EV_VALIDATE:
    1899             :         case NB_EV_PREPARE:
    1900             :         case NB_EV_ABORT:
    1901             :                 /* NOTHING */
    1902             :                 break;
    1903           0 :         case NB_EV_APPLY:
    1904           0 :                 ifp = nb_running_get_entry(args->dnode, NULL, true);
    1905           0 :                 pim_ifp = ifp->info;
    1906           0 :                 XFREE(MTYPE_TMP, pim_ifp->bfd_config.profile);
    1907           0 :                 break;
    1908             :         }
    1909             : 
    1910           0 :         return NB_OK;
    1911             : }
    1912             : 
    1913             : /*
    1914             :  * XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/bsm
    1915             :  */
    1916           0 : int lib_interface_pim_address_family_bsm_modify(struct nb_cb_modify_args *args)
    1917             : {
    1918           0 :         struct interface *ifp;
    1919           0 :         struct pim_interface *pim_ifp;
    1920             : 
    1921           0 :         switch (args->event) {
    1922             :         case NB_EV_VALIDATE:
    1923             :         case NB_EV_PREPARE:
    1924             :         case NB_EV_ABORT:
    1925             :                 break;
    1926           0 :         case NB_EV_APPLY:
    1927           0 :                 ifp = nb_running_get_entry(args->dnode, NULL, true);
    1928           0 :                 pim_ifp = ifp->info;
    1929           0 :                 pim_ifp->bsm_enable = yang_dnode_get_bool(args->dnode, NULL);
    1930             : 
    1931           0 :                 break;
    1932             :         }
    1933             : 
    1934           0 :         return NB_OK;
    1935             : }
    1936             : 
    1937             : /*
    1938             :  * XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/unicast-bsm
    1939             :  */
    1940           0 : int lib_interface_pim_address_family_unicast_bsm_modify(
    1941             :         struct nb_cb_modify_args *args)
    1942             : {
    1943           0 :         struct interface *ifp;
    1944           0 :         struct pim_interface *pim_ifp;
    1945             : 
    1946           0 :         switch (args->event) {
    1947             :         case NB_EV_VALIDATE:
    1948             :         case NB_EV_PREPARE:
    1949             :         case NB_EV_ABORT:
    1950             :                 break;
    1951           0 :         case NB_EV_APPLY:
    1952           0 :                 ifp = nb_running_get_entry(args->dnode, NULL, true);
    1953           0 :                 pim_ifp = ifp->info;
    1954           0 :                 pim_ifp->ucast_bsm_accept =
    1955           0 :                         yang_dnode_get_bool(args->dnode, NULL);
    1956             : 
    1957           0 :                 break;
    1958             :         }
    1959             : 
    1960           0 :         return NB_OK;
    1961             : }
    1962             : 
    1963             : /*
    1964             :  * XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/active-active
    1965             :  */
    1966           0 : int lib_interface_pim_address_family_active_active_modify(
    1967             :         struct nb_cb_modify_args *args)
    1968             : {
    1969           0 :         struct interface *ifp;
    1970           0 :         struct pim_interface *pim_ifp;
    1971             : 
    1972           0 :         switch (args->event) {
    1973             :         case NB_EV_VALIDATE:
    1974             :         case NB_EV_PREPARE:
    1975             :         case NB_EV_ABORT:
    1976             :                 break;
    1977           0 :         case NB_EV_APPLY:
    1978           0 :                 ifp = nb_running_get_entry(args->dnode, NULL, true);
    1979           0 :                 pim_ifp = ifp->info;
    1980           0 :                 if (yang_dnode_get_bool(args->dnode, NULL)) {
    1981           0 :                         if (PIM_DEBUG_MLAG)
    1982           0 :                                 zlog_debug(
    1983             :                                         "Configuring PIM active-active on Interface: %s",
    1984             :                                         ifp->name);
    1985           0 :                         pim_if_configure_mlag_dualactive(pim_ifp);
    1986             :                 } else {
    1987           0 :                         if (PIM_DEBUG_MLAG)
    1988           0 :                                 zlog_debug(
    1989             :                                         "UnConfiguring PIM active-active on Interface: %s",
    1990             :                                         ifp->name);
    1991           0 :                         pim_if_unconfigure_mlag_dualactive(pim_ifp);
    1992             :                 }
    1993             : 
    1994             :                 break;
    1995             :         }
    1996             : 
    1997           0 :         return NB_OK;
    1998             : 
    1999             : }
    2000             : 
    2001             : /*
    2002             :  * XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/dr-priority
    2003             :  */
    2004           0 : int lib_interface_pim_address_family_dr_priority_modify(
    2005             :         struct nb_cb_modify_args *args)
    2006             : {
    2007           0 :         struct interface *ifp;
    2008           0 :         struct pim_interface *pim_ifp;
    2009           0 :         uint32_t old_dr_prio;
    2010           0 :         const struct lyd_node *if_dnode;
    2011             : 
    2012           0 :         switch (args->event) {
    2013           0 :         case NB_EV_VALIDATE:
    2014           0 :                 if_dnode = yang_dnode_get_parent(args->dnode, "interface");
    2015           0 :                 if (!is_pim_interface(if_dnode)) {
    2016           0 :                         snprintf(args->errmsg, args->errmsg_len,
    2017             :                                  "Pim not enabled on this interface");
    2018           0 :                         return NB_ERR_VALIDATION;
    2019             :                 }
    2020             :                 break;
    2021             :         case NB_EV_PREPARE:
    2022             :         case NB_EV_ABORT:
    2023             :                 break;
    2024           0 :         case NB_EV_APPLY:
    2025           0 :                 ifp = nb_running_get_entry(args->dnode, NULL, true);
    2026           0 :                 pim_ifp = ifp->info;
    2027           0 :                 old_dr_prio = pim_ifp->pim_dr_priority;
    2028           0 :                 pim_ifp->pim_dr_priority = yang_dnode_get_uint32(args->dnode,
    2029             :                                 NULL);
    2030             : 
    2031           0 :                 if (old_dr_prio != pim_ifp->pim_dr_priority) {
    2032           0 :                         pim_if_dr_election(ifp);
    2033           0 :                         pim_hello_restart_now(ifp);
    2034             :                 }
    2035             :                 break;
    2036             :         }
    2037             : 
    2038             :         return NB_OK;
    2039             : }
    2040             : 
    2041             : /*
    2042             :  * XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/use-source
    2043             :  */
    2044           0 : int lib_interface_pim_address_family_use_source_modify(
    2045             :         struct nb_cb_modify_args *args)
    2046             : {
    2047           0 :         struct interface *ifp;
    2048           0 :         pim_addr source_addr;
    2049           0 :         int result;
    2050           0 :         const struct lyd_node *if_dnode;
    2051             : 
    2052           0 :         switch (args->event) {
    2053           0 :         case NB_EV_VALIDATE:
    2054           0 :                 if_dnode = yang_dnode_get_parent(args->dnode, "interface");
    2055           0 :                 if (!is_pim_interface(if_dnode)) {
    2056           0 :                         snprintf(args->errmsg, args->errmsg_len,
    2057             :                                         "Pim not enabled on this interface");
    2058           0 :                         return NB_ERR_VALIDATION;
    2059             :                 }
    2060             :                 break;
    2061             :         case NB_EV_ABORT:
    2062             :         case NB_EV_PREPARE:
    2063             :                 break;
    2064           0 :         case NB_EV_APPLY:
    2065           0 :                 ifp = nb_running_get_entry(args->dnode, NULL, true);
    2066             : #if PIM_IPV == 4
    2067           0 :                 yang_dnode_get_ipv4(&source_addr, args->dnode, NULL);
    2068             : #else
    2069             :                 yang_dnode_get_ipv6(&source_addr, args->dnode, NULL);
    2070             : #endif
    2071             : 
    2072           0 :                 result = interface_pim_use_src_cmd_worker(
    2073             :                                 ifp, source_addr,
    2074             :                                 args->errmsg, args->errmsg_len);
    2075             : 
    2076           0 :                 if (result != PIM_SUCCESS)
    2077             :                         return NB_ERR_INCONSISTENCY;
    2078             : 
    2079             :                 break;
    2080             :         }
    2081             : 
    2082             :         return NB_OK;
    2083             : }
    2084             : 
    2085           0 : int lib_interface_pim_address_family_use_source_destroy(
    2086             :         struct nb_cb_destroy_args *args)
    2087             : {
    2088           0 :         struct interface *ifp;
    2089           0 :         int result;
    2090           0 :         const struct lyd_node *if_dnode;
    2091             : 
    2092           0 :         switch (args->event) {
    2093           0 :         case NB_EV_VALIDATE:
    2094           0 :                 if_dnode = yang_dnode_get_parent(args->dnode, "interface");
    2095           0 :                 if (!is_pim_interface(if_dnode)) {
    2096           0 :                         snprintf(args->errmsg, args->errmsg_len,
    2097             :                                  "Pim not enabled on this interface");
    2098           0 :                         return NB_ERR_VALIDATION;
    2099             :                 }
    2100           0 :                 break;
    2101             :         case NB_EV_ABORT:
    2102             :         case NB_EV_PREPARE:
    2103             :                 break;
    2104           0 :         case NB_EV_APPLY:
    2105           0 :                 ifp = nb_running_get_entry(args->dnode, NULL, true);
    2106             : 
    2107           0 :                 result = interface_pim_use_src_cmd_worker(ifp, PIMADDR_ANY,
    2108             :                                 args->errmsg,
    2109             :                                 args->errmsg_len);
    2110             : 
    2111           0 :                 if (result != PIM_SUCCESS)
    2112             :                         return NB_ERR_INCONSISTENCY;
    2113             : 
    2114             :                 break;
    2115             :         }
    2116             : 
    2117             :         return NB_OK;
    2118             : }
    2119             : 
    2120             : /*
    2121             :  * XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/multicast-boundary-oil
    2122             :  */
    2123           0 : int lib_interface_pim_address_family_multicast_boundary_oil_modify(
    2124             :         struct nb_cb_modify_args *args)
    2125             : {
    2126           0 :         struct interface *ifp;
    2127           0 :         struct pim_interface *pim_ifp;
    2128           0 :         const char *plist;
    2129           0 :         const struct lyd_node *if_dnode;
    2130             : 
    2131           0 :         switch (args->event) {
    2132           0 :         case NB_EV_VALIDATE:
    2133           0 :                 if_dnode = yang_dnode_get_parent(args->dnode, "interface");
    2134           0 :                 if (!is_pim_interface(if_dnode)) {
    2135           0 :                         snprintf(args->errmsg, args->errmsg_len,
    2136             :                                         "Pim not enabled on this interface");
    2137           0 :                         return NB_ERR_VALIDATION;
    2138             :                 }
    2139             :                 break;
    2140             :         case NB_EV_ABORT:
    2141             :         case NB_EV_PREPARE:
    2142             :                 break;
    2143           0 :         case NB_EV_APPLY:
    2144           0 :                 ifp = nb_running_get_entry(args->dnode, NULL, true);
    2145           0 :                 pim_ifp = ifp->info;
    2146           0 :                 plist = yang_dnode_get_string(args->dnode, NULL);
    2147             : 
    2148           0 :                 if (pim_ifp->boundary_oil_plist)
    2149           0 :                         XFREE(MTYPE_PIM_INTERFACE, pim_ifp->boundary_oil_plist);
    2150             : 
    2151           0 :                 pim_ifp->boundary_oil_plist =
    2152           0 :                         XSTRDUP(MTYPE_PIM_INTERFACE, plist);
    2153             : 
    2154           0 :                 break;
    2155             :         }
    2156             : 
    2157             :         return NB_OK;
    2158             : }
    2159             : 
    2160           0 : int lib_interface_pim_address_family_multicast_boundary_oil_destroy(
    2161             :         struct nb_cb_destroy_args *args)
    2162             : {
    2163           0 :         struct interface *ifp;
    2164           0 :         struct pim_interface *pim_ifp;
    2165           0 :         const struct lyd_node *if_dnode;
    2166             : 
    2167           0 :         switch (args->event) {
    2168           0 :         case NB_EV_VALIDATE:
    2169           0 :                 if_dnode = yang_dnode_get_parent(args->dnode, "interface");
    2170           0 :                 if (!is_pim_interface(if_dnode)) {
    2171           0 :                         snprintf(args->errmsg, args->errmsg_len,
    2172             :                                  "%% Enable PIM and/or IGMP on this interface first");
    2173           0 :                         return NB_ERR_VALIDATION;
    2174             :                 }
    2175             :                 break;
    2176             :         case NB_EV_ABORT:
    2177             :         case NB_EV_PREPARE:
    2178             :                 break;
    2179           0 :         case NB_EV_APPLY:
    2180           0 :                 ifp = nb_running_get_entry(args->dnode, NULL, true);
    2181           0 :                 pim_ifp = ifp->info;
    2182           0 :                 if (pim_ifp->boundary_oil_plist)
    2183           0 :                         XFREE(MTYPE_PIM_INTERFACE, pim_ifp->boundary_oil_plist);
    2184             :                 break;
    2185             :         }
    2186             : 
    2187             :         return NB_OK;
    2188             : }
    2189             : 
    2190             : /*
    2191             :  * XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/mroute
    2192             :  */
    2193           0 : int lib_interface_pim_address_family_mroute_create(
    2194             :         struct nb_cb_create_args *args)
    2195             : {
    2196           0 :         switch (args->event) {
    2197             :         case NB_EV_VALIDATE:
    2198             :         case NB_EV_PREPARE:
    2199             :         case NB_EV_ABORT:
    2200             :         case NB_EV_APPLY:
    2201             :                 break;
    2202             :         }
    2203             : 
    2204           0 :         return NB_OK;
    2205             : }
    2206             : 
    2207           0 : int lib_interface_pim_address_family_mroute_destroy(
    2208             :         struct nb_cb_destroy_args *args)
    2209             : {
    2210           0 :         struct pim_instance *pim;
    2211           0 :         struct pim_interface *pim_iifp;
    2212           0 :         struct interface *iif;
    2213           0 :         struct interface *oif;
    2214           0 :         const char *oifname;
    2215           0 :         pim_addr source_addr;
    2216           0 :         pim_addr group_addr;
    2217           0 :         const struct lyd_node *if_dnode;
    2218             : 
    2219           0 :         switch (args->event) {
    2220           0 :         case NB_EV_VALIDATE:
    2221           0 :                 if_dnode = yang_dnode_get_parent(args->dnode, "interface");
    2222           0 :                 if (!is_pim_interface(if_dnode)) {
    2223           0 :                         snprintf(args->errmsg, args->errmsg_len,
    2224             :                                  "%% Enable PIM and/or IGMP on this interface first");
    2225           0 :                         return NB_ERR_VALIDATION;
    2226             :                 }
    2227             :                 break;
    2228             :         case NB_EV_PREPARE:
    2229             :         case NB_EV_ABORT:
    2230             :                 break;
    2231           0 :         case NB_EV_APPLY:
    2232           0 :                 iif = nb_running_get_entry(args->dnode, NULL, true);
    2233           0 :                 pim_iifp = iif->info;
    2234           0 :                 pim = pim_iifp->pim;
    2235             : 
    2236           0 :                 oifname = yang_dnode_get_string(args->dnode, "./oif");
    2237           0 :                 oif = if_lookup_by_name(oifname, pim->vrf->vrf_id);
    2238             : 
    2239           0 :                 if (!oif) {
    2240           0 :                         snprintf(args->errmsg, args->errmsg_len,
    2241             :                                         "No such interface name %s",
    2242             :                                         oifname);
    2243           0 :                         return NB_ERR_INCONSISTENCY;
    2244             :                 }
    2245             : 
    2246           0 :                 yang_dnode_get_pimaddr(&source_addr, args->dnode, "./source-addr");
    2247           0 :                 yang_dnode_get_pimaddr(&group_addr, args->dnode, "./group-addr");
    2248             : 
    2249           0 :                 if (pim_static_del(pim, iif, oif, group_addr, source_addr)) {
    2250           0 :                         snprintf(args->errmsg, args->errmsg_len,
    2251             :                                         "Failed to remove static mroute");
    2252           0 :                         return NB_ERR_INCONSISTENCY;
    2253             :                 }
    2254             : 
    2255             :                 break;
    2256             :         }
    2257             : 
    2258             :         return NB_OK;
    2259             : }
    2260             : 
    2261             : /*
    2262             :  * XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/mroute/oif
    2263             :  */
    2264           0 : int lib_interface_pim_address_family_mroute_oif_modify(
    2265             :         struct nb_cb_modify_args *args)
    2266             : {
    2267           0 :         struct pim_instance *pim;
    2268           0 :         struct pim_interface *pim_iifp;
    2269           0 :         struct interface *iif;
    2270           0 :         struct interface *oif;
    2271           0 :         const char *oifname;
    2272           0 :         pim_addr source_addr;
    2273           0 :         pim_addr group_addr;
    2274           0 :         const struct lyd_node *if_dnode;
    2275             : 
    2276           0 :         switch (args->event) {
    2277           0 :         case NB_EV_VALIDATE:
    2278           0 :                 if_dnode = yang_dnode_get_parent(args->dnode, "interface");
    2279           0 :                 if (!is_pim_interface(if_dnode)) {
    2280           0 :                         snprintf(args->errmsg, args->errmsg_len,
    2281             :                                  "%% Enable PIM and/or IGMP on this interface first");
    2282           0 :                         return NB_ERR_VALIDATION;
    2283             :                 }
    2284             : 
    2285             : #ifdef PIM_ENFORCE_LOOPFREE_MFC
    2286           0 :                 iif = nb_running_get_entry(args->dnode, NULL, false);
    2287           0 :                 if (!iif) {
    2288             :                         return NB_OK;
    2289             :                 }
    2290             : 
    2291           0 :                 pim_iifp = iif->info;
    2292           0 :                 pim = pim_iifp->pim;
    2293             : 
    2294           0 :                 oifname = yang_dnode_get_string(args->dnode, NULL);
    2295           0 :                 oif = if_lookup_by_name(oifname, pim->vrf->vrf_id);
    2296             : 
    2297           0 :                 if (oif && (iif->ifindex == oif->ifindex)) {
    2298           0 :                         strlcpy(args->errmsg,
    2299             :                                 "% IIF same as OIF and loopfree enforcement is enabled; rejecting",
    2300             :                                 args->errmsg_len);
    2301           0 :                         return NB_ERR_VALIDATION;
    2302             :                 }
    2303             : #endif
    2304             :                 break;
    2305             :         case NB_EV_PREPARE:
    2306             :         case NB_EV_ABORT:
    2307             :                 break;
    2308           0 :         case NB_EV_APPLY:
    2309           0 :                 iif = nb_running_get_entry(args->dnode, NULL, true);
    2310           0 :                 pim_iifp = iif->info;
    2311           0 :                 pim = pim_iifp->pim;
    2312             : 
    2313           0 :                 oifname = yang_dnode_get_string(args->dnode, NULL);
    2314           0 :                 oif = if_lookup_by_name(oifname, pim->vrf->vrf_id);
    2315           0 :                 if (!oif) {
    2316           0 :                         snprintf(args->errmsg, args->errmsg_len,
    2317             :                                  "No such interface name %s",
    2318             :                                  oifname);
    2319           0 :                         return NB_ERR_INCONSISTENCY;
    2320             :                 }
    2321             : 
    2322           0 :                 yang_dnode_get_pimaddr(&source_addr, args->dnode, "../source-addr");
    2323           0 :                 yang_dnode_get_pimaddr(&group_addr, args->dnode, "../group-addr");
    2324             : 
    2325           0 :                 if (pim_static_add(pim, iif, oif, group_addr, source_addr)) {
    2326           0 :                         snprintf(args->errmsg, args->errmsg_len,
    2327             :                                  "Failed to add static mroute");
    2328           0 :                         return NB_ERR_INCONSISTENCY;
    2329             :                 }
    2330             : 
    2331             :                 break;
    2332             :         }
    2333             : 
    2334             :         return NB_OK;
    2335             : }
    2336             : 
    2337           0 : int lib_interface_pim_address_family_mroute_oif_destroy(
    2338             :         struct nb_cb_destroy_args *args)
    2339             : {
    2340           0 :         switch (args->event) {
    2341             :         case NB_EV_VALIDATE:
    2342             :         case NB_EV_PREPARE:
    2343             :         case NB_EV_ABORT:
    2344             :         case NB_EV_APPLY:
    2345             :                 break;
    2346             :         }
    2347             : 
    2348           0 :         return NB_OK;
    2349             : }
    2350             : 
    2351             : /*
    2352             :  * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/frr-pim-rp:rp/static-rp/rp-list
    2353             :  */
    2354           0 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_static_rp_rp_list_create(
    2355             :         struct nb_cb_create_args *args)
    2356             : {
    2357           0 :         switch (args->event) {
    2358             :         case NB_EV_VALIDATE:
    2359             :         case NB_EV_PREPARE:
    2360             :         case NB_EV_ABORT:
    2361             :         case NB_EV_APPLY:
    2362             :                 break;
    2363             :         }
    2364             : 
    2365           0 :         return NB_OK;
    2366             : }
    2367             : 
    2368           0 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_static_rp_rp_list_destroy(
    2369             :         struct nb_cb_destroy_args *args)
    2370             : {
    2371           0 :         struct vrf *vrf;
    2372           0 :         struct pim_instance *pim;
    2373           0 :         struct prefix group;
    2374           0 :         pim_addr rp_addr;
    2375           0 :         const char *plist;
    2376           0 :         int result = 0;
    2377             : 
    2378           0 :         switch (args->event) {
    2379             :         case NB_EV_VALIDATE:
    2380             :         case NB_EV_PREPARE:
    2381             :         case NB_EV_ABORT:
    2382             :                 break;
    2383           0 :         case NB_EV_APPLY:
    2384           0 :                 vrf = nb_running_get_entry(args->dnode, NULL, true);
    2385           0 :                 pim = vrf->info;
    2386           0 :                 yang_dnode_get_pimaddr(&rp_addr, args->dnode, "./rp-address");
    2387             : 
    2388           0 :                 if (yang_dnode_get(args->dnode, "./group-list")) {
    2389           0 :                         yang_dnode_get_prefix(&group, args->dnode,
    2390             :                                               "./group-list");
    2391           0 :                         apply_mask(&group);
    2392           0 :                         result = pim_no_rp_cmd_worker(pim, rp_addr, group, NULL,
    2393             :                                                       args->errmsg,
    2394             :                                                       args->errmsg_len);
    2395             :                 }
    2396             : 
    2397           0 :                 else if (yang_dnode_get(args->dnode, "./prefix-list")) {
    2398           0 :                         plist = yang_dnode_get_string(args->dnode,
    2399             :                                         "./prefix-list");
    2400           0 :                         if (!pim_get_all_mcast_group(&group)) {
    2401           0 :                                 flog_err(
    2402             :                                         EC_LIB_DEVELOPMENT,
    2403             :                                         "Unable to convert 224.0.0.0/4 to prefix");
    2404           0 :                                 return NB_ERR_INCONSISTENCY;
    2405             :                         }
    2406             : 
    2407           0 :                         result = pim_no_rp_cmd_worker(pim, rp_addr, group,
    2408             :                                                       plist, args->errmsg,
    2409             :                                                       args->errmsg_len);
    2410             :                 }
    2411             : 
    2412           0 :                 if (result)
    2413             :                         return NB_ERR_INCONSISTENCY;
    2414             :                 break;
    2415             :         }
    2416             : 
    2417             :         return NB_OK;
    2418             : }
    2419             : 
    2420             : /*
    2421             :  * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/frr-pim-rp:rp/static-rp/rp-list/group-list
    2422             :  */
    2423           0 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_static_rp_rp_list_group_list_create(
    2424             :         struct nb_cb_create_args *args)
    2425             : {
    2426           0 :         struct vrf *vrf;
    2427           0 :         struct pim_instance *pim;
    2428           0 :         struct prefix group;
    2429           0 :         pim_addr rp_addr;
    2430             : 
    2431           0 :         switch (args->event) {
    2432             :         case NB_EV_VALIDATE:
    2433             :         case NB_EV_PREPARE:
    2434             :         case NB_EV_ABORT:
    2435             :                 break;
    2436           0 :         case NB_EV_APPLY:
    2437           0 :                 vrf = nb_running_get_entry(args->dnode, NULL, true);
    2438           0 :                 pim = vrf->info;
    2439           0 :                 yang_dnode_get_pimaddr(&rp_addr, args->dnode, "../rp-address");
    2440           0 :                 yang_dnode_get_prefix(&group, args->dnode, NULL);
    2441           0 :                 apply_mask(&group);
    2442           0 :                 return pim_rp_cmd_worker(pim, rp_addr, group, NULL,
    2443             :                                          args->errmsg, args->errmsg_len);
    2444             :         }
    2445             : 
    2446             :         return NB_OK;
    2447             : }
    2448             : 
    2449           0 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_static_rp_rp_list_group_list_destroy(
    2450             :         struct nb_cb_destroy_args *args)
    2451             : {
    2452           0 :         struct vrf *vrf;
    2453           0 :         struct pim_instance *pim;
    2454           0 :         struct prefix group;
    2455           0 :         pim_addr rp_addr;
    2456             : 
    2457           0 :         switch (args->event) {
    2458             :         case NB_EV_VALIDATE:
    2459             :         case NB_EV_PREPARE:
    2460             :         case NB_EV_ABORT:
    2461             :                 break;
    2462           0 :         case NB_EV_APPLY:
    2463           0 :                 vrf = nb_running_get_entry(args->dnode, NULL, true);
    2464           0 :                 pim = vrf->info;
    2465           0 :                 yang_dnode_get_pimaddr(&rp_addr, args->dnode, "../rp-address");
    2466           0 :                 yang_dnode_get_prefix(&group, args->dnode, NULL);
    2467           0 :                 apply_mask(&group);
    2468             : 
    2469           0 :                 return pim_no_rp_cmd_worker(pim, rp_addr, group, NULL,
    2470             :                                             args->errmsg, args->errmsg_len);
    2471             :         }
    2472             : 
    2473             :         return NB_OK;
    2474             : }
    2475             : 
    2476             : /*
    2477             :  * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/frr-pim-rp:rp/static-rp/rp-list/prefix-list
    2478             :  */
    2479           0 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_static_rp_rp_list_prefix_list_modify(
    2480             :         struct nb_cb_modify_args *args)
    2481             : {
    2482           0 :         struct vrf *vrf;
    2483           0 :         struct pim_instance *pim;
    2484           0 :         struct prefix group;
    2485           0 :         pim_addr rp_addr;
    2486           0 :         const char *plist;
    2487             : 
    2488           0 :         switch (args->event) {
    2489             :         case NB_EV_VALIDATE:
    2490             :         case NB_EV_PREPARE:
    2491             :         case NB_EV_ABORT:
    2492             :                 break;
    2493           0 :         case NB_EV_APPLY:
    2494           0 :                 vrf = nb_running_get_entry(args->dnode, NULL, true);
    2495           0 :                 pim = vrf->info;
    2496           0 :                 plist = yang_dnode_get_string(args->dnode, NULL);
    2497           0 :                 yang_dnode_get_pimaddr(&rp_addr, args->dnode, "../rp-address");
    2498           0 :                 if (!pim_get_all_mcast_group(&group)) {
    2499           0 :                         flog_err(EC_LIB_DEVELOPMENT,
    2500             :                                  "Unable to convert 224.0.0.0/4 to prefix");
    2501           0 :                         return NB_ERR_INCONSISTENCY;
    2502             :                 }
    2503           0 :                 return pim_rp_cmd_worker(pim, rp_addr, group, plist,
    2504             :                                          args->errmsg, args->errmsg_len);
    2505             :         }
    2506             : 
    2507             :         return NB_OK;
    2508             : }
    2509             : 
    2510           0 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_static_rp_rp_list_prefix_list_destroy(
    2511             :         struct nb_cb_destroy_args *args)
    2512             : {
    2513           0 :         struct vrf *vrf;
    2514           0 :         struct pim_instance *pim;
    2515           0 :         struct prefix group;
    2516           0 :         pim_addr rp_addr;
    2517           0 :         const char *plist;
    2518             : 
    2519           0 :         switch (args->event) {
    2520             :         case NB_EV_VALIDATE:
    2521             :         case NB_EV_PREPARE:
    2522             :         case NB_EV_ABORT:
    2523             :                 break;
    2524           0 :         case NB_EV_APPLY:
    2525           0 :                 vrf = nb_running_get_entry(args->dnode, NULL, true);
    2526           0 :                 pim = vrf->info;
    2527           0 :                 yang_dnode_get_pimaddr(&rp_addr, args->dnode, "../rp-address");
    2528           0 :                 plist = yang_dnode_get_string(args->dnode, NULL);
    2529           0 :                 if (!pim_get_all_mcast_group(&group)) {
    2530           0 :                         flog_err(EC_LIB_DEVELOPMENT,
    2531             :                                  "Unable to convert 224.0.0.0/4 to prefix");
    2532           0 :                         return NB_ERR_INCONSISTENCY;
    2533             :                 }
    2534           0 :                 return pim_no_rp_cmd_worker(pim, rp_addr, group, plist,
    2535             :                                             args->errmsg, args->errmsg_len);
    2536             :                 break;
    2537             :         }
    2538             : 
    2539             :         return NB_OK;
    2540             : }
    2541             : 
    2542             : /*
    2543             :  * XPath: /frr-interface:lib/interface/frr-gmp:gmp/address-family
    2544             :  */
    2545           0 : int lib_interface_gmp_address_family_create(struct nb_cb_create_args *args)
    2546             : {
    2547           0 :         switch (args->event) {
    2548             :         case NB_EV_VALIDATE:
    2549             :         case NB_EV_PREPARE:
    2550             :         case NB_EV_ABORT:
    2551             :         case NB_EV_APPLY:
    2552             :                 break;
    2553             :         }
    2554             : 
    2555           0 :         return NB_OK;
    2556             : }
    2557             : 
    2558           0 : int lib_interface_gmp_address_family_destroy(struct nb_cb_destroy_args *args)
    2559             : {
    2560           0 :         struct interface *ifp;
    2561           0 :         struct pim_interface *pim_ifp;
    2562             : 
    2563           0 :         switch (args->event) {
    2564             :         case NB_EV_VALIDATE:
    2565             :         case NB_EV_PREPARE:
    2566             :         case NB_EV_ABORT:
    2567             :                 break;
    2568           0 :         case NB_EV_APPLY:
    2569           0 :                 ifp = nb_running_get_entry(args->dnode, NULL, true);
    2570           0 :                 pim_ifp = ifp->info;
    2571             : 
    2572           0 :                 if (!pim_ifp)
    2573             :                         return NB_OK;
    2574             : 
    2575           0 :                 pim_ifp->gm_enable = false;
    2576             : 
    2577           0 :                 pim_if_membership_clear(ifp);
    2578             : 
    2579           0 :                 pim_if_addr_del_all_igmp(ifp);
    2580             : 
    2581           0 :                 if (!pim_ifp->pim_enable)
    2582           0 :                         pim_if_delete(ifp);
    2583             :         }
    2584             : 
    2585             :         return NB_OK;
    2586             : }
    2587             : 
    2588             : /*
    2589             :  * XPath: /frr-interface:lib/interface/frr-gmp:gmp/address-family/enable
    2590             :  */
    2591           0 : int lib_interface_gmp_address_family_enable_modify(
    2592             :         struct nb_cb_modify_args *args)
    2593             : {
    2594           0 :         struct interface *ifp;
    2595           0 :         bool gm_enable;
    2596           0 :         struct pim_interface *pim_ifp;
    2597           0 :         int mcast_if_count;
    2598           0 :         const char *ifp_name;
    2599           0 :         const struct lyd_node *if_dnode;
    2600             : 
    2601           0 :         switch (args->event) {
    2602           0 :         case NB_EV_VALIDATE:
    2603           0 :                 if_dnode = yang_dnode_get_parent(args->dnode, "interface");
    2604           0 :                 mcast_if_count =
    2605           0 :                         yang_get_list_elements_count(if_dnode);
    2606             :                 /* Limiting mcast interfaces to number of VIFs */
    2607           0 :                 if (mcast_if_count == MAXVIFS) {
    2608           0 :                         ifp_name = yang_dnode_get_string(if_dnode, "name");
    2609           0 :                         snprintf(
    2610             :                                 args->errmsg, args->errmsg_len,
    2611             :                                 "Max multicast interfaces(%d) Reached. Could not enable %s on interface %s",
    2612             :                                 MAXVIFS, GM, ifp_name);
    2613           0 :                         return NB_ERR_VALIDATION;
    2614             :                 }
    2615             :                 break;
    2616             :         case NB_EV_PREPARE:
    2617             :         case NB_EV_ABORT:
    2618             :                 break;
    2619           0 :         case NB_EV_APPLY:
    2620           0 :                 ifp = nb_running_get_entry(args->dnode, NULL, true);
    2621           0 :                 gm_enable = yang_dnode_get_bool(args->dnode, NULL);
    2622             : 
    2623           0 :                 if (gm_enable)
    2624           0 :                         return pim_cmd_gm_start(ifp);
    2625             : 
    2626             :                 else {
    2627           0 :                         pim_ifp = ifp->info;
    2628             : 
    2629           0 :                         if (!pim_ifp)
    2630             :                                 return NB_ERR_INCONSISTENCY;
    2631             : 
    2632           0 :                         pim_ifp->gm_enable = false;
    2633             : 
    2634           0 :                         pim_if_membership_clear(ifp);
    2635             : 
    2636             : #if PIM_IPV == 4
    2637           0 :                         pim_if_addr_del_all_igmp(ifp);
    2638             : #else
    2639             :                         gm_ifp_teardown(ifp);
    2640             : #endif
    2641             : 
    2642           0 :                         if (!pim_ifp->pim_enable)
    2643           0 :                                 pim_if_delete(ifp);
    2644             :                 }
    2645             :         }
    2646             :         return NB_OK;
    2647             : }
    2648             : 
    2649             : /*
    2650             :  * XPath: /frr-interface:lib/interface/frr-gmp:gmp/address-family/igmp-version
    2651             :  */
    2652           0 : int lib_interface_gmp_address_family_igmp_version_modify(
    2653             :         struct nb_cb_modify_args *args)
    2654             : {
    2655           0 :         struct interface *ifp;
    2656           0 :         struct pim_interface *pim_ifp;
    2657           0 :         int igmp_version, old_version = 0;
    2658             : 
    2659           0 :         switch (args->event) {
    2660             :         case NB_EV_VALIDATE:
    2661             :         case NB_EV_PREPARE:
    2662             :         case NB_EV_ABORT:
    2663             :                 break;
    2664           0 :         case NB_EV_APPLY:
    2665           0 :                 ifp = nb_running_get_entry(args->dnode, NULL, true);
    2666           0 :                 pim_ifp = ifp->info;
    2667             : 
    2668           0 :                 if (!pim_ifp)
    2669             :                         return NB_ERR_INCONSISTENCY;
    2670             : 
    2671           0 :                 igmp_version = yang_dnode_get_uint8(args->dnode, NULL);
    2672           0 :                 old_version = pim_ifp->igmp_version;
    2673           0 :                 pim_ifp->igmp_version = igmp_version;
    2674             : 
    2675             :                 /* Current and new version is different refresh existing
    2676             :                  * membership. Going from 3 -> 2 or 2 -> 3.
    2677             :                  */
    2678           0 :                 if (old_version != igmp_version)
    2679           0 :                         pim_if_membership_refresh(ifp);
    2680             : 
    2681             :                 break;
    2682             :         }
    2683             : 
    2684             :         return NB_OK;
    2685             : }
    2686             : 
    2687           0 : int lib_interface_gmp_address_family_igmp_version_destroy(
    2688             :         struct nb_cb_destroy_args *args)
    2689             : {
    2690           0 :         struct interface *ifp;
    2691           0 :         struct pim_interface *pim_ifp;
    2692             : 
    2693           0 :         switch (args->event) {
    2694             :         case NB_EV_VALIDATE:
    2695             :         case NB_EV_PREPARE:
    2696             :         case NB_EV_ABORT:
    2697             :                 break;
    2698           0 :         case NB_EV_APPLY:
    2699           0 :                 ifp = nb_running_get_entry(args->dnode, NULL, true);
    2700           0 :                 pim_ifp = ifp->info;
    2701           0 :                 pim_ifp->igmp_version = IGMP_DEFAULT_VERSION;
    2702           0 :                 break;
    2703             :         }
    2704             : 
    2705           0 :         return NB_OK;
    2706             : }
    2707             : 
    2708             : /*
    2709             :  * XPath: /frr-interface:lib/interface/frr-gmp:gmp/address-family/mld-version
    2710             :  */
    2711           0 : int lib_interface_gmp_address_family_mld_version_modify(
    2712             :         struct nb_cb_modify_args *args)
    2713             : {
    2714           0 :         struct interface *ifp;
    2715           0 :         struct pim_interface *pim_ifp;
    2716             : 
    2717           0 :         switch (args->event) {
    2718             :         case NB_EV_VALIDATE:
    2719             :         case NB_EV_PREPARE:
    2720             :         case NB_EV_ABORT:
    2721             :                 break;
    2722           0 :         case NB_EV_APPLY:
    2723           0 :                 ifp = nb_running_get_entry(args->dnode, NULL, true);
    2724           0 :                 pim_ifp = ifp->info;
    2725           0 :                 if (!pim_ifp)
    2726             :                         return NB_ERR_INCONSISTENCY;
    2727             : 
    2728           0 :                 pim_ifp->mld_version = yang_dnode_get_uint8(args->dnode, NULL);
    2729           0 :                 gm_ifp_update(ifp);
    2730             :                 break;
    2731             :         }
    2732             : 
    2733             :         return NB_OK;
    2734             : }
    2735             : 
    2736           0 : int lib_interface_gmp_address_family_mld_version_destroy(
    2737             :         struct nb_cb_destroy_args *args)
    2738             : {
    2739           0 :         struct interface *ifp;
    2740           0 :         struct pim_interface *pim_ifp;
    2741             : 
    2742           0 :         switch (args->event) {
    2743             :         case NB_EV_VALIDATE:
    2744             :         case NB_EV_PREPARE:
    2745             :         case NB_EV_ABORT:
    2746             :                 break;
    2747           0 :         case NB_EV_APPLY:
    2748           0 :                 ifp = nb_running_get_entry(args->dnode, NULL, true);
    2749           0 :                 pim_ifp = ifp->info;
    2750           0 :                 if (!pim_ifp)
    2751             :                         return NB_ERR_INCONSISTENCY;
    2752             : 
    2753           0 :                 pim_ifp->mld_version = 2;
    2754           0 :                 gm_ifp_update(ifp);
    2755             :                 break;
    2756             :         }
    2757             : 
    2758             :         return NB_OK;
    2759             : }
    2760             : 
    2761             : /*
    2762             :  * XPath: /frr-interface:lib/interface/frr-gmp:gmp/address-family/query-interval
    2763             :  */
    2764           0 : int lib_interface_gmp_address_family_query_interval_modify(
    2765             :         struct nb_cb_modify_args *args)
    2766             : {
    2767           0 :         struct interface *ifp;
    2768           0 :         int query_interval;
    2769             : 
    2770             : #if PIM_IPV == 4
    2771           0 :         switch (args->event) {
    2772             :         case NB_EV_VALIDATE:
    2773             :         case NB_EV_PREPARE:
    2774             :         case NB_EV_ABORT:
    2775             :                 break;
    2776           0 :         case NB_EV_APPLY:
    2777           0 :                 ifp = nb_running_get_entry(args->dnode, NULL, true);
    2778           0 :                 query_interval = yang_dnode_get_uint16(args->dnode, NULL);
    2779           0 :                 change_query_interval(ifp->info, query_interval);
    2780             :         }
    2781             : #else
    2782             :         struct pim_interface *pim_ifp;
    2783             : 
    2784             :         switch (args->event) {
    2785             :         case NB_EV_VALIDATE:
    2786             :         case NB_EV_PREPARE:
    2787             :         case NB_EV_ABORT:
    2788             :                 break;
    2789             :         case NB_EV_APPLY:
    2790             :                 ifp = nb_running_get_entry(args->dnode, NULL, true);
    2791             :                 pim_ifp = ifp->info;
    2792             :                 if (!pim_ifp)
    2793             :                         return NB_ERR_INCONSISTENCY;
    2794             : 
    2795             :                 query_interval = yang_dnode_get_uint16(args->dnode, NULL);
    2796             :                 pim_ifp->gm_default_query_interval = query_interval;
    2797             :                 gm_ifp_update(ifp);
    2798             :         }
    2799             : #endif
    2800           0 :         return NB_OK;
    2801             : }
    2802             : 
    2803             : /*
    2804             :  * XPath: /frr-interface:lib/interface/frr-gmp:gmp/address-family/query-max-response-time
    2805             :  */
    2806           0 : int lib_interface_gmp_address_family_query_max_response_time_modify(
    2807             :         struct nb_cb_modify_args *args)
    2808             : {
    2809           0 :         struct interface *ifp;
    2810           0 :         int query_max_response_time_dsec;
    2811             : 
    2812           0 :         switch (args->event) {
    2813             :         case NB_EV_VALIDATE:
    2814             :         case NB_EV_PREPARE:
    2815             :         case NB_EV_ABORT:
    2816             :                 break;
    2817           0 :         case NB_EV_APPLY:
    2818           0 :                 ifp = nb_running_get_entry(args->dnode, NULL, true);
    2819           0 :                 query_max_response_time_dsec =
    2820           0 :                         yang_dnode_get_uint16(args->dnode, NULL);
    2821           0 :                 change_query_max_response_time(ifp,
    2822             :                                                query_max_response_time_dsec);
    2823             :         }
    2824             : 
    2825           0 :         return NB_OK;
    2826             : }
    2827             : 
    2828             : /*
    2829             :  * XPath: /frr-interface:lib/interface/frr-gmp:gmp/address-family/last-member-query-interval
    2830             :  */
    2831           0 : int lib_interface_gmp_address_family_last_member_query_interval_modify(
    2832             :         struct nb_cb_modify_args *args)
    2833             : {
    2834           0 :         struct interface *ifp;
    2835           0 :         struct pim_interface *pim_ifp;
    2836           0 :         int last_member_query_interval;
    2837             : 
    2838           0 :         switch (args->event) {
    2839             :         case NB_EV_VALIDATE:
    2840             :         case NB_EV_PREPARE:
    2841             :         case NB_EV_ABORT:
    2842             :                 break;
    2843           0 :         case NB_EV_APPLY:
    2844           0 :                 ifp = nb_running_get_entry(args->dnode, NULL, true);
    2845           0 :                 pim_ifp = ifp->info;
    2846           0 :                 last_member_query_interval =
    2847           0 :                         yang_dnode_get_uint16(args->dnode, NULL);
    2848           0 :                 pim_ifp->gm_specific_query_max_response_time_dsec =
    2849             :                         last_member_query_interval;
    2850             : #if PIM_IPV == 6
    2851             :                 gm_ifp_update(ifp);
    2852             : #endif
    2853             : 
    2854           0 :                 break;
    2855             :         }
    2856             : 
    2857           0 :         return NB_OK;
    2858             : }
    2859             : 
    2860             : /*
    2861             :  * XPath: /frr-interface:lib/interface/frr-gmp:gmp/address-family/robustness-variable
    2862             :  */
    2863           0 : int lib_interface_gmp_address_family_robustness_variable_modify(
    2864             :         struct nb_cb_modify_args *args)
    2865             : {
    2866           0 :         struct interface *ifp;
    2867           0 :         struct pim_interface *pim_ifp;
    2868           0 :         int last_member_query_count;
    2869             : 
    2870           0 :         switch (args->event) {
    2871             :         case NB_EV_VALIDATE:
    2872             :         case NB_EV_PREPARE:
    2873             :         case NB_EV_ABORT:
    2874             :                 break;
    2875           0 :         case NB_EV_APPLY:
    2876           0 :                 ifp = nb_running_get_entry(args->dnode, NULL, true);
    2877           0 :                 pim_ifp = ifp->info;
    2878           0 :                 last_member_query_count =
    2879           0 :                         yang_dnode_get_uint8(args->dnode, NULL);
    2880           0 :                 pim_ifp->gm_last_member_query_count = last_member_query_count;
    2881             : #if PIM_IPV == 6
    2882             :                 gm_ifp_update(ifp);
    2883             : #endif
    2884           0 :                 break;
    2885             :         }
    2886             : 
    2887           0 :         return NB_OK;
    2888             : }
    2889             : 
    2890             : /*
    2891             :  * XPath: /frr-interface:lib/interface/frr-gmp:gmp/address-family/static-group
    2892             :  */
    2893           0 : int lib_interface_gmp_address_family_static_group_create(
    2894             :         struct nb_cb_create_args *args)
    2895             : {
    2896             : #if PIM_IPV == 4
    2897           0 :         struct interface *ifp;
    2898           0 :         struct ipaddr source_addr;
    2899           0 :         struct ipaddr group_addr;
    2900           0 :         int result;
    2901           0 :         const char *ifp_name;
    2902           0 :         const struct lyd_node *if_dnode;
    2903             : 
    2904           0 :         switch (args->event) {
    2905           0 :         case NB_EV_VALIDATE:
    2906           0 :                 if_dnode =  yang_dnode_get_parent(args->dnode, "interface");
    2907           0 :                 if (!is_pim_interface(if_dnode)) {
    2908           0 :                         ifp_name = yang_dnode_get_string(if_dnode, "name");
    2909           0 :                         snprintf(args->errmsg, args->errmsg_len,
    2910             :                                  "multicast not enabled on interface %s",
    2911             :                                  ifp_name);
    2912           0 :                         return NB_ERR_VALIDATION;
    2913             :                 }
    2914             : 
    2915           0 :                 yang_dnode_get_ip(&group_addr, args->dnode, "./group-addr");
    2916           0 :                 if (pim_is_group_224_0_0_0_24(group_addr.ip._v4_addr)) {
    2917           0 :                         snprintf(
    2918             :                                 args->errmsg, args->errmsg_len,
    2919             :                                 "Groups within 224.0.0.0/24 are reserved and cannot be joined");
    2920           0 :                         return NB_ERR_VALIDATION;
    2921             :                 }
    2922             :                 break;
    2923             :         case NB_EV_PREPARE:
    2924             :         case NB_EV_ABORT:
    2925             :                 break;
    2926           0 :         case NB_EV_APPLY:
    2927           0 :                 ifp = nb_running_get_entry(args->dnode, NULL, true);
    2928           0 :                 yang_dnode_get_ip(&source_addr, args->dnode, "./source-addr");
    2929           0 :                 yang_dnode_get_ip(&group_addr, args->dnode, "./group-addr");
    2930             : 
    2931           0 :                 result = pim_if_igmp_join_add(ifp, group_addr.ip._v4_addr,
    2932             :                                 source_addr.ip._v4_addr);
    2933           0 :                 if (result) {
    2934           0 :                         snprintf(args->errmsg, args->errmsg_len,
    2935             :                                  "Failure joining IGMP group");
    2936           0 :                         return NB_ERR_INCONSISTENCY;
    2937             :                 }
    2938             :         }
    2939             : #else
    2940             :         /* TBD Depends on MLD data structure changes */
    2941             : #endif /* PIM_IPV == 4 */
    2942             :         return NB_OK;
    2943             : }
    2944             : 
    2945           0 : int lib_interface_gmp_address_family_static_group_destroy(
    2946             :         struct nb_cb_destroy_args *args)
    2947             : {
    2948           0 :         struct interface *ifp;
    2949           0 :         struct ipaddr source_addr;
    2950           0 :         struct ipaddr group_addr;
    2951           0 :         int result;
    2952             : 
    2953           0 :         switch (args->event) {
    2954             :         case NB_EV_VALIDATE:
    2955             :         case NB_EV_PREPARE:
    2956             :         case NB_EV_ABORT:
    2957             :                 break;
    2958           0 :         case NB_EV_APPLY:
    2959           0 :                 ifp = nb_running_get_entry(args->dnode, NULL, true);
    2960           0 :                 yang_dnode_get_ip(&source_addr, args->dnode, "./source-addr");
    2961           0 :                 yang_dnode_get_ip(&group_addr, args->dnode, "./group-addr");
    2962             : 
    2963           0 :                 result = pim_if_igmp_join_del(ifp, group_addr.ip._v4_addr,
    2964             :                                 source_addr.ip._v4_addr);
    2965             : 
    2966           0 :                 if (result) {
    2967           0 :                         char src_str[INET_ADDRSTRLEN];
    2968           0 :                         char grp_str[INET_ADDRSTRLEN];
    2969             : 
    2970           0 :                         ipaddr2str(&source_addr, src_str, sizeof(src_str));
    2971           0 :                         ipaddr2str(&group_addr, grp_str, sizeof(grp_str));
    2972             : 
    2973           0 :                         snprintf(args->errmsg, args->errmsg_len,
    2974             :                                  "%% Failure leaving IGMP group %s %s on interface %s: %d",
    2975           0 :                                  src_str, grp_str, ifp->name, result);
    2976             : 
    2977           0 :                         return NB_ERR_INCONSISTENCY;
    2978             :                 }
    2979             : 
    2980             :                 break;
    2981             :         }
    2982             : 
    2983             :         return NB_OK;
    2984             : }

Generated by: LCOV version v1.16-topotato