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