]> git.proxmox.com Git - mirror_frr.git/blame - pimd/pim_zebra.c
pimd: Move some data tracking variables per VRF
[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(
87ad28f4 83 "%s: %s index %d(%u) flags %ld metric %d mtu %d operative %d",
e0ae31b8 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(
87ad28f4 133 "%s: %s index %d(%u) flags %ld metric %d mtu %d operative %d",
e0ae31b8 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(
87ad28f4 161 "%s: %s index %d(%u) flags %ld metric %d mtu %d operative %d",
e0ae31b8 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) {
996c9314
LB
188 zlog_debug(
189 "%s: Unable to find Master interface for %s",
190 __PRETTY_FUNCTION__, vrf->name);
e691f179
DS
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(
87ad28f4 216 "%s: %s index %d(%u) flags %ld metric %d mtu %d operative %d",
e0ae31b8 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);
87ad28f4 296 zlog_debug("%s: %s(%u) connected IP address %s flags %u %s",
e0ae31b8 297 __PRETTY_FUNCTION__, c->ifp->name, vrf_id, buf,
996c9314
LB
298 c->flags,
299 CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY)
300 ? "secondary"
301 : "primary");
d62a17ae 302
12e41d03 303#ifdef PIM_DEBUG_IFADDR_DUMP
d62a17ae 304 dump_if_address(c->ifp);
12e41d03 305#endif
d62a17ae 306 }
12e41d03 307
d62a17ae 308 if (!CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY)) {
309 /* trying to add primary address */
12e41d03 310
d62a17ae 311 struct in_addr primary_addr = pim_find_primary_addr(c->ifp);
312 if (p->family != AF_INET
313 || primary_addr.s_addr != p->u.prefix4.s_addr) {
314 if (PIM_DEBUG_ZEBRA) {
315 /* but we had a primary address already */
12e41d03 316
d62a17ae 317 char buf[BUFSIZ];
12e41d03 318
d62a17ae 319 prefix2str(p, buf, BUFSIZ);
12e41d03 320
d62a17ae 321 zlog_warn(
322 "%s: %s : forcing secondary flag on %s",
323 __PRETTY_FUNCTION__, c->ifp->name, buf);
324 }
325 SET_FLAG(c->flags, ZEBRA_IFA_SECONDARY);
326 }
327 }
12e41d03 328
d62a17ae 329 pim_if_addr_add(c);
330 if (pim_ifp)
331 pim_rp_check_on_if_add(pim_ifp);
12e41d03 332
d62a17ae 333 if (if_is_loopback(c->ifp)) {
f4e14fdb 334 struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
d62a17ae 335 struct interface *ifp;
d8424057 336
451fda4f 337 FOR_ALL_INTERFACES (vrf, ifp) {
d62a17ae 338 if (!if_is_loopback(ifp) && if_is_operative(ifp))
339 pim_if_addr_add_all(ifp);
340 }
341 }
d8424057 342
d62a17ae 343 return 0;
12e41d03
DL
344}
345
346static int pim_zebra_if_address_del(int command, struct zclient *client,
469351b3 347 zebra_size_t length, vrf_id_t vrf_id)
12e41d03 348{
d62a17ae 349 struct connected *c;
350 struct prefix *p;
fec883d9 351 struct vrf *vrf = vrf_lookup_by_id(vrf_id);
819f099b
DS
352 struct pim_instance *pim;
353
354 if (!vrf)
355 return 0;
356 pim = vrf->info;
d62a17ae 357
358 /*
359 zebra api notifies address adds/dels events by using the same call
360 interface_add_read below, see comments in lib/zclient.c
361
362 zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_DELETE, ...)
363 will remove address from interface list by calling
364 connected_delete_by_prefix()
365 */
366 c = zebra_interface_address_read(command, client->ibuf, vrf_id);
367 if (!c)
368 return 0;
369
370 p = c->address;
371 if (p->family == AF_INET) {
372 if (PIM_DEBUG_ZEBRA) {
373 char buf[BUFSIZ];
374 prefix2str(p, buf, BUFSIZ);
375 zlog_debug(
87ad28f4 376 "%s: %s(%u) disconnected IP address %s flags %u %s",
e0ae31b8 377 __PRETTY_FUNCTION__, c->ifp->name, vrf_id, buf,
d62a17ae 378 c->flags,
379 CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY)
380 ? "secondary"
381 : "primary");
6233f087 382
12e41d03 383#ifdef PIM_DEBUG_IFADDR_DUMP
d62a17ae 384 dump_if_address(c->ifp);
12e41d03 385#endif
d62a17ae 386 }
12e41d03 387
d62a17ae 388 pim_if_addr_del(c, 0);
fec883d9
DS
389 pim_rp_setup(pim);
390 pim_i_am_rp_re_evaluate(pim);
d62a17ae 391 }
6233f087 392
d62a17ae 393 connected_free(c);
394 return 0;
12e41d03
DL
395}
396
da11e325 397static void scan_upstream_rpf_cache(struct pim_instance *pim)
12e41d03 398{
d62a17ae 399 struct listnode *up_node;
d62a17ae 400 struct listnode *up_nextnode;
401 struct listnode *node;
402 struct pim_upstream *up;
403 struct interface *ifp;
d62a17ae 404
da11e325
DS
405 for (ALL_LIST_ELEMENTS(pim->upstream_list, up_node, up_nextnode, up)) {
406 enum pim_rpf_result rpf_result;
407 struct pim_rpf old;
408 struct prefix nht_p;
d62a17ae 409
da11e325
DS
410 nht_p.family = AF_INET;
411 nht_p.prefixlen = IPV4_MAX_BITLEN;
412 nht_p.u.prefix4.s_addr = up->upstream_addr.s_addr;
413 pim_resolve_upstream_nh(pim, &nht_p);
d62a17ae 414
da11e325
DS
415 old.source_nexthop.interface = up->rpf.source_nexthop.interface;
416 old.source_nexthop.nbr = up->rpf.source_nexthop.nbr;
417 rpf_result = pim_rpf_update(pim, up, &old, 0);
d62a17ae 418
da11e325
DS
419 if (rpf_result == PIM_RPF_FAILURE)
420 continue;
d62a17ae 421
da11e325
DS
422 if (rpf_result == PIM_RPF_CHANGED) {
423 struct pim_neighbor *nbr;
424
425 nbr = pim_neighbor_find(old.source_nexthop.interface,
426 old.rpf_addr.u.prefix4);
427 if (nbr)
428 pim_jp_agg_remove_group(nbr->upstream_jp_agg,
429 up);
430
431 /*
432 * We have detected a case where we might need
433 * to rescan
434 * the inherited o_list so do it.
435 */
436 if (up->channel_oil->oil_inherited_rescan) {
437 pim_upstream_inherited_olist_decide(pim, up);
438 up->channel_oil->oil_inherited_rescan = 0;
439 }
d62a17ae 440
da11e325
DS
441 if (up->join_state == PIM_UPSTREAM_JOINED) {
442 /*
443 * If we come up real fast we can be here
444 * where the mroute has not been installed
445 * so install it.
446 */
447 if (!up->channel_oil->installed)
448 pim_mroute_add(up->channel_oil,
449 __PRETTY_FUNCTION__);
d62a17ae 450
451 /*
da11e325
DS
452 * RFC 4601: 4.5.7. Sending (S,G)
453 * Join/Prune Messages
454 *
455 * Transitions from Joined State
456 *
457 * RPF'(S,G) changes not due to an Assert
458 *
459 * The upstream (S,G) state machine remains
460 * in Joined state. Send Join(S,G) to the new
461 * upstream neighbor, which is the new value
462 * of RPF'(S,G). Send Prune(S,G) to the old
463 * upstream neighbor, which is the old value
464 * of RPF'(S,G). Set the Join Timer (JT) to
465 * expire after t_periodic seconds.
d62a17ae 466 */
da11e325 467 pim_jp_agg_switch_interface(&old, &up->rpf, up);
9b29ea95 468
da11e325
DS
469 pim_upstream_join_timer_restart(up, &old);
470 } /* up->join_state == PIM_UPSTREAM_JOINED */
d62a17ae 471
da11e325
DS
472 /* FIXME can join_desired actually be changed by
473 pim_rpf_update()
474 returning PIM_RPF_CHANGED ? */
475 pim_upstream_update_join_desired(pim, up);
d62a17ae 476
da11e325
DS
477 } /* PIM_RPF_CHANGED */
478
479 } /* for (qpim_upstream_list) */
480
481 FOR_ALL_INTERFACES (pim->vrf, ifp)
482 if (ifp->info) {
483 struct pim_interface *pim_ifp = ifp->info;
484 struct pim_iface_upstream_switch *us;
485
486 for (ALL_LIST_ELEMENTS_RO(pim_ifp->upstream_switch_list,
487 node, us)) {
488 struct pim_rpf rpf;
489
490 rpf.source_nexthop.interface = ifp;
491 rpf.rpf_addr.u.prefix4 = us->address;
492 pim_joinprune_send(&rpf, us->us);
493 pim_jp_agg_clear_group(us->us);
d62a17ae 494 }
da11e325 495 }
12e41d03
DL
496}
497
d62a17ae 498void pim_scan_individual_oil(struct channel_oil *c_oil, int in_vif_index)
12e41d03 499{
d62a17ae 500 struct in_addr vif_source;
501 int input_iface_vif_index;
502 int old_vif_index;
503
d9c9a9ee
DS
504 if (!pim_rp_set_upstream_addr(c_oil->pim, &vif_source,
505 c_oil->oil.mfcc_origin,
d62a17ae 506 c_oil->oil.mfcc_mcastgrp))
507 return;
508
509 if (in_vif_index)
510 input_iface_vif_index = in_vif_index;
511 else {
512 struct prefix src, grp;
513
514 src.family = AF_INET;
515 src.prefixlen = IPV4_MAX_BITLEN;
516 src.u.prefix4 = vif_source;
517 grp.family = AF_INET;
518 grp.prefixlen = IPV4_MAX_BITLEN;
519 grp.u.prefix4 = c_oil->oil.mfcc_mcastgrp;
520
521 if (PIM_DEBUG_ZEBRA) {
522 char source_str[INET_ADDRSTRLEN];
523 char group_str[INET_ADDRSTRLEN];
524 pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin,
525 source_str, sizeof(source_str));
526 pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp,
527 group_str, sizeof(group_str));
528 zlog_debug(
a895ac30 529 "%s: channel_oil (%s,%s) upstream info is not present.",
d62a17ae 530 __PRETTY_FUNCTION__, source_str, group_str);
531 }
532 input_iface_vif_index = pim_ecmp_fib_lookup_if_vif_index(
25b787a2 533 c_oil->pim, vif_source, &src, &grp);
d62a17ae 534 }
535
536 if (input_iface_vif_index < 1) {
537 if (PIM_DEBUG_ZEBRA) {
538 char source_str[INET_ADDRSTRLEN];
539 char group_str[INET_ADDRSTRLEN];
540 pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin,
541 source_str, sizeof(source_str));
542 pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp,
543 group_str, sizeof(group_str));
544 zlog_debug(
545 "%s %s: could not find input interface(%d) for (S,G)=(%s,%s)",
546 __FILE__, __PRETTY_FUNCTION__,
547 c_oil->oil.mfcc_parent, source_str, group_str);
548 }
549 pim_mroute_del(c_oil, __PRETTY_FUNCTION__);
550 return;
551 }
552
553 if (input_iface_vif_index == c_oil->oil.mfcc_parent) {
554 if (!c_oil->installed)
555 pim_mroute_add(c_oil, __PRETTY_FUNCTION__);
556
557 /* RPF unchanged */
558 return;
559 }
560
561 if (PIM_DEBUG_ZEBRA) {
7cfc7bcf
DS
562 struct interface *old_iif = pim_if_find_by_vif_index(
563 c_oil->pim, c_oil->oil.mfcc_parent);
564 struct interface *new_iif = pim_if_find_by_vif_index(
565 c_oil->pim, input_iface_vif_index);
d62a17ae 566 char source_str[INET_ADDRSTRLEN];
567 char group_str[INET_ADDRSTRLEN];
568 pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str,
569 sizeof(source_str));
570 pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str,
571 sizeof(group_str));
572 zlog_debug(
573 "%s %s: (S,G)=(%s,%s) input interface changed from %s vif_index=%d to %s vif_index=%d",
574 __FILE__, __PRETTY_FUNCTION__, source_str, group_str,
97f03dde
DS
575 (old_iif) ? old_iif->name : "<old_iif?>",
576 c_oil->oil.mfcc_parent,
577 (new_iif) ? new_iif->name : "<new_iif?>",
d62a17ae 578 input_iface_vif_index);
579 }
580
581 /* new iif loops to existing oif ? */
582 if (c_oil->oil.mfcc_ttls[input_iface_vif_index]) {
7cfc7bcf
DS
583 struct interface *new_iif = pim_if_find_by_vif_index(
584 c_oil->pim, input_iface_vif_index);
d62a17ae 585
586 if (PIM_DEBUG_ZEBRA) {
587 char source_str[INET_ADDRSTRLEN];
588 char group_str[INET_ADDRSTRLEN];
589 pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin,
590 source_str, sizeof(source_str));
591 pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp,
592 group_str, sizeof(group_str));
593 zlog_debug(
594 "%s %s: (S,G)=(%s,%s) new iif loops to existing oif: %s vif_index=%d",
595 __FILE__, __PRETTY_FUNCTION__, source_str,
97f03dde
DS
596 group_str,
597 (new_iif) ? new_iif->name : "<new_iif?>",
d62a17ae 598 input_iface_vif_index);
599 }
600 }
601
602 /* update iif vif_index */
603 old_vif_index = c_oil->oil.mfcc_parent;
604 c_oil->oil.mfcc_parent = input_iface_vif_index;
605
606 /* update kernel multicast forwarding cache (MFC) */
607 if (pim_mroute_add(c_oil, __PRETTY_FUNCTION__)) {
608 if (PIM_DEBUG_MROUTE) {
609 /* just log warning */
7cfc7bcf
DS
610 struct interface *old_iif = pim_if_find_by_vif_index(
611 c_oil->pim, old_vif_index);
612 struct interface *new_iif = pim_if_find_by_vif_index(
613 c_oil->pim, input_iface_vif_index);
d62a17ae 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) failure updating input interface from %s vif_index=%d to %s vif_index=%d",
622 __FILE__, __PRETTY_FUNCTION__, source_str,
623 group_str,
624 old_iif ? old_iif->name : "<old_iif?>",
625 c_oil->oil.mfcc_parent,
626 new_iif ? new_iif->name : "<new_iif?>",
627 input_iface_vif_index);
628 }
629 }
8a67a996
DS
630}
631
da11e325 632void pim_scan_oil(struct pim_instance *pim)
8a67a996 633{
d62a17ae 634 struct listnode *node;
635 struct listnode *nextnode;
636 struct channel_oil *c_oil;
637 ifindex_t ifindex;
638 int vif_index = 0;
639
bfc92019
DS
640 pim->scan_oil_last = pim_time_monotonic_sec();
641 ++pim->scan_oil_events;
d62a17ae 642
da11e325
DS
643 for (ALL_LIST_ELEMENTS(pim->channel_oil_list, node, nextnode, c_oil)) {
644 if (c_oil->up && c_oil->up->rpf.source_nexthop.interface) {
645 ifindex = c_oil->up->rpf.source_nexthop
646 .interface->ifindex;
647 vif_index =
648 pim_if_find_vifindex_by_ifindex(pim, ifindex);
649 /* Pass Current selected NH vif index to mroute
650 * download */
651 if (vif_index)
652 pim_scan_individual_oil(c_oil, vif_index);
653 } else
654 pim_scan_individual_oil(c_oil, 0);
d62a17ae 655 }
12e41d03
DL
656}
657
658static int on_rpf_cache_refresh(struct thread *t)
659{
da11e325
DS
660 struct pim_instance *pim = THREAD_ARG(t);
661
d62a17ae 662 /* update PIM protocol state */
da11e325 663 scan_upstream_rpf_cache(pim);
12e41d03 664
d62a17ae 665 /* update kernel multicast forwarding cache (MFC) */
da11e325 666 pim_scan_oil(pim);
12e41d03 667
bfc92019
DS
668 pim->rpf_cache_refresh_last = pim_time_monotonic_sec();
669 ++pim->rpf_cache_refresh_events;
12e41d03 670
d62a17ae 671 // It is called as part of pim_neighbor_add
672 // pim_rp_setup ();
673 return 0;
12e41d03
DL
674}
675
da11e325 676void sched_rpf_cache_refresh(struct pim_instance *pim)
12e41d03 677{
bfc92019 678 ++pim->rpf_cache_refresh_requests;
12e41d03 679
bfc92019 680 pim_rpf_set_refresh_time(pim);
e71bf8f7 681
da11e325 682 if (pim->rpf_cache_refresher) {
d62a17ae 683 /* Refresh timer is already running */
684 return;
685 }
12e41d03 686
d62a17ae 687 /* Start refresh timer */
12e41d03 688
d62a17ae 689 if (PIM_DEBUG_ZEBRA) {
690 zlog_debug("%s: triggering %ld msec timer", __PRETTY_FUNCTION__,
691 qpim_rpf_cache_refresh_delay_msec);
692 }
12e41d03 693
da11e325 694 thread_add_timer_msec(master, on_rpf_cache_refresh, pim,
d62a17ae 695 qpim_rpf_cache_refresh_delay_msec,
da11e325 696 &pim->rpf_cache_refresher);
12e41d03
DL
697}
698
d62a17ae 699static void pim_zebra_connected(struct zclient *zclient)
48e8451b 700{
d62a17ae 701 /* Send the client registration */
702 bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER);
ba4eb1bc 703
0708beb1 704 zclient_send_reg_requests(zclient, pimg->vrf_id);
48e8451b 705}
8711a53d 706
eb05883f 707void pim_zebra_init(void)
12e41d03 708{
d62a17ae 709 int i;
12e41d03 710
d62a17ae 711 /* Socket for receiving updates from Zebra daemon */
e1a1880d 712 zclient = zclient_new_notify(master, &zclient_options_default);
d62a17ae 713
714 zclient->zebra_connected = pim_zebra_connected;
715 zclient->router_id_update = pim_router_id_update_zebra;
716 zclient->interface_add = pim_zebra_if_add;
717 zclient->interface_delete = pim_zebra_if_del;
718 zclient->interface_up = pim_zebra_if_state_up;
719 zclient->interface_down = pim_zebra_if_state_down;
720 zclient->interface_address_add = pim_zebra_if_address_add;
721 zclient->interface_address_delete = pim_zebra_if_address_del;
722 zclient->nexthop_update = pim_parse_nexthop_update;
723
342213ea 724 zclient_init(zclient, ZEBRA_ROUTE_PIM, 0, &pimd_privs);
d62a17ae 725 if (PIM_DEBUG_PIM_TRACE) {
726 zlog_info("zclient_init cleared redistribution request");
727 }
728
d62a17ae 729 /* Request all redistribution */
730 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
731 if (i == zclient->redist_default)
732 continue;
0708beb1 733 vrf_bitmap_set(zclient->redist[AFI_IP][i], pimg->vrf_id);
d62a17ae 734 ;
735 if (PIM_DEBUG_PIM_TRACE) {
736 zlog_debug("%s: requesting redistribution for %s (%i)",
737 __PRETTY_FUNCTION__, zebra_route_string(i),
738 i);
739 }
740 }
741
742 /* Request default information */
743 zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_ADD, zclient,
0708beb1 744 pimg->vrf_id);
d62a17ae 745
746 if (PIM_DEBUG_PIM_TRACE) {
747 zlog_info("%s: requesting default information redistribution",
748 __PRETTY_FUNCTION__);
749
750 zlog_notice("%s: zclient update socket initialized",
751 __PRETTY_FUNCTION__);
752 }
753
754 zclient_lookup_new();
12e41d03
DL
755}
756
6f932b0c
DS
757void igmp_anysource_forward_start(struct pim_instance *pim,
758 struct igmp_group *group)
12e41d03 759{
d62a17ae 760 struct igmp_source *source;
761 struct in_addr src_addr = {.s_addr = 0};
762 /* Any source (*,G) is forwarded only if mode is EXCLUDE {empty} */
763 zassert(group->group_filtermode_isexcl);
764 zassert(listcount(group->group_source_list) < 1);
765
766 source = source_new(group, src_addr);
767 if (!source) {
768 zlog_warn("%s: Failure to create * source",
769 __PRETTY_FUNCTION__);
770 return;
771 }
772
6f932b0c 773 igmp_source_forward_start(pim, source);
12e41d03
DL
774}
775
776void igmp_anysource_forward_stop(struct igmp_group *group)
777{
d62a17ae 778 struct igmp_source *source;
779 struct in_addr star = {.s_addr = 0};
12e41d03 780
d62a17ae 781 source = igmp_find_source_by_addr(group, star);
782 if (source)
783 igmp_source_forward_stop(source);
12e41d03
DL
784}
785
6f439a70
DS
786static void igmp_source_forward_reevaluate_one(struct pim_instance *pim,
787 struct igmp_source *source)
15a5dafe 788{
d62a17ae 789 struct prefix_sg sg;
790 struct igmp_group *group = source->source_group;
791 struct pim_ifchannel *ch;
792
793 if ((source->source_addr.s_addr != INADDR_ANY)
794 || !IGMP_SOURCE_TEST_FORWARDING(source->source_flags))
795 return;
796
797 memset(&sg, 0, sizeof(struct prefix_sg));
798 sg.src = source->source_addr;
799 sg.grp = group->group_addr;
800
801 ch = pim_ifchannel_find(group->group_igmp_sock->interface, &sg);
6f439a70 802 if (pim_is_grp_ssm(pim, group->group_addr)) {
d62a17ae 803 /* If SSM group withdraw local membership */
804 if (ch
805 && (ch->local_ifmembership == PIM_IFMEMBERSHIP_INCLUDE)) {
806 if (PIM_DEBUG_PIM_EVENTS)
807 zlog_debug(
808 "local membership del for %s as G is now SSM",
809 pim_str_sg_dump(&sg));
810 pim_ifchannel_local_membership_del(
811 group->group_igmp_sock->interface, &sg);
812 }
813 } else {
814 /* If ASM group add local membership */
815 if (!ch
816 || (ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO)) {
817 if (PIM_DEBUG_PIM_EVENTS)
818 zlog_debug(
819 "local membership add for %s as G is now ASM",
820 pim_str_sg_dump(&sg));
821 pim_ifchannel_local_membership_add(
822 group->group_igmp_sock->interface, &sg);
823 }
824 }
15a5dafe 825}
826
5d59e408 827void igmp_source_forward_reevaluate_all(struct pim_instance *pim)
15a5dafe 828{
d62a17ae 829 struct interface *ifp;
830
5d59e408
DS
831 FOR_ALL_INTERFACES (pim->vrf, ifp) {
832 struct pim_interface *pim_ifp = ifp->info;
833 struct listnode *sock_node;
834 struct igmp_sock *igmp;
835
836 if (!pim_ifp)
d62a17ae 837 continue;
838
5d59e408
DS
839 /* scan igmp sockets */
840 for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node,
841 igmp)) {
842 struct listnode *grpnode;
843 struct igmp_group *grp;
844
845 /* scan igmp groups */
846 for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list,
847 grpnode, grp)) {
848 struct listnode *srcnode;
849 struct igmp_source *src;
850
851 /* scan group sources */
852 for (ALL_LIST_ELEMENTS_RO(
853 grp->group_source_list, srcnode,
854 src)) {
855 igmp_source_forward_reevaluate_one(pim,
856 src);
857 } /* scan group sources */
858 } /* scan igmp groups */
859 } /* scan igmp sockets */
860 } /* scan interfaces */
15a5dafe 861}
862
6f932b0c
DS
863void igmp_source_forward_start(struct pim_instance *pim,
864 struct igmp_source *source)
12e41d03 865{
d62a17ae 866 struct igmp_group *group;
867 struct prefix_sg sg;
868 int result;
869 int input_iface_vif_index = 0;
870
871 memset(&sg, 0, sizeof(struct prefix_sg));
872 sg.src = source->source_addr;
873 sg.grp = source->source_group->group_addr;
874
875 if (PIM_DEBUG_IGMP_TRACE) {
876 zlog_debug(
877 "%s: (S,G)=%s igmp_sock=%d oif=%s fwd=%d",
878 __PRETTY_FUNCTION__, pim_str_sg_dump(&sg),
879 source->source_group->group_igmp_sock->fd,
880 source->source_group->group_igmp_sock->interface->name,
881 IGMP_SOURCE_TEST_FORWARDING(source->source_flags));
882 }
883
884 /* Prevent IGMP interface from installing multicast route multiple
885 times */
886 if (IGMP_SOURCE_TEST_FORWARDING(source->source_flags)) {
887 return;
8711a53d 888 }
d62a17ae 889
890 group = source->source_group;
891
892 if (!source->source_channel_oil) {
893 struct in_addr vif_source;
894 struct pim_interface *pim_oif;
895 struct prefix nht_p, src, grp;
d62a17ae 896 struct pim_nexthop_cache out_pnc;
897 struct pim_nexthop nexthop;
898 struct pim_upstream *up = NULL;
899
6f932b0c 900 if (!pim_rp_set_upstream_addr(pim, &vif_source,
d9c9a9ee 901 source->source_addr, sg.grp))
d62a17ae 902 return;
903
904 /* Register addr with Zebra NHT */
905 nht_p.family = AF_INET;
906 nht_p.prefixlen = IPV4_MAX_BITLEN;
907 nht_p.u.prefix4 = vif_source;
908 memset(&out_pnc, 0, sizeof(struct pim_nexthop_cache));
909
910 src.family = AF_INET;
911 src.prefixlen = IPV4_MAX_BITLEN;
912 src.u.prefix4 = vif_source; // RP or Src address
913 grp.family = AF_INET;
914 grp.prefixlen = IPV4_MAX_BITLEN;
915 grp.u.prefix4 = sg.grp;
916
6f932b0c 917 if (pim_find_or_track_nexthop(pim, &nht_p, NULL, NULL,
25bdac42 918 &out_pnc)) {
d62a17ae 919 if (out_pnc.nexthop_num) {
6f932b0c 920 up = pim_upstream_find(pim, &sg);
cb9c7c50 921 memset(&nexthop, 0, sizeof(nexthop));
d62a17ae 922 if (up)
923 memcpy(&nexthop,
924 &up->rpf.source_nexthop,
925 sizeof(struct pim_nexthop));
6f932b0c
DS
926 pim_ecmp_nexthop_search(pim, &out_pnc, &nexthop,
927 &src, &grp, 0);
d62a17ae 928 if (nexthop.interface)
929 input_iface_vif_index =
930 pim_if_find_vifindex_by_ifindex(
6f932b0c 931 pim,
d62a17ae 932 nexthop.interface->ifindex);
933 } else {
934 if (PIM_DEBUG_ZEBRA) {
935 char buf1[INET_ADDRSTRLEN];
936 char buf2[INET_ADDRSTRLEN];
937 pim_inet4_dump("<source?>",
938 nht_p.u.prefix4, buf1,
939 sizeof(buf1));
940 pim_inet4_dump("<source?>",
941 grp.u.prefix4, buf2,
942 sizeof(buf2));
943 zlog_debug(
944 "%s: NHT Nexthop not found for addr %s grp %s",
945 __PRETTY_FUNCTION__, buf1,
946 buf2);
947 }
948 }
949 } else
950 input_iface_vif_index =
25b787a2 951 pim_ecmp_fib_lookup_if_vif_index(
6f932b0c 952 pim, vif_source, &src, &grp);
d62a17ae 953
954 if (PIM_DEBUG_ZEBRA) {
955 char buf2[INET_ADDRSTRLEN];
956 pim_inet4_dump("<source?>", vif_source, buf2,
957 sizeof(buf2));
958 zlog_debug("%s: NHT %s vif_source %s vif_index:%d ",
959 __PRETTY_FUNCTION__, pim_str_sg_dump(&sg),
960 buf2, input_iface_vif_index);
961 }
962
963 if (input_iface_vif_index < 1) {
964 if (PIM_DEBUG_IGMP_TRACE) {
965 char source_str[INET_ADDRSTRLEN];
966 pim_inet4_dump("<source?>", source->source_addr,
967 source_str, sizeof(source_str));
968 zlog_debug(
969 "%s %s: could not find input interface for source %s",
970 __FILE__, __PRETTY_FUNCTION__,
971 source_str);
972 }
973 return;
974 }
975
976 /*
977 Protect IGMP against adding looped MFC entries created by both
978 source and receiver attached to the same interface. See TODO
979 T22.
980 */
981 pim_oif =
982 source->source_group->group_igmp_sock->interface->info;
983 if (!pim_oif) {
984 if (PIM_DEBUG_IGMP_TRACE) {
985 zlog_debug(
986 "%s: multicast not enabled on oif=%s ?",
987 __PRETTY_FUNCTION__,
988 source->source_group->group_igmp_sock
989 ->interface->name);
990 }
991 return;
992 }
993
994 if (input_iface_vif_index == pim_oif->mroute_vif_index) {
995 /* ignore request for looped MFC entry */
996 if (PIM_DEBUG_IGMP_TRACE) {
997 zlog_debug(
998 "%s: ignoring request for looped MFC entry (S,G)=%s: igmp_sock=%d oif=%s vif_index=%d",
999 __PRETTY_FUNCTION__,
1000 pim_str_sg_dump(&sg),
1001 source->source_group->group_igmp_sock
1002 ->fd,
1003 source->source_group->group_igmp_sock
1004 ->interface->name,
1005 input_iface_vif_index);
1006 }
1007 return;
1008 }
1009
1010 source->source_channel_oil =
6f932b0c 1011 pim_channel_oil_add(pim, &sg, input_iface_vif_index);
d62a17ae 1012 if (!source->source_channel_oil) {
1013 if (PIM_DEBUG_IGMP_TRACE) {
1014 zlog_debug(
1015 "%s %s: could not create OIL for channel (S,G)=%s",
1016 __FILE__, __PRETTY_FUNCTION__,
1017 pim_str_sg_dump(&sg));
1018 }
1019 return;
1020 }
8711a53d 1021 }
d62a17ae 1022
1023 result = pim_channel_add_oif(source->source_channel_oil,
1024 group->group_igmp_sock->interface,
1025 PIM_OIF_FLAG_PROTO_IGMP);
1026 if (result) {
1027 if (PIM_DEBUG_MROUTE) {
1028 zlog_warn("%s: add_oif() failed with return=%d",
1029 __func__, result);
1030 }
1031 return;
8711a53d 1032 }
d62a17ae 1033
1034 /*
1035 Feed IGMPv3-gathered local membership information into PIM
1036 per-interface (S,G) state.
1037 */
1038 if (!pim_ifchannel_local_membership_add(
1039 group->group_igmp_sock->interface, &sg)) {
1040 if (PIM_DEBUG_MROUTE)
1041 zlog_warn("%s: Failure to add local membership for %s",
1042 __PRETTY_FUNCTION__, pim_str_sg_dump(&sg));
1043 return;
1044 }
1045
1046 IGMP_SOURCE_DO_FORWARDING(source->source_flags);
12e41d03
DL
1047}
1048
1049/*
1050 igmp_source_forward_stop: stop fowarding, but keep the source
1051 igmp_source_delete: stop fowarding, and delete the source
1052 */
1053void igmp_source_forward_stop(struct igmp_source *source)
1054{
d62a17ae 1055 struct igmp_group *group;
1056 struct prefix_sg sg;
1057 int result;
1058
1059 memset(&sg, 0, sizeof(struct prefix_sg));
1060 sg.src = source->source_addr;
1061 sg.grp = source->source_group->group_addr;
1062
1063 if (PIM_DEBUG_IGMP_TRACE) {
1064 zlog_debug(
1065 "%s: (S,G)=%s igmp_sock=%d oif=%s fwd=%d",
1066 __PRETTY_FUNCTION__, pim_str_sg_dump(&sg),
1067 source->source_group->group_igmp_sock->fd,
1068 source->source_group->group_igmp_sock->interface->name,
1069 IGMP_SOURCE_TEST_FORWARDING(source->source_flags));
1070 }
1071
1072 /* Prevent IGMP interface from removing multicast route multiple
1073 times */
1074 if (!IGMP_SOURCE_TEST_FORWARDING(source->source_flags)) {
1075 return;
1076 }
1077
1078 group = source->source_group;
1079
1080 /*
1081 It appears that in certain circumstances that
1082 igmp_source_forward_stop is called when IGMP forwarding
1083 was not enabled in oif_flags for this outgoing interface.
1084 Possibly because of multiple calls. When that happens, we
1085 enter the below if statement and this function returns early
1086 which in turn triggers the calling function to assert.
1087 Making the call to pim_channel_del_oif and ignoring the return code
1088 fixes the issue without ill effect, similar to
1089 pim_forward_stop below.
1090 */
1091 result = pim_channel_del_oif(source->source_channel_oil,
1092 group->group_igmp_sock->interface,
1093 PIM_OIF_FLAG_PROTO_IGMP);
1094 if (result) {
1095 if (PIM_DEBUG_IGMP_TRACE)
1096 zlog_debug(
1097 "%s: pim_channel_del_oif() failed with return=%d",
1098 __func__, result);
1099 return;
1100 }
1101
1102 /*
1103 Feed IGMPv3-gathered local membership information into PIM
1104 per-interface (S,G) state.
1105 */
1106 pim_ifchannel_local_membership_del(group->group_igmp_sock->interface,
1107 &sg);
1108
1109 IGMP_SOURCE_DONT_FORWARDING(source->source_flags);
12e41d03
DL
1110}
1111
1112void pim_forward_start(struct pim_ifchannel *ch)
1113{
d62a17ae 1114 struct pim_upstream *up = ch->upstream;
1115 uint32_t mask = PIM_OIF_FLAG_PROTO_PIM;
1116 int input_iface_vif_index = 0;
6f932b0c
DS
1117 struct pim_instance *pim;
1118 struct pim_interface *pim_ifp;
1119
1120 pim_ifp = ch->interface->info;
1121 pim = pim_ifp->pim;
d62a17ae 1122
1123 if (PIM_DEBUG_PIM_TRACE) {
1124 char source_str[INET_ADDRSTRLEN];
1125 char group_str[INET_ADDRSTRLEN];
1126 char upstream_str[INET_ADDRSTRLEN];
1127
1128 pim_inet4_dump("<source?>", ch->sg.src, source_str,
1129 sizeof(source_str));
1130 pim_inet4_dump("<group?>", ch->sg.grp, group_str,
1131 sizeof(group_str));
1132 pim_inet4_dump("<upstream?>", up->upstream_addr, upstream_str,
1133 sizeof(upstream_str));
1134 zlog_debug("%s: (S,G)=(%s,%s) oif=%s (%s)", __PRETTY_FUNCTION__,
1135 source_str, group_str, ch->interface->name,
1136 upstream_str);
1137 }
1138
1139 /* Resolve IIF for upstream as mroute_del sets mfcc_parent to MAXVIFS,
1140 as part of mroute_del called by pim_forward_stop.
1141 */
1142 if (!up->channel_oil
1143 || (up->channel_oil
1144 && up->channel_oil->oil.mfcc_parent >= MAXVIFS)) {
1145 struct prefix nht_p, src, grp;
d62a17ae 1146 struct pim_nexthop_cache out_pnc;
1147
1148 /* Register addr with Zebra NHT */
1149 nht_p.family = AF_INET;
1150 nht_p.prefixlen = IPV4_MAX_BITLEN;
1151 nht_p.u.prefix4.s_addr = up->upstream_addr.s_addr;
1152 grp.family = AF_INET;
1153 grp.prefixlen = IPV4_MAX_BITLEN;
1154 grp.u.prefix4 = up->sg.grp;
1155 memset(&out_pnc, 0, sizeof(struct pim_nexthop_cache));
1156
6f932b0c 1157 if (pim_find_or_track_nexthop(pim, &nht_p, NULL, NULL,
25bdac42 1158 &out_pnc)) {
d62a17ae 1159 if (out_pnc.nexthop_num) {
1160 src.family = AF_INET;
1161 src.prefixlen = IPV4_MAX_BITLEN;
1162 src.u.prefix4 =
1163 up->upstream_addr; // RP or Src address
1164 grp.family = AF_INET;
1165 grp.prefixlen = IPV4_MAX_BITLEN;
1166 grp.u.prefix4 = up->sg.grp;
1167 // Compute PIM RPF using Cached nexthop
1168 if (pim_ecmp_nexthop_search(
6f932b0c 1169 pim, &out_pnc,
25b787a2
DS
1170 &up->rpf.source_nexthop, &src, &grp,
1171 0))
d62a17ae 1172 input_iface_vif_index =
1173 pim_if_find_vifindex_by_ifindex(
6f932b0c 1174 pim,
d62a17ae 1175 up->rpf.source_nexthop
1176 .interface->ifindex);
1177 else {
1178 if (PIM_DEBUG_TRACE)
1179 zlog_debug(
1180 "%s: Nexthop selection failed for %s ",
1181 __PRETTY_FUNCTION__,
1182 up->sg_str);
1183 }
1184 } else {
1185 if (PIM_DEBUG_ZEBRA) {
1186 char buf1[INET_ADDRSTRLEN];
1187 char buf2[INET_ADDRSTRLEN];
1188 pim_inet4_dump("<source?>",
1189 nht_p.u.prefix4, buf1,
1190 sizeof(buf1));
1191 pim_inet4_dump("<source?>",
1192 grp.u.prefix4, buf2,
1193 sizeof(buf2));
1194 zlog_debug(
1195 "%s: NHT pnc is NULL for addr %s grp %s",
1196 __PRETTY_FUNCTION__, buf1,
1197 buf2);
1198 }
1199 }
1200 } else
1201 input_iface_vif_index =
1202 pim_ecmp_fib_lookup_if_vif_index(
6f932b0c 1203 pim, up->upstream_addr, &src, &grp);
d62a17ae 1204
1205 if (input_iface_vif_index < 1) {
1206 if (PIM_DEBUG_PIM_TRACE) {
1207 char source_str[INET_ADDRSTRLEN];
1208 pim_inet4_dump("<source?>", up->sg.src,
1209 source_str, sizeof(source_str));
1210 zlog_debug(
1211 "%s %s: could not find input interface for source %s",
1212 __FILE__, __PRETTY_FUNCTION__,
1213 source_str);
1214 }
1215 return;
1216 }
1217 if (PIM_DEBUG_TRACE) {
7cfc7bcf 1218 struct interface *in_intf = pim_if_find_by_vif_index(
6f932b0c 1219 pim, input_iface_vif_index);
d62a17ae 1220 zlog_debug(
1221 "%s: Update channel_oil IIF %s VIFI %d entry %s ",
1222 __PRETTY_FUNCTION__,
1223 in_intf ? in_intf->name : "NIL",
1224 input_iface_vif_index, up->sg_str);
1225 }
6f932b0c 1226 up->channel_oil = pim_channel_oil_add(pim, &up->sg,
611925dc 1227 input_iface_vif_index);
d62a17ae 1228 if (!up->channel_oil) {
1229 if (PIM_DEBUG_PIM_TRACE)
1230 zlog_debug(
1231 "%s %s: could not create OIL for channel (S,G)=%s",
1232 __FILE__, __PRETTY_FUNCTION__,
1233 up->sg_str);
1234 return;
1235 }
1236 }
1237
1238 if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP)
1239 mask = PIM_OIF_FLAG_PROTO_IGMP;
1240
1241 pim_channel_add_oif(up->channel_oil, ch->interface, mask);
12e41d03
DL
1242}
1243
aabb9a2f 1244void pim_forward_stop(struct pim_ifchannel *ch, bool install_it)
12e41d03 1245{
d62a17ae 1246 struct pim_upstream *up = ch->upstream;
12e41d03 1247
d62a17ae 1248 if (PIM_DEBUG_PIM_TRACE) {
aabb9a2f
DS
1249 zlog_debug("%s: (S,G)=%s oif=%s install_it: %d installed: %d",
1250 __PRETTY_FUNCTION__, ch->sg_str, ch->interface->name,
1251 install_it, up->channel_oil->installed);
d62a17ae 1252 }
12e41d03 1253
d62a17ae 1254 pim_channel_del_oif(up->channel_oil, ch->interface,
1255 PIM_OIF_FLAG_PROTO_PIM);
aabb9a2f
DS
1256
1257 if (install_it && !up->channel_oil->installed)
1258 pim_mroute_add(up->channel_oil, __PRETTY_FUNCTION__);
12e41d03 1259}
8799b66b 1260
d62a17ae 1261void pim_zebra_zclient_update(struct vty *vty)
8799b66b 1262{
d62a17ae 1263 vty_out(vty, "Zclient update socket: ");
1264
1265 if (zclient) {
1266 vty_out(vty, "%d failures=%d\n", zclient->sock, zclient->fail);
1267 } else {
1268 vty_out(vty, "<null zclient>\n");
1269 }
8799b66b 1270}
1bc98276 1271
d62a17ae 1272struct zclient *pim_zebra_zclient_get(void)
1bc98276 1273{
d62a17ae 1274 if (zclient)
1275 return zclient;
1276 else
1277 return NULL;
1bc98276 1278}