Coverage Report

Created: 2025-08-26 06:20

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