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