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