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