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