]> git.proxmox.com Git - mirror_frr.git/blame - pimd/pim_zebra.c
*: Make zapi route install Notifications optional
[mirror_frr.git] / pimd / pim_zebra.c
CommitLineData
12e41d03 1/*
896014f4
DL
2 * PIM for Quagga
3 * Copyright (C) 2008 Everton da Silva Marques
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for 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 */
12e41d03
DL
19
20#include <zebra.h>
21
22#include "zebra/rib.h"
23
24#include "if.h"
25#include "log.h"
26#include "prefix.h"
27#include "zclient.h"
28#include "stream.h"
29#include "network.h"
dfe43e25
DW
30#include "vty.h"
31#include "plist.h"
ba4eb1bc 32#include "lib/bfd.h"
12e41d03
DL
33
34#include "pimd.h"
35#include "pim_pim.h"
36#include "pim_zebra.h"
37#include "pim_iface.h"
38#include "pim_str.h"
39#include "pim_oil.h"
40#include "pim_rpf.h"
41#include "pim_time.h"
42#include "pim_join.h"
43#include "pim_zlookup.h"
44#include "pim_ifchannel.h"
8f5f5e91 45#include "pim_rp.h"
2560106c 46#include "pim_igmpv3.h"
982bff89 47#include "pim_jp_agg.h"
1bc98276 48#include "pim_nht.h"
15a5dafe 49#include "pim_ssm.h"
12e41d03
DL
50
51#undef PIM_DEBUG_IFADDR_DUMP
52#define PIM_DEBUG_IFADDR_DUMP
53
38f4935a
DS
54static struct zclient *zclient = NULL;
55
12e41d03 56
12e41d03
DL
57/* Router-id update message from zebra. */
58static int pim_router_id_update_zebra(int command, struct zclient *zclient,
469351b3 59 zebra_size_t length, vrf_id_t vrf_id)
12e41d03 60{
d62a17ae 61 struct prefix router_id;
12e41d03 62
d62a17ae 63 zebra_router_id_update_read(zclient->ibuf, &router_id);
12e41d03 64
d62a17ae 65 return 0;
12e41d03
DL
66}
67
68static int pim_zebra_if_add(int command, struct zclient *zclient,
469351b3 69 zebra_size_t length, vrf_id_t vrf_id)
12e41d03 70{
d62a17ae 71 struct interface *ifp;
72
73 /*
74 zebra api adds/dels interfaces using the same call
75 interface_add_read below, see comments in lib/zclient.c
76 */
77 ifp = zebra_interface_add_read(zclient->ibuf, vrf_id);
78 if (!ifp)
79 return 0;
80
81 if (PIM_DEBUG_ZEBRA) {
82 zlog_debug(
e0ae31b8
DS
83 "%s: %s index %d(%d) flags %ld metric %d mtu %d operative %d",
84 __PRETTY_FUNCTION__, ifp->name, ifp->ifindex, vrf_id,
d62a17ae 85 (long)ifp->flags, ifp->metric, ifp->mtu,
86 if_is_operative(ifp));
87 }
88
89 if (if_is_operative(ifp))
90 pim_if_addr_add_all(ifp);
91
90133de6
DS
92 /*
93 * If we are a vrf device that is up, open up the pim_socket for
94 * listening
95 * to incoming pim messages irrelevant if the user has configured us
96 * for pim or not.
97 */
98 if (pim_if_is_vrf_device(ifp)) {
99 struct pim_interface *pim_ifp;
100
101 if (!ifp->info) {
102 pim_ifp = pim_if_new(ifp, 0, 0);
103 ifp->info = pim_ifp;
104 }
105
106 pim_sock_add(ifp);
107 }
108
d62a17ae 109 return 0;
12e41d03
DL
110}
111
112static int pim_zebra_if_del(int command, struct zclient *zclient,
469351b3 113 zebra_size_t length, vrf_id_t vrf_id)
12e41d03 114{
d62a17ae 115 struct interface *ifp;
116
117 /*
118 zebra api adds/dels interfaces using the same call
119 interface_add_read below, see comments in lib/zclient.c
120
121 comments in lib/zclient.c seem to indicate that calling
122 zebra_interface_add_read is the correct call, but that
123 results in an attemted out of bounds read which causes
124 pimd to assert. Other clients use zebra_interface_state_read
125 and it appears to work just fine.
126 */
127 ifp = zebra_interface_state_read(zclient->ibuf, vrf_id);
128 if (!ifp)
129 return 0;
130
131 if (PIM_DEBUG_ZEBRA) {
132 zlog_debug(
e0ae31b8
DS
133 "%s: %s index %d(%d) flags %ld metric %d mtu %d operative %d",
134 __PRETTY_FUNCTION__, ifp->name, ifp->ifindex, vrf_id,
d62a17ae 135 (long)ifp->flags, ifp->metric, ifp->mtu,
136 if_is_operative(ifp));
137 }
138
139 if (!if_is_operative(ifp))
140 pim_if_addr_del_all(ifp);
141
142 return 0;
12e41d03
DL
143}
144
145static int pim_zebra_if_state_up(int command, struct zclient *zclient,
469351b3 146 zebra_size_t length, vrf_id_t vrf_id)
12e41d03 147{
d62a17ae 148 struct interface *ifp;
e0ae31b8 149 uint32_t table_id;
d62a17ae 150
151 /*
152 zebra api notifies interface up/down events by using the same call
153 zebra_interface_state_read below, see comments in lib/zclient.c
154 */
155 ifp = zebra_interface_state_read(zclient->ibuf, vrf_id);
156 if (!ifp)
157 return 0;
158
159 if (PIM_DEBUG_ZEBRA) {
160 zlog_debug(
e0ae31b8
DS
161 "%s: %s index %d(%d) flags %ld metric %d mtu %d operative %d",
162 __PRETTY_FUNCTION__, ifp->name, ifp->ifindex, vrf_id,
d62a17ae 163 (long)ifp->flags, ifp->metric, ifp->mtu,
164 if_is_operative(ifp));
165 }
166
167 if (if_is_operative(ifp)) {
168 /*
169 pim_if_addr_add_all() suffices for bringing up both IGMP and
170 PIM
171 */
172 pim_if_addr_add_all(ifp);
173 }
174
e0ae31b8
DS
175 /*
176 * If we have a pimreg device callback and it's for a specific
177 * table set the master appropriately
178 */
179 if (sscanf(ifp->name, "pimreg%d", &table_id) == 1) {
180 struct vrf *vrf;
a2addae8 181 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
e0ae31b8
DS
182 if ((table_id == vrf->data.l.table_id)
183 && (ifp->vrf_id != vrf->vrf_id)) {
184 struct interface *master = if_lookup_by_name(
185 vrf->name, vrf->vrf_id);
e691f179
DS
186
187 if (!master) {
188 zlog_debug("%s: Unable to find Master interface for %s",
189 __PRETTY_FUNCTION__,
190 vrf->name);
191 return 0;
192 }
e0ae31b8
DS
193 zclient_interface_set_master(zclient, master,
194 ifp);
195 }
196 }
197 }
d62a17ae 198 return 0;
12e41d03
DL
199}
200
201static int pim_zebra_if_state_down(int command, struct zclient *zclient,
469351b3 202 zebra_size_t length, vrf_id_t vrf_id)
12e41d03 203{
d62a17ae 204 struct interface *ifp;
205
206 /*
207 zebra api notifies interface up/down events by using the same call
208 zebra_interface_state_read below, see comments in lib/zclient.c
209 */
210 ifp = zebra_interface_state_read(zclient->ibuf, vrf_id);
211 if (!ifp)
212 return 0;
213
214 if (PIM_DEBUG_ZEBRA) {
215 zlog_debug(
e0ae31b8
DS
216 "%s: %s index %d(%d) flags %ld metric %d mtu %d operative %d",
217 __PRETTY_FUNCTION__, ifp->name, ifp->ifindex, vrf_id,
d62a17ae 218 (long)ifp->flags, ifp->metric, ifp->mtu,
219 if_is_operative(ifp));
220 }
221
222 if (!if_is_operative(ifp)) {
223 pim_ifchannel_delete_all(ifp);
224 /*
225 pim_if_addr_del_all() suffices for shutting down IGMP,
226 but not for shutting down PIM
227 */
228 pim_if_addr_del_all(ifp);
229
230 /*
231 pim_sock_delete() closes the socket, stops read and timer
232 threads,
233 and kills all neighbors.
234 */
235 if (ifp->info) {
236 pim_sock_delete(ifp, "link down");
237 }
238 }
239
240 if (ifp->info)
241 pim_if_del_vif(ifp);
242
243 return 0;
12e41d03
DL
244}
245
246#ifdef PIM_DEBUG_IFADDR_DUMP
247static void dump_if_address(struct interface *ifp)
248{
d62a17ae 249 struct connected *ifc;
250 struct listnode *node;
251
252 zlog_debug("%s %s: interface %s addresses:", __FILE__,
253 __PRETTY_FUNCTION__, ifp->name);
254
255 for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) {
256 struct prefix *p = ifc->address;
257
258 if (p->family != AF_INET)
259 continue;
260
261 zlog_debug("%s %s: interface %s address %s %s", __FILE__,
262 __PRETTY_FUNCTION__, ifp->name,
263 inet_ntoa(p->u.prefix4),
264 CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY)
265 ? "secondary"
266 : "primary");
267 }
12e41d03
DL
268}
269#endif
270
271static int pim_zebra_if_address_add(int command, struct zclient *zclient,
469351b3 272 zebra_size_t length, vrf_id_t vrf_id)
12e41d03 273{
d62a17ae 274 struct connected *c;
275 struct prefix *p;
276 struct pim_interface *pim_ifp;
277
278 /*
279 zebra api notifies address adds/dels events by using the same call
280 interface_add_read below, see comments in lib/zclient.c
281
282 zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_ADD, ...)
283 will add address to interface list by calling
284 connected_add_by_prefix()
285 */
286 c = zebra_interface_address_read(command, zclient->ibuf, vrf_id);
287 if (!c)
288 return 0;
289
290 pim_ifp = c->ifp->info;
291 p = c->address;
292
293 if (PIM_DEBUG_ZEBRA) {
294 char buf[BUFSIZ];
295 prefix2str(p, buf, BUFSIZ);
e0ae31b8
DS
296 zlog_debug("%s: %s(%d) connected IP address %s flags %u %s",
297 __PRETTY_FUNCTION__, c->ifp->name, vrf_id, buf,
298 c->flags, CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY)
299 ? "secondary"
300 : "primary");
d62a17ae 301
12e41d03 302#ifdef PIM_DEBUG_IFADDR_DUMP
d62a17ae 303 dump_if_address(c->ifp);
12e41d03 304#endif
d62a17ae 305 }
12e41d03 306
d62a17ae 307 if (!CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY)) {
308 /* trying to add primary address */
12e41d03 309
d62a17ae 310 struct in_addr primary_addr = pim_find_primary_addr(c->ifp);
311 if (p->family != AF_INET
312 || primary_addr.s_addr != p->u.prefix4.s_addr) {
313 if (PIM_DEBUG_ZEBRA) {
314 /* but we had a primary address already */
12e41d03 315
d62a17ae 316 char buf[BUFSIZ];
12e41d03 317
d62a17ae 318 prefix2str(p, buf, BUFSIZ);
12e41d03 319
d62a17ae 320 zlog_warn(
321 "%s: %s : forcing secondary flag on %s",
322 __PRETTY_FUNCTION__, c->ifp->name, buf);
323 }
324 SET_FLAG(c->flags, ZEBRA_IFA_SECONDARY);
325 }
326 }
12e41d03 327
d62a17ae 328 pim_if_addr_add(c);
329 if (pim_ifp)
330 pim_rp_check_on_if_add(pim_ifp);
12e41d03 331
d62a17ae 332 if (if_is_loopback(c->ifp)) {
f4e14fdb 333 struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
d62a17ae 334 struct interface *ifp;
d8424057 335
451fda4f 336 FOR_ALL_INTERFACES (vrf, ifp) {
d62a17ae 337 if (!if_is_loopback(ifp) && if_is_operative(ifp))
338 pim_if_addr_add_all(ifp);
339 }
340 }
d8424057 341
d62a17ae 342 return 0;
12e41d03
DL
343}
344
345static int pim_zebra_if_address_del(int command, struct zclient *client,
469351b3 346 zebra_size_t length, vrf_id_t vrf_id)
12e41d03 347{
d62a17ae 348 struct connected *c;
349 struct prefix *p;
fec883d9 350 struct vrf *vrf = vrf_lookup_by_id(vrf_id);
819f099b
DS
351 struct pim_instance *pim;
352
353 if (!vrf)
354 return 0;
355 pim = vrf->info;
d62a17ae 356
357 /*
358 zebra api notifies address adds/dels events by using the same call
359 interface_add_read below, see comments in lib/zclient.c
360
361 zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_DELETE, ...)
362 will remove address from interface list by calling
363 connected_delete_by_prefix()
364 */
365 c = zebra_interface_address_read(command, client->ibuf, vrf_id);
366 if (!c)
367 return 0;
368
369 p = c->address;
370 if (p->family == AF_INET) {
371 if (PIM_DEBUG_ZEBRA) {
372 char buf[BUFSIZ];
373 prefix2str(p, buf, BUFSIZ);
374 zlog_debug(
e0ae31b8
DS
375 "%s: %s(%d) disconnected IP address %s flags %u %s",
376 __PRETTY_FUNCTION__, c->ifp->name, vrf_id, buf,
d62a17ae 377 c->flags,
378 CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY)
379 ? "secondary"
380 : "primary");
6233f087 381
12e41d03 382#ifdef PIM_DEBUG_IFADDR_DUMP
d62a17ae 383 dump_if_address(c->ifp);
12e41d03 384#endif
d62a17ae 385 }
12e41d03 386
d62a17ae 387 pim_if_addr_del(c, 0);
fec883d9
DS
388 pim_rp_setup(pim);
389 pim_i_am_rp_re_evaluate(pim);
d62a17ae 390 }
6233f087 391
d62a17ae 392 connected_free(c);
393 return 0;
12e41d03
DL
394}
395
396static void scan_upstream_rpf_cache()
397{
d62a17ae 398 struct listnode *up_node;
d62a17ae 399 struct listnode *up_nextnode;
400 struct listnode *node;
401 struct pim_upstream *up;
402 struct interface *ifp;
9b29ea95
DS
403 struct vrf *vrf;
404 struct pim_instance *pim;
d62a17ae 405
a2addae8 406 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
9b29ea95
DS
407 pim = vrf->info;
408 if (!pim)
409 continue;
d62a17ae 410
9b29ea95
DS
411 for (ALL_LIST_ELEMENTS(pim->upstream_list, up_node, up_nextnode,
412 up)) {
413 enum pim_rpf_result rpf_result;
414 struct pim_rpf old;
415 struct prefix nht_p;
d62a17ae 416
9b29ea95
DS
417 nht_p.family = AF_INET;
418 nht_p.prefixlen = IPV4_MAX_BITLEN;
419 nht_p.u.prefix4.s_addr = up->upstream_addr.s_addr;
420 pim_resolve_upstream_nh(pim, &nht_p);
d62a17ae 421
9b29ea95
DS
422 old.source_nexthop.interface =
423 up->rpf.source_nexthop.interface;
424 old.source_nexthop.nbr = up->rpf.source_nexthop.nbr;
2002dcdb 425 rpf_result = pim_rpf_update(pim, up, &old, 0);
d62a17ae 426
9b29ea95
DS
427 if (rpf_result == PIM_RPF_FAILURE)
428 continue;
d62a17ae 429
9b29ea95
DS
430 if (rpf_result == PIM_RPF_CHANGED) {
431 struct pim_neighbor *nbr;
d62a17ae 432
9b29ea95
DS
433 nbr = pim_neighbor_find(
434 old.source_nexthop.interface,
435 old.rpf_addr.u.prefix4);
436 if (nbr)
437 pim_jp_agg_remove_group(
438 nbr->upstream_jp_agg, up);
d62a17ae 439
440 /*
9b29ea95
DS
441 * We have detected a case where we might need
442 * to rescan
443 * the inherited o_list so do it.
d62a17ae 444 */
9b29ea95
DS
445 if (up->channel_oil->oil_inherited_rescan) {
446 pim_upstream_inherited_olist_decide(pim,
447 up);
448 up->channel_oil->oil_inherited_rescan =
449 0;
450 }
451
452 if (up->join_state == PIM_UPSTREAM_JOINED) {
453 /*
454 * If we come up real fast we can be
455 * here
456 * where the mroute has not been
457 * installed
458 * so install it.
459 */
460 if (!up->channel_oil->installed)
461 pim_mroute_add(
462 up->channel_oil,
463 __PRETTY_FUNCTION__);
464
465 /*
466 * RFC 4601: 4.5.7. Sending (S,G)
467 * Join/Prune Messages
468 *
469 * Transitions from Joined State
470 *
471 * RPF'(S,G) changes not due to an
472 * Assert
473 *
474 * The upstream (S,G) state machine
475 * remains in Joined
476 * state. Send Join(S,G) to the new
477 * upstream neighbor, which is
478 * the new value of RPF'(S,G). Send
479 * Prune(S,G) to the old
480 * upstream neighbor, which is the old
481 * value of RPF'(S,G). Set
482 * the Join Timer (JT) to expire after
483 * t_periodic seconds.
484 */
485 pim_jp_agg_switch_interface(
486 &old, &up->rpf, up);
487
488 pim_upstream_join_timer_restart(up,
489 &old);
490 } /* up->join_state == PIM_UPSTREAM_JOINED */
491
492 /* FIXME can join_desired actually be changed by
493 pim_rpf_update()
494 returning PIM_RPF_CHANGED ? */
495 pim_upstream_update_join_desired(pim, up);
496
497 } /* PIM_RPF_CHANGED */
498
499 } /* for (qpim_upstream_list) */
500 }
d62a17ae 501
a2addae8 502 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
9b29ea95
DS
503 pim = vrf->info;
504 if (!pim)
505 continue;
d62a17ae 506
451fda4f 507 FOR_ALL_INTERFACES (pim->vrf, ifp)
9b29ea95
DS
508 if (ifp->info) {
509 struct pim_interface *pim_ifp = ifp->info;
510 struct pim_iface_upstream_switch *us;
d62a17ae 511
9b29ea95
DS
512 for (ALL_LIST_ELEMENTS_RO(
513 pim_ifp->upstream_switch_list,
514 node, us)) {
515 struct pim_rpf rpf;
516 rpf.source_nexthop.interface = ifp;
517 rpf.rpf_addr.u.prefix4 = us->address;
518 pim_joinprune_send(&rpf, us->us);
519 pim_jp_agg_clear_group(us->us);
520 }
d62a17ae 521 }
9b29ea95 522 }
12e41d03
DL
523}
524
d62a17ae 525void pim_scan_individual_oil(struct channel_oil *c_oil, int in_vif_index)
12e41d03 526{
d62a17ae 527 struct in_addr vif_source;
528 int input_iface_vif_index;
529 int old_vif_index;
530
d9c9a9ee
DS
531 if (!pim_rp_set_upstream_addr(c_oil->pim, &vif_source,
532 c_oil->oil.mfcc_origin,
d62a17ae 533 c_oil->oil.mfcc_mcastgrp))
534 return;
535
536 if (in_vif_index)
537 input_iface_vif_index = in_vif_index;
538 else {
539 struct prefix src, grp;
540
541 src.family = AF_INET;
542 src.prefixlen = IPV4_MAX_BITLEN;
543 src.u.prefix4 = vif_source;
544 grp.family = AF_INET;
545 grp.prefixlen = IPV4_MAX_BITLEN;
546 grp.u.prefix4 = c_oil->oil.mfcc_mcastgrp;
547
548 if (PIM_DEBUG_ZEBRA) {
549 char source_str[INET_ADDRSTRLEN];
550 char group_str[INET_ADDRSTRLEN];
551 pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin,
552 source_str, sizeof(source_str));
553 pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp,
554 group_str, sizeof(group_str));
555 zlog_debug(
a895ac30 556 "%s: channel_oil (%s,%s) upstream info is not present.",
d62a17ae 557 __PRETTY_FUNCTION__, source_str, group_str);
558 }
559 input_iface_vif_index = pim_ecmp_fib_lookup_if_vif_index(
25b787a2 560 c_oil->pim, vif_source, &src, &grp);
d62a17ae 561 }
562
563 if (input_iface_vif_index < 1) {
564 if (PIM_DEBUG_ZEBRA) {
565 char source_str[INET_ADDRSTRLEN];
566 char group_str[INET_ADDRSTRLEN];
567 pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin,
568 source_str, sizeof(source_str));
569 pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp,
570 group_str, sizeof(group_str));
571 zlog_debug(
572 "%s %s: could not find input interface(%d) for (S,G)=(%s,%s)",
573 __FILE__, __PRETTY_FUNCTION__,
574 c_oil->oil.mfcc_parent, source_str, group_str);
575 }
576 pim_mroute_del(c_oil, __PRETTY_FUNCTION__);
577 return;
578 }
579
580 if (input_iface_vif_index == c_oil->oil.mfcc_parent) {
581 if (!c_oil->installed)
582 pim_mroute_add(c_oil, __PRETTY_FUNCTION__);
583
584 /* RPF unchanged */
585 return;
586 }
587
588 if (PIM_DEBUG_ZEBRA) {
7cfc7bcf
DS
589 struct interface *old_iif = pim_if_find_by_vif_index(
590 c_oil->pim, c_oil->oil.mfcc_parent);
591 struct interface *new_iif = pim_if_find_by_vif_index(
592 c_oil->pim, input_iface_vif_index);
d62a17ae 593 char source_str[INET_ADDRSTRLEN];
594 char group_str[INET_ADDRSTRLEN];
595 pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str,
596 sizeof(source_str));
597 pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str,
598 sizeof(group_str));
599 zlog_debug(
600 "%s %s: (S,G)=(%s,%s) input interface changed from %s vif_index=%d to %s vif_index=%d",
601 __FILE__, __PRETTY_FUNCTION__, source_str, group_str,
97f03dde
DS
602 (old_iif) ? old_iif->name : "<old_iif?>",
603 c_oil->oil.mfcc_parent,
604 (new_iif) ? new_iif->name : "<new_iif?>",
d62a17ae 605 input_iface_vif_index);
606 }
607
608 /* new iif loops to existing oif ? */
609 if (c_oil->oil.mfcc_ttls[input_iface_vif_index]) {
7cfc7bcf
DS
610 struct interface *new_iif = pim_if_find_by_vif_index(
611 c_oil->pim, input_iface_vif_index);
d62a17ae 612
613 if (PIM_DEBUG_ZEBRA) {
614 char source_str[INET_ADDRSTRLEN];
615 char group_str[INET_ADDRSTRLEN];
616 pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin,
617 source_str, sizeof(source_str));
618 pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp,
619 group_str, sizeof(group_str));
620 zlog_debug(
621 "%s %s: (S,G)=(%s,%s) new iif loops to existing oif: %s vif_index=%d",
622 __FILE__, __PRETTY_FUNCTION__, source_str,
97f03dde
DS
623 group_str,
624 (new_iif) ? new_iif->name : "<new_iif?>",
d62a17ae 625 input_iface_vif_index);
626 }
627 }
628
629 /* update iif vif_index */
630 old_vif_index = c_oil->oil.mfcc_parent;
631 c_oil->oil.mfcc_parent = input_iface_vif_index;
632
633 /* update kernel multicast forwarding cache (MFC) */
634 if (pim_mroute_add(c_oil, __PRETTY_FUNCTION__)) {
635 if (PIM_DEBUG_MROUTE) {
636 /* just log warning */
7cfc7bcf
DS
637 struct interface *old_iif = pim_if_find_by_vif_index(
638 c_oil->pim, old_vif_index);
639 struct interface *new_iif = pim_if_find_by_vif_index(
640 c_oil->pim, input_iface_vif_index);
d62a17ae 641 char source_str[INET_ADDRSTRLEN];
642 char group_str[INET_ADDRSTRLEN];
643 pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin,
644 source_str, sizeof(source_str));
645 pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp,
646 group_str, sizeof(group_str));
647 zlog_debug(
648 "%s %s: (S,G)=(%s,%s) failure updating input interface from %s vif_index=%d to %s vif_index=%d",
649 __FILE__, __PRETTY_FUNCTION__, source_str,
650 group_str,
651 old_iif ? old_iif->name : "<old_iif?>",
652 c_oil->oil.mfcc_parent,
653 new_iif ? new_iif->name : "<new_iif?>",
654 input_iface_vif_index);
655 }
656 }
8a67a996
DS
657}
658
c68ba0d7 659void pim_scan_oil(struct pim_instance *pim_matcher)
8a67a996 660{
d62a17ae 661 struct listnode *node;
662 struct listnode *nextnode;
663 struct channel_oil *c_oil;
664 ifindex_t ifindex;
665 int vif_index = 0;
611925dc
DS
666 struct vrf *vrf;
667 struct pim_instance *pim;
d62a17ae 668
669 qpim_scan_oil_last = pim_time_monotonic_sec();
670 ++qpim_scan_oil_events;
671
a2addae8 672 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
611925dc
DS
673 pim = vrf->info;
674 if (!pim)
675 continue;
676
c68ba0d7
DS
677 if (pim_matcher && pim != pim_matcher)
678 continue;
679
611925dc
DS
680 for (ALL_LIST_ELEMENTS(pim->channel_oil_list, node, nextnode,
681 c_oil)) {
682 if (c_oil->up
683 && c_oil->up->rpf.source_nexthop.interface) {
684 ifindex = c_oil->up->rpf.source_nexthop
685 .interface->ifindex;
686 vif_index = pim_if_find_vifindex_by_ifindex(
687 pim, ifindex);
688 /* Pass Current selected NH vif index to mroute
689 * download */
690 if (vif_index)
691 pim_scan_individual_oil(c_oil,
692 vif_index);
693 } else
694 pim_scan_individual_oil(c_oil, 0);
695 }
d62a17ae 696 }
12e41d03
DL
697}
698
699static int on_rpf_cache_refresh(struct thread *t)
700{
d62a17ae 701 /* update PIM protocol state */
702 scan_upstream_rpf_cache();
12e41d03 703
d62a17ae 704 /* update kernel multicast forwarding cache (MFC) */
c68ba0d7 705 pim_scan_oil(NULL);
12e41d03 706
d62a17ae 707 qpim_rpf_cache_refresh_last = pim_time_monotonic_sec();
708 ++qpim_rpf_cache_refresh_events;
12e41d03 709
d62a17ae 710 // It is called as part of pim_neighbor_add
711 // pim_rp_setup ();
712 return 0;
12e41d03
DL
713}
714
da72c9fd 715void sched_rpf_cache_refresh(void)
12e41d03 716{
d62a17ae 717 ++qpim_rpf_cache_refresh_requests;
12e41d03 718
d62a17ae 719 pim_rpf_set_refresh_time();
e71bf8f7 720
d62a17ae 721 if (qpim_rpf_cache_refresher) {
722 /* Refresh timer is already running */
723 return;
724 }
12e41d03 725
d62a17ae 726 /* Start refresh timer */
12e41d03 727
d62a17ae 728 if (PIM_DEBUG_ZEBRA) {
729 zlog_debug("%s: triggering %ld msec timer", __PRETTY_FUNCTION__,
730 qpim_rpf_cache_refresh_delay_msec);
731 }
12e41d03 732
d62a17ae 733 thread_add_timer_msec(master, on_rpf_cache_refresh, 0,
734 qpim_rpf_cache_refresh_delay_msec,
735 &qpim_rpf_cache_refresher);
12e41d03
DL
736}
737
d62a17ae 738static void pim_zebra_connected(struct zclient *zclient)
48e8451b 739{
d62a17ae 740 /* Send the client registration */
741 bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER);
ba4eb1bc 742
0708beb1 743 zclient_send_reg_requests(zclient, pimg->vrf_id);
48e8451b 744}
8711a53d 745
eb05883f 746void pim_zebra_init(void)
12e41d03 747{
d62a17ae 748 int i;
12e41d03 749
d62a17ae 750 /* Socket for receiving updates from Zebra daemon */
e1a1880d 751 zclient = zclient_new_notify(master, &zclient_options_default);
d62a17ae 752
753 zclient->zebra_connected = pim_zebra_connected;
754 zclient->router_id_update = pim_router_id_update_zebra;
755 zclient->interface_add = pim_zebra_if_add;
756 zclient->interface_delete = pim_zebra_if_del;
757 zclient->interface_up = pim_zebra_if_state_up;
758 zclient->interface_down = pim_zebra_if_state_down;
759 zclient->interface_address_add = pim_zebra_if_address_add;
760 zclient->interface_address_delete = pim_zebra_if_address_del;
761 zclient->nexthop_update = pim_parse_nexthop_update;
762
342213ea 763 zclient_init(zclient, ZEBRA_ROUTE_PIM, 0, &pimd_privs);
d62a17ae 764 if (PIM_DEBUG_PIM_TRACE) {
765 zlog_info("zclient_init cleared redistribution request");
766 }
767
768 zassert(zclient->redist_default == ZEBRA_ROUTE_PIM);
769
770 /* Request all redistribution */
771 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
772 if (i == zclient->redist_default)
773 continue;
0708beb1 774 vrf_bitmap_set(zclient->redist[AFI_IP][i], pimg->vrf_id);
d62a17ae 775 ;
776 if (PIM_DEBUG_PIM_TRACE) {
777 zlog_debug("%s: requesting redistribution for %s (%i)",
778 __PRETTY_FUNCTION__, zebra_route_string(i),
779 i);
780 }
781 }
782
783 /* Request default information */
784 zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_ADD, zclient,
0708beb1 785 pimg->vrf_id);
d62a17ae 786
787 if (PIM_DEBUG_PIM_TRACE) {
788 zlog_info("%s: requesting default information redistribution",
789 __PRETTY_FUNCTION__);
790
791 zlog_notice("%s: zclient update socket initialized",
792 __PRETTY_FUNCTION__);
793 }
794
795 zclient_lookup_new();
12e41d03
DL
796}
797
6f932b0c
DS
798void igmp_anysource_forward_start(struct pim_instance *pim,
799 struct igmp_group *group)
12e41d03 800{
d62a17ae 801 struct igmp_source *source;
802 struct in_addr src_addr = {.s_addr = 0};
803 /* Any source (*,G) is forwarded only if mode is EXCLUDE {empty} */
804 zassert(group->group_filtermode_isexcl);
805 zassert(listcount(group->group_source_list) < 1);
806
807 source = source_new(group, src_addr);
808 if (!source) {
809 zlog_warn("%s: Failure to create * source",
810 __PRETTY_FUNCTION__);
811 return;
812 }
813
6f932b0c 814 igmp_source_forward_start(pim, source);
12e41d03
DL
815}
816
817void igmp_anysource_forward_stop(struct igmp_group *group)
818{
d62a17ae 819 struct igmp_source *source;
820 struct in_addr star = {.s_addr = 0};
12e41d03 821
d62a17ae 822 source = igmp_find_source_by_addr(group, star);
823 if (source)
824 igmp_source_forward_stop(source);
12e41d03
DL
825}
826
6f439a70
DS
827static void igmp_source_forward_reevaluate_one(struct pim_instance *pim,
828 struct igmp_source *source)
15a5dafe 829{
d62a17ae 830 struct prefix_sg sg;
831 struct igmp_group *group = source->source_group;
832 struct pim_ifchannel *ch;
833
834 if ((source->source_addr.s_addr != INADDR_ANY)
835 || !IGMP_SOURCE_TEST_FORWARDING(source->source_flags))
836 return;
837
838 memset(&sg, 0, sizeof(struct prefix_sg));
839 sg.src = source->source_addr;
840 sg.grp = group->group_addr;
841
842 ch = pim_ifchannel_find(group->group_igmp_sock->interface, &sg);
6f439a70 843 if (pim_is_grp_ssm(pim, group->group_addr)) {
d62a17ae 844 /* If SSM group withdraw local membership */
845 if (ch
846 && (ch->local_ifmembership == PIM_IFMEMBERSHIP_INCLUDE)) {
847 if (PIM_DEBUG_PIM_EVENTS)
848 zlog_debug(
849 "local membership del for %s as G is now SSM",
850 pim_str_sg_dump(&sg));
851 pim_ifchannel_local_membership_del(
852 group->group_igmp_sock->interface, &sg);
853 }
854 } else {
855 /* If ASM group add local membership */
856 if (!ch
857 || (ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO)) {
858 if (PIM_DEBUG_PIM_EVENTS)
859 zlog_debug(
860 "local membership add for %s as G is now ASM",
861 pim_str_sg_dump(&sg));
862 pim_ifchannel_local_membership_add(
863 group->group_igmp_sock->interface, &sg);
864 }
865 }
15a5dafe 866}
867
d62a17ae 868void igmp_source_forward_reevaluate_all(void)
15a5dafe 869{
d62a17ae 870 struct interface *ifp;
6f932b0c
DS
871 struct vrf *vrf;
872 struct pim_instance *pim;
d62a17ae 873
a2addae8 874 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
6f932b0c
DS
875 pim = vrf->info;
876 if (!pim)
d62a17ae 877 continue;
878
451fda4f 879 FOR_ALL_INTERFACES (pim->vrf, ifp) {
6f932b0c
DS
880 struct pim_interface *pim_ifp = ifp->info;
881 struct listnode *sock_node;
882 struct igmp_sock *igmp;
d62a17ae 883
6f932b0c
DS
884 if (!pim_ifp)
885 continue;
d62a17ae 886
6f932b0c
DS
887 /* scan igmp sockets */
888 for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list,
889 sock_node, igmp)) {
890 struct listnode *grpnode;
891 struct igmp_group *grp;
892
893 /* scan igmp groups */
894 for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list,
895 grpnode, grp)) {
896 struct listnode *srcnode;
897 struct igmp_source *src;
898
899 /* scan group sources */
900 for (ALL_LIST_ELEMENTS_RO(
901 grp->group_source_list,
902 srcnode, src)) {
903 igmp_source_forward_reevaluate_one(
6f439a70 904 pim, src);
6f932b0c
DS
905 } /* scan group sources */
906 } /* scan igmp groups */
907 } /* scan igmp sockets */
908 } /* scan interfaces */
909 }
15a5dafe 910}
911
6f932b0c
DS
912void igmp_source_forward_start(struct pim_instance *pim,
913 struct igmp_source *source)
12e41d03 914{
d62a17ae 915 struct igmp_group *group;
916 struct prefix_sg sg;
917 int result;
918 int input_iface_vif_index = 0;
919
920 memset(&sg, 0, sizeof(struct prefix_sg));
921 sg.src = source->source_addr;
922 sg.grp = source->source_group->group_addr;
923
924 if (PIM_DEBUG_IGMP_TRACE) {
925 zlog_debug(
926 "%s: (S,G)=%s igmp_sock=%d oif=%s fwd=%d",
927 __PRETTY_FUNCTION__, pim_str_sg_dump(&sg),
928 source->source_group->group_igmp_sock->fd,
929 source->source_group->group_igmp_sock->interface->name,
930 IGMP_SOURCE_TEST_FORWARDING(source->source_flags));
931 }
932
933 /* Prevent IGMP interface from installing multicast route multiple
934 times */
935 if (IGMP_SOURCE_TEST_FORWARDING(source->source_flags)) {
936 return;
8711a53d 937 }
d62a17ae 938
939 group = source->source_group;
940
941 if (!source->source_channel_oil) {
942 struct in_addr vif_source;
943 struct pim_interface *pim_oif;
944 struct prefix nht_p, src, grp;
d62a17ae 945 struct pim_nexthop_cache out_pnc;
946 struct pim_nexthop nexthop;
947 struct pim_upstream *up = NULL;
948
6f932b0c 949 if (!pim_rp_set_upstream_addr(pim, &vif_source,
d9c9a9ee 950 source->source_addr, sg.grp))
d62a17ae 951 return;
952
953 /* Register addr with Zebra NHT */
954 nht_p.family = AF_INET;
955 nht_p.prefixlen = IPV4_MAX_BITLEN;
956 nht_p.u.prefix4 = vif_source;
957 memset(&out_pnc, 0, sizeof(struct pim_nexthop_cache));
958
959 src.family = AF_INET;
960 src.prefixlen = IPV4_MAX_BITLEN;
961 src.u.prefix4 = vif_source; // RP or Src address
962 grp.family = AF_INET;
963 grp.prefixlen = IPV4_MAX_BITLEN;
964 grp.u.prefix4 = sg.grp;
965
6f932b0c 966 if (pim_find_or_track_nexthop(pim, &nht_p, NULL, NULL,
25bdac42 967 &out_pnc)) {
d62a17ae 968 if (out_pnc.nexthop_num) {
6f932b0c 969 up = pim_upstream_find(pim, &sg);
cb9c7c50 970 memset(&nexthop, 0, sizeof(nexthop));
d62a17ae 971 if (up)
972 memcpy(&nexthop,
973 &up->rpf.source_nexthop,
974 sizeof(struct pim_nexthop));
6f932b0c
DS
975 pim_ecmp_nexthop_search(pim, &out_pnc, &nexthop,
976 &src, &grp, 0);
d62a17ae 977 if (nexthop.interface)
978 input_iface_vif_index =
979 pim_if_find_vifindex_by_ifindex(
6f932b0c 980 pim,
d62a17ae 981 nexthop.interface->ifindex);
982 } else {
983 if (PIM_DEBUG_ZEBRA) {
984 char buf1[INET_ADDRSTRLEN];
985 char buf2[INET_ADDRSTRLEN];
986 pim_inet4_dump("<source?>",
987 nht_p.u.prefix4, buf1,
988 sizeof(buf1));
989 pim_inet4_dump("<source?>",
990 grp.u.prefix4, buf2,
991 sizeof(buf2));
992 zlog_debug(
993 "%s: NHT Nexthop not found for addr %s grp %s",
994 __PRETTY_FUNCTION__, buf1,
995 buf2);
996 }
997 }
998 } else
999 input_iface_vif_index =
25b787a2 1000 pim_ecmp_fib_lookup_if_vif_index(
6f932b0c 1001 pim, vif_source, &src, &grp);
d62a17ae 1002
1003 if (PIM_DEBUG_ZEBRA) {
1004 char buf2[INET_ADDRSTRLEN];
1005 pim_inet4_dump("<source?>", vif_source, buf2,
1006 sizeof(buf2));
1007 zlog_debug("%s: NHT %s vif_source %s vif_index:%d ",
1008 __PRETTY_FUNCTION__, pim_str_sg_dump(&sg),
1009 buf2, input_iface_vif_index);
1010 }
1011
1012 if (input_iface_vif_index < 1) {
1013 if (PIM_DEBUG_IGMP_TRACE) {
1014 char source_str[INET_ADDRSTRLEN];
1015 pim_inet4_dump("<source?>", source->source_addr,
1016 source_str, sizeof(source_str));
1017 zlog_debug(
1018 "%s %s: could not find input interface for source %s",
1019 __FILE__, __PRETTY_FUNCTION__,
1020 source_str);
1021 }
1022 return;
1023 }
1024
1025 /*
1026 Protect IGMP against adding looped MFC entries created by both
1027 source and receiver attached to the same interface. See TODO
1028 T22.
1029 */
1030 pim_oif =
1031 source->source_group->group_igmp_sock->interface->info;
1032 if (!pim_oif) {
1033 if (PIM_DEBUG_IGMP_TRACE) {
1034 zlog_debug(
1035 "%s: multicast not enabled on oif=%s ?",
1036 __PRETTY_FUNCTION__,
1037 source->source_group->group_igmp_sock
1038 ->interface->name);
1039 }
1040 return;
1041 }
1042
1043 if (input_iface_vif_index == pim_oif->mroute_vif_index) {
1044 /* ignore request for looped MFC entry */
1045 if (PIM_DEBUG_IGMP_TRACE) {
1046 zlog_debug(
1047 "%s: ignoring request for looped MFC entry (S,G)=%s: igmp_sock=%d oif=%s vif_index=%d",
1048 __PRETTY_FUNCTION__,
1049 pim_str_sg_dump(&sg),
1050 source->source_group->group_igmp_sock
1051 ->fd,
1052 source->source_group->group_igmp_sock
1053 ->interface->name,
1054 input_iface_vif_index);
1055 }
1056 return;
1057 }
1058
1059 source->source_channel_oil =
6f932b0c 1060 pim_channel_oil_add(pim, &sg, input_iface_vif_index);
d62a17ae 1061 if (!source->source_channel_oil) {
1062 if (PIM_DEBUG_IGMP_TRACE) {
1063 zlog_debug(
1064 "%s %s: could not create OIL for channel (S,G)=%s",
1065 __FILE__, __PRETTY_FUNCTION__,
1066 pim_str_sg_dump(&sg));
1067 }
1068 return;
1069 }
8711a53d 1070 }
d62a17ae 1071
1072 result = pim_channel_add_oif(source->source_channel_oil,
1073 group->group_igmp_sock->interface,
1074 PIM_OIF_FLAG_PROTO_IGMP);
1075 if (result) {
1076 if (PIM_DEBUG_MROUTE) {
1077 zlog_warn("%s: add_oif() failed with return=%d",
1078 __func__, result);
1079 }
1080 return;
8711a53d 1081 }
d62a17ae 1082
1083 /*
1084 Feed IGMPv3-gathered local membership information into PIM
1085 per-interface (S,G) state.
1086 */
1087 if (!pim_ifchannel_local_membership_add(
1088 group->group_igmp_sock->interface, &sg)) {
1089 if (PIM_DEBUG_MROUTE)
1090 zlog_warn("%s: Failure to add local membership for %s",
1091 __PRETTY_FUNCTION__, pim_str_sg_dump(&sg));
1092 return;
1093 }
1094
1095 IGMP_SOURCE_DO_FORWARDING(source->source_flags);
12e41d03
DL
1096}
1097
1098/*
1099 igmp_source_forward_stop: stop fowarding, but keep the source
1100 igmp_source_delete: stop fowarding, and delete the source
1101 */
1102void igmp_source_forward_stop(struct igmp_source *source)
1103{
d62a17ae 1104 struct igmp_group *group;
1105 struct prefix_sg sg;
1106 int result;
1107
1108 memset(&sg, 0, sizeof(struct prefix_sg));
1109 sg.src = source->source_addr;
1110 sg.grp = source->source_group->group_addr;
1111
1112 if (PIM_DEBUG_IGMP_TRACE) {
1113 zlog_debug(
1114 "%s: (S,G)=%s igmp_sock=%d oif=%s fwd=%d",
1115 __PRETTY_FUNCTION__, pim_str_sg_dump(&sg),
1116 source->source_group->group_igmp_sock->fd,
1117 source->source_group->group_igmp_sock->interface->name,
1118 IGMP_SOURCE_TEST_FORWARDING(source->source_flags));
1119 }
1120
1121 /* Prevent IGMP interface from removing multicast route multiple
1122 times */
1123 if (!IGMP_SOURCE_TEST_FORWARDING(source->source_flags)) {
1124 return;
1125 }
1126
1127 group = source->source_group;
1128
1129 /*
1130 It appears that in certain circumstances that
1131 igmp_source_forward_stop is called when IGMP forwarding
1132 was not enabled in oif_flags for this outgoing interface.
1133 Possibly because of multiple calls. When that happens, we
1134 enter the below if statement and this function returns early
1135 which in turn triggers the calling function to assert.
1136 Making the call to pim_channel_del_oif and ignoring the return code
1137 fixes the issue without ill effect, similar to
1138 pim_forward_stop below.
1139 */
1140 result = pim_channel_del_oif(source->source_channel_oil,
1141 group->group_igmp_sock->interface,
1142 PIM_OIF_FLAG_PROTO_IGMP);
1143 if (result) {
1144 if (PIM_DEBUG_IGMP_TRACE)
1145 zlog_debug(
1146 "%s: pim_channel_del_oif() failed with return=%d",
1147 __func__, result);
1148 return;
1149 }
1150
1151 /*
1152 Feed IGMPv3-gathered local membership information into PIM
1153 per-interface (S,G) state.
1154 */
1155 pim_ifchannel_local_membership_del(group->group_igmp_sock->interface,
1156 &sg);
1157
1158 IGMP_SOURCE_DONT_FORWARDING(source->source_flags);
12e41d03
DL
1159}
1160
1161void pim_forward_start(struct pim_ifchannel *ch)
1162{
d62a17ae 1163 struct pim_upstream *up = ch->upstream;
1164 uint32_t mask = PIM_OIF_FLAG_PROTO_PIM;
1165 int input_iface_vif_index = 0;
6f932b0c
DS
1166 struct pim_instance *pim;
1167 struct pim_interface *pim_ifp;
1168
1169 pim_ifp = ch->interface->info;
1170 pim = pim_ifp->pim;
d62a17ae 1171
1172 if (PIM_DEBUG_PIM_TRACE) {
1173 char source_str[INET_ADDRSTRLEN];
1174 char group_str[INET_ADDRSTRLEN];
1175 char upstream_str[INET_ADDRSTRLEN];
1176
1177 pim_inet4_dump("<source?>", ch->sg.src, source_str,
1178 sizeof(source_str));
1179 pim_inet4_dump("<group?>", ch->sg.grp, group_str,
1180 sizeof(group_str));
1181 pim_inet4_dump("<upstream?>", up->upstream_addr, upstream_str,
1182 sizeof(upstream_str));
1183 zlog_debug("%s: (S,G)=(%s,%s) oif=%s (%s)", __PRETTY_FUNCTION__,
1184 source_str, group_str, ch->interface->name,
1185 upstream_str);
1186 }
1187
1188 /* Resolve IIF for upstream as mroute_del sets mfcc_parent to MAXVIFS,
1189 as part of mroute_del called by pim_forward_stop.
1190 */
1191 if (!up->channel_oil
1192 || (up->channel_oil
1193 && up->channel_oil->oil.mfcc_parent >= MAXVIFS)) {
1194 struct prefix nht_p, src, grp;
d62a17ae 1195 struct pim_nexthop_cache out_pnc;
1196
1197 /* Register addr with Zebra NHT */
1198 nht_p.family = AF_INET;
1199 nht_p.prefixlen = IPV4_MAX_BITLEN;
1200 nht_p.u.prefix4.s_addr = up->upstream_addr.s_addr;
1201 grp.family = AF_INET;
1202 grp.prefixlen = IPV4_MAX_BITLEN;
1203 grp.u.prefix4 = up->sg.grp;
1204 memset(&out_pnc, 0, sizeof(struct pim_nexthop_cache));
1205
6f932b0c 1206 if (pim_find_or_track_nexthop(pim, &nht_p, NULL, NULL,
25bdac42 1207 &out_pnc)) {
d62a17ae 1208 if (out_pnc.nexthop_num) {
1209 src.family = AF_INET;
1210 src.prefixlen = IPV4_MAX_BITLEN;
1211 src.u.prefix4 =
1212 up->upstream_addr; // RP or Src address
1213 grp.family = AF_INET;
1214 grp.prefixlen = IPV4_MAX_BITLEN;
1215 grp.u.prefix4 = up->sg.grp;
1216 // Compute PIM RPF using Cached nexthop
1217 if (pim_ecmp_nexthop_search(
6f932b0c 1218 pim, &out_pnc,
25b787a2
DS
1219 &up->rpf.source_nexthop, &src, &grp,
1220 0))
d62a17ae 1221 input_iface_vif_index =
1222 pim_if_find_vifindex_by_ifindex(
6f932b0c 1223 pim,
d62a17ae 1224 up->rpf.source_nexthop
1225 .interface->ifindex);
1226 else {
1227 if (PIM_DEBUG_TRACE)
1228 zlog_debug(
1229 "%s: Nexthop selection failed for %s ",
1230 __PRETTY_FUNCTION__,
1231 up->sg_str);
1232 }
1233 } else {
1234 if (PIM_DEBUG_ZEBRA) {
1235 char buf1[INET_ADDRSTRLEN];
1236 char buf2[INET_ADDRSTRLEN];
1237 pim_inet4_dump("<source?>",
1238 nht_p.u.prefix4, buf1,
1239 sizeof(buf1));
1240 pim_inet4_dump("<source?>",
1241 grp.u.prefix4, buf2,
1242 sizeof(buf2));
1243 zlog_debug(
1244 "%s: NHT pnc is NULL for addr %s grp %s",
1245 __PRETTY_FUNCTION__, buf1,
1246 buf2);
1247 }
1248 }
1249 } else
1250 input_iface_vif_index =
1251 pim_ecmp_fib_lookup_if_vif_index(
6f932b0c 1252 pim, up->upstream_addr, &src, &grp);
d62a17ae 1253
1254 if (input_iface_vif_index < 1) {
1255 if (PIM_DEBUG_PIM_TRACE) {
1256 char source_str[INET_ADDRSTRLEN];
1257 pim_inet4_dump("<source?>", up->sg.src,
1258 source_str, sizeof(source_str));
1259 zlog_debug(
1260 "%s %s: could not find input interface for source %s",
1261 __FILE__, __PRETTY_FUNCTION__,
1262 source_str);
1263 }
1264 return;
1265 }
1266 if (PIM_DEBUG_TRACE) {
7cfc7bcf 1267 struct interface *in_intf = pim_if_find_by_vif_index(
6f932b0c 1268 pim, input_iface_vif_index);
d62a17ae 1269 zlog_debug(
1270 "%s: Update channel_oil IIF %s VIFI %d entry %s ",
1271 __PRETTY_FUNCTION__,
1272 in_intf ? in_intf->name : "NIL",
1273 input_iface_vif_index, up->sg_str);
1274 }
6f932b0c 1275 up->channel_oil = pim_channel_oil_add(pim, &up->sg,
611925dc 1276 input_iface_vif_index);
d62a17ae 1277 if (!up->channel_oil) {
1278 if (PIM_DEBUG_PIM_TRACE)
1279 zlog_debug(
1280 "%s %s: could not create OIL for channel (S,G)=%s",
1281 __FILE__, __PRETTY_FUNCTION__,
1282 up->sg_str);
1283 return;
1284 }
1285 }
1286
1287 if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP)
1288 mask = PIM_OIF_FLAG_PROTO_IGMP;
1289
1290 pim_channel_add_oif(up->channel_oil, ch->interface, mask);
12e41d03
DL
1291}
1292
aabb9a2f 1293void pim_forward_stop(struct pim_ifchannel *ch, bool install_it)
12e41d03 1294{
d62a17ae 1295 struct pim_upstream *up = ch->upstream;
12e41d03 1296
d62a17ae 1297 if (PIM_DEBUG_PIM_TRACE) {
aabb9a2f
DS
1298 zlog_debug("%s: (S,G)=%s oif=%s install_it: %d installed: %d",
1299 __PRETTY_FUNCTION__, ch->sg_str, ch->interface->name,
1300 install_it, up->channel_oil->installed);
d62a17ae 1301 }
12e41d03 1302
d62a17ae 1303 pim_channel_del_oif(up->channel_oil, ch->interface,
1304 PIM_OIF_FLAG_PROTO_PIM);
aabb9a2f
DS
1305
1306 if (install_it && !up->channel_oil->installed)
1307 pim_mroute_add(up->channel_oil, __PRETTY_FUNCTION__);
12e41d03 1308}
8799b66b 1309
d62a17ae 1310void pim_zebra_zclient_update(struct vty *vty)
8799b66b 1311{
d62a17ae 1312 vty_out(vty, "Zclient update socket: ");
1313
1314 if (zclient) {
1315 vty_out(vty, "%d failures=%d\n", zclient->sock, zclient->fail);
1316 } else {
1317 vty_out(vty, "<null zclient>\n");
1318 }
8799b66b 1319}
1bc98276 1320
d62a17ae 1321struct zclient *pim_zebra_zclient_get(void)
1bc98276 1322{
d62a17ae 1323 if (zclient)
1324 return zclient;
1325 else
1326 return NULL;
1bc98276 1327}