]> git.proxmox.com Git - mirror_frr.git/blob - pimd/pim_zebra.c
Merge pull request #10582 from anlancs/pimd-remove-redundant
[mirror_frr.git] / pimd / pim_zebra.c
1 /*
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 */
19
20 #include <zebra.h>
21
22 #include "if.h"
23 #include "log.h"
24 #include "prefix.h"
25 #include "zclient.h"
26 #include "stream.h"
27 #include "network.h"
28 #include "vty.h"
29 #include "plist.h"
30 #include "lib/bfd.h"
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"
43 #include "pim_rp.h"
44 #include "pim_igmpv3.h"
45 #include "pim_jp_agg.h"
46 #include "pim_nht.h"
47 #include "pim_ssm.h"
48 #include "pim_vxlan.h"
49 #include "pim_mlag.h"
50
51 #undef PIM_DEBUG_IFADDR_DUMP
52 #define PIM_DEBUG_IFADDR_DUMP
53
54 struct zclient *zclient;
55
56
57 /* Router-id update message from zebra. */
58 static int pim_router_id_update_zebra(ZAPI_CALLBACK_ARGS)
59 {
60 struct prefix router_id;
61
62 zebra_router_id_update_read(zclient->ibuf, &router_id);
63
64 return 0;
65 }
66
67 static int pim_zebra_interface_vrf_update(ZAPI_CALLBACK_ARGS)
68 {
69 struct interface *ifp;
70 vrf_id_t new_vrf_id;
71
72 ifp = zebra_interface_vrf_update_read(zclient->ibuf, vrf_id,
73 &new_vrf_id);
74 if (!ifp)
75 return 0;
76
77 if (PIM_DEBUG_ZEBRA)
78 zlog_debug("%s: %s updating from %u to %u", __func__, ifp->name,
79 vrf_id, new_vrf_id);
80
81 if_update_to_new_vrf(ifp, new_vrf_id);
82
83 return 0;
84 }
85
86 #ifdef PIM_DEBUG_IFADDR_DUMP
87 static void dump_if_address(struct interface *ifp)
88 {
89 struct connected *ifc;
90 struct listnode *node;
91
92 zlog_debug("%s %s: interface %s addresses:", __FILE__, __func__,
93 ifp->name);
94
95 for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) {
96 struct prefix *p = ifc->address;
97
98 if (p->family != AF_INET)
99 continue;
100
101 zlog_debug("%s %s: interface %s address %pI4 %s", __FILE__,
102 __func__, ifp->name, &p->u.prefix4,
103 CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY)
104 ? "secondary"
105 : "primary");
106 }
107 }
108 #endif
109
110 static int pim_zebra_if_address_add(ZAPI_CALLBACK_ARGS)
111 {
112 struct connected *c;
113 struct prefix *p;
114 struct pim_interface *pim_ifp;
115 struct pim_instance *pim;
116
117 /*
118 zebra api notifies address adds/dels events by using the same call
119 interface_add_read below, see comments in lib/zclient.c
120
121 zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_ADD, ...)
122 will add address to interface list by calling
123 connected_add_by_prefix()
124 */
125 c = zebra_interface_address_read(cmd, zclient->ibuf, vrf_id);
126 if (!c)
127 return 0;
128
129 pim_ifp = c->ifp->info;
130 p = c->address;
131
132 if (PIM_DEBUG_ZEBRA) {
133 zlog_debug("%s: %s(%u) connected IP address %pFX flags %u %s",
134 __func__, c->ifp->name, vrf_id, p, c->flags,
135 CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY)
136 ? "secondary"
137 : "primary");
138
139 #ifdef PIM_DEBUG_IFADDR_DUMP
140 dump_if_address(c->ifp);
141 #endif
142 }
143
144 if (p->family != PIM_AF)
145 SET_FLAG(c->flags, ZEBRA_IFA_SECONDARY);
146 else if (!CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY)) {
147 /* trying to add primary address? */
148 pim_addr primary_addr = pim_find_primary_addr(c->ifp);
149 pim_addr addr = pim_addr_from_prefix(p);
150
151 if (pim_addr_cmp(primary_addr, addr)) {
152 if (PIM_DEBUG_ZEBRA)
153 zlog_warn(
154 "%s: %s : forcing secondary flag on %pFX",
155 __func__, c->ifp->name, p);
156 SET_FLAG(c->flags, ZEBRA_IFA_SECONDARY);
157 }
158 }
159
160 pim_if_addr_add(c);
161 if (pim_ifp) {
162 pim = pim_get_pim_instance(vrf_id);
163 pim_ifp->pim = pim;
164
165 pim_rp_check_on_if_add(pim_ifp);
166 }
167
168 if (if_is_loopback(c->ifp)) {
169 struct vrf *vrf = vrf_lookup_by_id(vrf_id);
170 struct interface *ifp;
171
172 FOR_ALL_INTERFACES (vrf, ifp) {
173 if (!if_is_loopback(ifp) && if_is_operative(ifp))
174 pim_if_addr_add_all(ifp);
175 }
176 }
177
178 return 0;
179 }
180
181 static int pim_zebra_if_address_del(ZAPI_CALLBACK_ARGS)
182 {
183 struct connected *c;
184 struct prefix *p;
185 struct vrf *vrf = vrf_lookup_by_id(vrf_id);
186 struct pim_instance *pim;
187
188 if (!vrf)
189 return 0;
190 pim = vrf->info;
191
192 /*
193 zebra api notifies address adds/dels events by using the same call
194 interface_add_read below, see comments in lib/zclient.c
195
196 zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_DELETE, ...)
197 will remove address from interface list by calling
198 connected_delete_by_prefix()
199 */
200 c = zebra_interface_address_read(cmd, zclient->ibuf, vrf_id);
201 if (!c)
202 return 0;
203
204 p = c->address;
205 if (p->family == AF_INET) {
206 if (PIM_DEBUG_ZEBRA) {
207 zlog_debug(
208 "%s: %s(%u) disconnected IP address %pFX flags %u %s",
209 __func__, c->ifp->name, vrf_id, p, c->flags,
210 CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY)
211 ? "secondary"
212 : "primary");
213
214 #ifdef PIM_DEBUG_IFADDR_DUMP
215 dump_if_address(c->ifp);
216 #endif
217 }
218
219 pim_if_addr_del(c, 0);
220 pim_rp_setup(pim);
221 pim_i_am_rp_re_evaluate(pim);
222 }
223
224 connected_free(&c);
225 return 0;
226 }
227
228 void pim_zebra_update_all_interfaces(struct pim_instance *pim)
229 {
230 struct interface *ifp;
231
232 FOR_ALL_INTERFACES (pim->vrf, ifp) {
233 struct pim_interface *pim_ifp = ifp->info;
234 struct pim_iface_upstream_switch *us;
235 struct listnode *node;
236
237 if (!pim_ifp)
238 continue;
239
240 for (ALL_LIST_ELEMENTS_RO(pim_ifp->upstream_switch_list, node,
241 us)) {
242 struct pim_rpf rpf;
243
244 rpf.source_nexthop.interface = ifp;
245 rpf.rpf_addr.u.prefix4 = us->address;
246 pim_joinprune_send(&rpf, us->us);
247 pim_jp_agg_clear_group(us->us);
248 }
249 }
250 }
251
252 void pim_zebra_upstream_rpf_changed(struct pim_instance *pim,
253 struct pim_upstream *up,
254 struct pim_rpf *old)
255 {
256 if (old->source_nexthop.interface) {
257 struct pim_neighbor *nbr;
258
259 nbr = pim_neighbor_find_prefix(old->source_nexthop.interface,
260 &old->rpf_addr);
261 if (nbr)
262 pim_jp_agg_remove_group(nbr->upstream_jp_agg, up, nbr);
263
264 /*
265 * We have detected a case where we might need
266 * to rescan the inherited o_list so do it.
267 */
268 if (up->channel_oil->oil_inherited_rescan) {
269 pim_upstream_inherited_olist_decide(pim, up);
270 up->channel_oil->oil_inherited_rescan = 0;
271 }
272
273 if (up->join_state == PIM_UPSTREAM_JOINED) {
274 /*
275 * If we come up real fast we can be here
276 * where the mroute has not been installed
277 * so install it.
278 */
279 if (!up->channel_oil->installed)
280 pim_upstream_mroute_add(up->channel_oil,
281 __func__);
282
283 /*
284 * RFC 4601: 4.5.7. Sending (S,G)
285 * Join/Prune Messages
286 *
287 * Transitions from Joined State
288 *
289 * RPF'(S,G) changes not due to an Assert
290 *
291 * The upstream (S,G) state machine remains
292 * in Joined state. Send Join(S,G) to the new
293 * upstream neighbor, which is the new value
294 * of RPF'(S,G). Send Prune(S,G) to the old
295 * upstream neighbor, which is the old value
296 * of RPF'(S,G). Set the Join Timer (JT) to
297 * expire after t_periodic seconds.
298 */
299 pim_jp_agg_switch_interface(old, &up->rpf, up);
300
301 pim_upstream_join_timer_restart(up, old);
302 } /* up->join_state == PIM_UPSTREAM_JOINED */
303 }
304
305 else {
306 /*
307 * We have detected a case where we might need
308 * to rescan the inherited o_list so do it.
309 */
310 if (up->channel_oil->oil_inherited_rescan) {
311 pim_upstream_inherited_olist_decide(pim, up);
312 up->channel_oil->oil_inherited_rescan = 0;
313 }
314
315 if (up->join_state == PIM_UPSTREAM_JOINED)
316 pim_jp_agg_switch_interface(old, &up->rpf, up);
317
318 if (!up->channel_oil->installed)
319 pim_upstream_mroute_add(up->channel_oil, __func__);
320 }
321
322 /* FIXME can join_desired actually be changed by pim_rpf_update()
323 * returning PIM_RPF_CHANGED ?
324 */
325 pim_upstream_update_join_desired(pim, up);
326 }
327
328 static int pim_zebra_vxlan_sg_proc(ZAPI_CALLBACK_ARGS)
329 {
330 struct stream *s;
331 struct pim_instance *pim;
332 pim_sgaddr sg;
333 size_t prefixlen;
334
335 pim = pim_get_pim_instance(vrf_id);
336 if (!pim)
337 return 0;
338
339 s = zclient->ibuf;
340
341 prefixlen = stream_getl(s);
342 stream_get(&sg.src, s, prefixlen);
343 stream_get(&sg.grp, s, prefixlen);
344
345 if (PIM_DEBUG_ZEBRA)
346 zlog_debug("%u:recv SG %s %pSG", vrf_id,
347 (cmd == ZEBRA_VXLAN_SG_ADD) ? "add" : "del", &sg);
348
349 if (cmd == ZEBRA_VXLAN_SG_ADD)
350 pim_vxlan_sg_add(pim, &sg);
351 else
352 pim_vxlan_sg_del(pim, &sg);
353
354 return 0;
355 }
356
357 static void pim_zebra_vxlan_replay(void)
358 {
359 struct stream *s = NULL;
360
361 /* Check socket. */
362 if (!zclient || zclient->sock < 0)
363 return;
364
365 s = zclient->obuf;
366 stream_reset(s);
367
368 zclient_create_header(s, ZEBRA_VXLAN_SG_REPLAY, VRF_DEFAULT);
369 stream_putw_at(s, 0, stream_get_endp(s));
370
371 zclient_send_message(zclient);
372 }
373
374 void pim_scan_oil(struct pim_instance *pim)
375 {
376 struct channel_oil *c_oil;
377
378 pim->scan_oil_last = pim_time_monotonic_sec();
379 ++pim->scan_oil_events;
380
381 frr_each (rb_pim_oil, &pim->channel_oil_head, c_oil)
382 pim_upstream_mroute_iif_update(c_oil, __func__);
383 }
384
385 static int on_rpf_cache_refresh(struct thread *t)
386 {
387 struct pim_instance *pim = THREAD_ARG(t);
388
389 /* update kernel multicast forwarding cache (MFC) */
390 pim_scan_oil(pim);
391
392 pim->rpf_cache_refresh_last = pim_time_monotonic_sec();
393 ++pim->rpf_cache_refresh_events;
394
395 // It is called as part of pim_neighbor_add
396 // pim_rp_setup ();
397 return 0;
398 }
399
400 void sched_rpf_cache_refresh(struct pim_instance *pim)
401 {
402 ++pim->rpf_cache_refresh_requests;
403
404 pim_rpf_set_refresh_time(pim);
405
406 if (pim->rpf_cache_refresher) {
407 /* Refresh timer is already running */
408 return;
409 }
410
411 /* Start refresh timer */
412
413 if (PIM_DEBUG_ZEBRA) {
414 zlog_debug("%s: triggering %ld msec timer", __func__,
415 router->rpf_cache_refresh_delay_msec);
416 }
417
418 thread_add_timer_msec(router->master, on_rpf_cache_refresh, pim,
419 router->rpf_cache_refresh_delay_msec,
420 &pim->rpf_cache_refresher);
421 }
422
423 static void pim_zebra_connected(struct zclient *zclient)
424 {
425 /* Send the client registration */
426 bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER, router->vrf_id);
427
428 zclient_send_reg_requests(zclient, router->vrf_id);
429
430 /* request for VxLAN BUM group addresses */
431 pim_zebra_vxlan_replay();
432 }
433
434 static void pim_zebra_capabilities(struct zclient_capabilities *cap)
435 {
436 router->mlag_role = cap->role;
437 }
438
439 static zclient_handler *const pim_handlers[] = {
440 [ZEBRA_ROUTER_ID_UPDATE] = pim_router_id_update_zebra,
441 [ZEBRA_INTERFACE_ADDRESS_ADD] = pim_zebra_if_address_add,
442 [ZEBRA_INTERFACE_ADDRESS_DELETE] = pim_zebra_if_address_del,
443 [ZEBRA_INTERFACE_VRF_UPDATE] = pim_zebra_interface_vrf_update,
444 [ZEBRA_NEXTHOP_UPDATE] = pim_parse_nexthop_update,
445
446 [ZEBRA_VXLAN_SG_ADD] = pim_zebra_vxlan_sg_proc,
447 [ZEBRA_VXLAN_SG_DEL] = pim_zebra_vxlan_sg_proc,
448
449 [ZEBRA_MLAG_PROCESS_UP] = pim_zebra_mlag_process_up,
450 [ZEBRA_MLAG_PROCESS_DOWN] = pim_zebra_mlag_process_down,
451 [ZEBRA_MLAG_FORWARD_MSG] = pim_zebra_mlag_handle_msg,
452 };
453
454 void pim_zebra_init(void)
455 {
456 /* Socket for receiving updates from Zebra daemon */
457 zclient = zclient_new(router->master, &zclient_options_default,
458 pim_handlers, array_size(pim_handlers));
459
460 zclient->zebra_capabilities = pim_zebra_capabilities;
461 zclient->zebra_connected = pim_zebra_connected;
462
463 zclient_init(zclient, ZEBRA_ROUTE_PIM, 0, &pimd_privs);
464 if (PIM_DEBUG_PIM_TRACE) {
465 zlog_notice("%s: zclient socket initialized", __func__);
466 }
467
468 zclient_lookup_new();
469 }
470
471 void igmp_anysource_forward_start(struct pim_instance *pim,
472 struct gm_group *group)
473 {
474 struct gm_source *source;
475 struct in_addr src_addr = {.s_addr = 0};
476 /* Any source (*,G) is forwarded only if mode is EXCLUDE {empty} */
477 assert(group->group_filtermode_isexcl);
478 assert(listcount(group->group_source_list) < 1);
479
480 source = igmp_get_source_by_addr(group, src_addr, NULL);
481 if (!source) {
482 zlog_warn("%s: Failure to create * source", __func__);
483 return;
484 }
485
486 igmp_source_forward_start(pim, source);
487 }
488
489 void igmp_anysource_forward_stop(struct gm_group *group)
490 {
491 struct gm_source *source;
492 struct in_addr star = {.s_addr = 0};
493
494 source = igmp_find_source_by_addr(group, star);
495 if (source)
496 igmp_source_forward_stop(source);
497 }
498
499 static void igmp_source_forward_reevaluate_one(struct pim_instance *pim,
500 struct gm_source *source)
501 {
502 pim_sgaddr sg;
503 struct gm_group *group = source->source_group;
504 struct pim_ifchannel *ch;
505
506 if ((source->source_addr.s_addr != INADDR_ANY)
507 || !IGMP_SOURCE_TEST_FORWARDING(source->source_flags))
508 return;
509
510 memset(&sg, 0, sizeof(sg));
511 sg.src = source->source_addr;
512 sg.grp = group->group_addr;
513
514 ch = pim_ifchannel_find(group->interface, &sg);
515 if (pim_is_grp_ssm(pim, group->group_addr)) {
516 /* If SSM group withdraw local membership */
517 if (ch
518 && (ch->local_ifmembership == PIM_IFMEMBERSHIP_INCLUDE)) {
519 if (PIM_DEBUG_PIM_EVENTS)
520 zlog_debug("local membership del for %pSG as G is now SSM",
521 &sg);
522 pim_ifchannel_local_membership_del(group->interface,
523 &sg);
524 }
525 } else {
526 /* If ASM group add local membership */
527 if (!ch
528 || (ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO)) {
529 if (PIM_DEBUG_PIM_EVENTS)
530 zlog_debug("local membership add for %pSG as G is now ASM",
531 &sg);
532 pim_ifchannel_local_membership_add(
533 group->interface, &sg, false /*is_vxlan*/);
534 }
535 }
536 }
537
538 void igmp_source_forward_reevaluate_all(struct pim_instance *pim)
539 {
540 struct interface *ifp;
541
542 FOR_ALL_INTERFACES (pim->vrf, ifp) {
543 struct pim_interface *pim_ifp = ifp->info;
544 struct listnode *grpnode;
545 struct gm_group *grp;
546 struct pim_ifchannel *ch, *ch_temp;
547
548 if (!pim_ifp)
549 continue;
550
551 /* scan igmp groups */
552 for (ALL_LIST_ELEMENTS_RO(pim_ifp->gm_group_list, grpnode,
553 grp)) {
554 struct listnode *srcnode;
555 struct gm_source *src;
556
557 /* scan group sources */
558 for (ALL_LIST_ELEMENTS_RO(grp->group_source_list,
559 srcnode, src)) {
560 igmp_source_forward_reevaluate_one(pim, src);
561 } /* scan group sources */
562 } /* scan igmp groups */
563
564 RB_FOREACH_SAFE (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb,
565 ch_temp) {
566 if (pim_is_grp_ssm(pim, ch->sg.grp)) {
567 if (pim_addr_is_any(ch->sg.src))
568 pim_ifchannel_delete(ch);
569 }
570 }
571 } /* scan interfaces */
572 }
573
574 void igmp_source_forward_start(struct pim_instance *pim,
575 struct gm_source *source)
576 {
577 struct pim_interface *pim_oif;
578 struct gm_group *group;
579 pim_sgaddr sg;
580 int result;
581 int input_iface_vif_index = 0;
582
583 memset(&sg, 0, sizeof(sg));
584 sg.src = source->source_addr;
585 sg.grp = source->source_group->group_addr;
586
587 if (PIM_DEBUG_IGMP_TRACE) {
588 zlog_debug("%s: (S,G)=%pSG oif=%s fwd=%d", __func__, &sg,
589 source->source_group->interface->name,
590 IGMP_SOURCE_TEST_FORWARDING(source->source_flags));
591 }
592
593 /* Prevent IGMP interface from installing multicast route multiple
594 times */
595 if (IGMP_SOURCE_TEST_FORWARDING(source->source_flags)) {
596 return;
597 }
598
599 group = source->source_group;
600 pim_oif = group->interface->info;
601 if (!pim_oif) {
602 if (PIM_DEBUG_IGMP_TRACE) {
603 zlog_debug("%s: multicast not enabled on oif=%s ?",
604 __func__,
605 source->source_group->interface->name);
606 }
607 return;
608 }
609
610 if (!source->source_channel_oil) {
611 pim_addr vif_source;
612 struct prefix src, grp;
613 struct pim_nexthop nexthop;
614 struct pim_upstream *up = NULL;
615
616 if (!pim_rp_set_upstream_addr(pim, &vif_source,
617 source->source_addr, sg.grp)) {
618 /*Create a dummy channel oil */
619 source->source_channel_oil =
620 pim_channel_oil_add(pim, &sg, __func__);
621 }
622
623 else {
624 pim_addr_to_prefix(&src, vif_source); // RP or Src addr
625 pim_addr_to_prefix(&grp, sg.grp);
626
627 up = pim_upstream_find(pim, &sg);
628 if (up) {
629 memcpy(&nexthop, &up->rpf.source_nexthop,
630 sizeof(struct pim_nexthop));
631 pim_ecmp_nexthop_lookup(pim, &nexthop, &src,
632 &grp, 0);
633 if (nexthop.interface)
634 input_iface_vif_index =
635 pim_if_find_vifindex_by_ifindex(
636 pim,
637 nexthop.interface->ifindex);
638 } else
639 input_iface_vif_index =
640 pim_ecmp_fib_lookup_if_vif_index(
641 pim, &src, &grp);
642
643 if (PIM_DEBUG_ZEBRA)
644 zlog_debug(
645 "%s: NHT %pSG vif_source %pPAs vif_index:%d ",
646 __func__, &sg, &vif_source,
647 input_iface_vif_index);
648
649 if (input_iface_vif_index < 1) {
650 if (PIM_DEBUG_IGMP_TRACE) {
651 char source_str[INET_ADDRSTRLEN];
652 pim_inet4_dump("<source?>",
653 source->source_addr,
654 source_str, sizeof(source_str));
655 zlog_debug(
656 "%s %s: could not find input interface for source %s",
657 __FILE__, __func__, source_str);
658 }
659 source->source_channel_oil =
660 pim_channel_oil_add(pim, &sg, __func__);
661 }
662
663 else {
664 /*
665 * Protect IGMP against adding looped MFC
666 * entries created by both source and receiver
667 * attached to the same interface. See TODO
668 * T22. Block only when the intf is non DR
669 * DR must create upstream.
670 */
671 if ((input_iface_vif_index ==
672 pim_oif->mroute_vif_index) &&
673 !(PIM_I_am_DR(pim_oif))) {
674 /* ignore request for looped MFC entry
675 */
676 if (PIM_DEBUG_IGMP_TRACE) {
677 zlog_debug("%s: ignoring request for looped MFC entry (S,G)=%pSG: oif=%s vif_index=%d",
678 __func__,
679 &sg,
680 source->source_group
681 ->interface->name,
682 input_iface_vif_index);
683 }
684 return;
685 }
686
687 source->source_channel_oil =
688 pim_channel_oil_add(pim, &sg, __func__);
689 if (!source->source_channel_oil) {
690 if (PIM_DEBUG_IGMP_TRACE) {
691 zlog_debug("%s %s: could not create OIL for channel (S,G)=%pSG",
692 __FILE__, __func__,
693 &sg);
694 }
695 return;
696 }
697 }
698 }
699 }
700
701 if (PIM_I_am_DR(pim_oif) || PIM_I_am_DualActive(pim_oif)) {
702 result = pim_channel_add_oif(source->source_channel_oil,
703 group->interface,
704 PIM_OIF_FLAG_PROTO_IGMP, __func__);
705 if (result) {
706 if (PIM_DEBUG_MROUTE) {
707 zlog_warn("%s: add_oif() failed with return=%d",
708 __func__, result);
709 }
710 return;
711 }
712 } else {
713 if (PIM_DEBUG_IGMP_TRACE)
714 zlog_debug("%s: %pSG was received on %s interface but we are not DR for that interface",
715 __func__, &sg,
716 group->interface->name);
717
718 return;
719 }
720 /*
721 Feed IGMPv3-gathered local membership information into PIM
722 per-interface (S,G) state.
723 */
724 if (!pim_ifchannel_local_membership_add(group->interface, &sg,
725 false /*is_vxlan*/)) {
726 if (PIM_DEBUG_MROUTE)
727 zlog_warn("%s: Failure to add local membership for %pSG",
728 __func__, &sg);
729
730 pim_channel_del_oif(source->source_channel_oil,
731 group->interface, PIM_OIF_FLAG_PROTO_IGMP,
732 __func__);
733 return;
734 }
735
736 IGMP_SOURCE_DO_FORWARDING(source->source_flags);
737 }
738
739 /*
740 igmp_source_forward_stop: stop fowarding, but keep the source
741 igmp_source_delete: stop fowarding, and delete the source
742 */
743 void igmp_source_forward_stop(struct gm_source *source)
744 {
745 struct gm_group *group;
746 pim_sgaddr sg;
747 int result;
748
749 memset(&sg, 0, sizeof(sg));
750 sg.src = source->source_addr;
751 sg.grp = source->source_group->group_addr;
752
753 if (PIM_DEBUG_IGMP_TRACE) {
754 zlog_debug("%s: (S,G)=%pSG oif=%s fwd=%d", __func__, &sg,
755 source->source_group->interface->name,
756 IGMP_SOURCE_TEST_FORWARDING(source->source_flags));
757 }
758
759 /* Prevent IGMP interface from removing multicast route multiple
760 times */
761 if (!IGMP_SOURCE_TEST_FORWARDING(source->source_flags)) {
762 return;
763 }
764
765 group = source->source_group;
766
767 /*
768 It appears that in certain circumstances that
769 igmp_source_forward_stop is called when IGMP forwarding
770 was not enabled in oif_flags for this outgoing interface.
771 Possibly because of multiple calls. When that happens, we
772 enter the below if statement and this function returns early
773 which in turn triggers the calling function to assert.
774 Making the call to pim_channel_del_oif and ignoring the return code
775 fixes the issue without ill effect, similar to
776 pim_forward_stop below.
777 */
778 result = pim_channel_del_oif(source->source_channel_oil,
779 group->interface, PIM_OIF_FLAG_PROTO_IGMP,
780 __func__);
781 if (result) {
782 if (PIM_DEBUG_IGMP_TRACE)
783 zlog_debug(
784 "%s: pim_channel_del_oif() failed with return=%d",
785 __func__, result);
786 return;
787 }
788
789 /*
790 Feed IGMPv3-gathered local membership information into PIM
791 per-interface (S,G) state.
792 */
793 pim_ifchannel_local_membership_del(group->interface, &sg);
794
795 IGMP_SOURCE_DONT_FORWARDING(source->source_flags);
796 }
797
798 void pim_forward_start(struct pim_ifchannel *ch)
799 {
800 struct pim_upstream *up = ch->upstream;
801 uint32_t mask = 0;
802
803 if (PIM_DEBUG_PIM_TRACE)
804 zlog_debug("%s: (S,G)=%pSG oif=%s (%pI4)", __func__, &ch->sg,
805 ch->interface->name, &up->upstream_addr);
806
807 if (PIM_IF_FLAG_TEST_PROTO_IGMP(ch->flags))
808 mask = PIM_OIF_FLAG_PROTO_IGMP;
809
810 if (PIM_IF_FLAG_TEST_PROTO_PIM(ch->flags))
811 mask |= PIM_OIF_FLAG_PROTO_PIM;
812
813 pim_channel_add_oif(up->channel_oil, ch->interface,
814 mask, __func__);
815 }
816
817 void pim_forward_stop(struct pim_ifchannel *ch)
818 {
819 struct pim_upstream *up = ch->upstream;
820
821 if (PIM_DEBUG_PIM_TRACE) {
822 zlog_debug("%s: (S,G)=%s oif=%s installed: %d",
823 __func__, ch->sg_str, ch->interface->name,
824 up->channel_oil->installed);
825 }
826
827 /*
828 * If a channel is being removed, check to see if we still need
829 * to inherit the interface. If so make sure it is added in
830 */
831 if (pim_upstream_evaluate_join_desired_interface(up, ch, ch->parent))
832 pim_channel_add_oif(up->channel_oil, ch->interface,
833 PIM_OIF_FLAG_PROTO_PIM, __func__);
834 else
835 pim_channel_del_oif(up->channel_oil, ch->interface,
836 PIM_OIF_FLAG_PROTO_PIM, __func__);
837 }
838
839 void pim_zebra_zclient_update(struct vty *vty)
840 {
841 vty_out(vty, "Zclient update socket: ");
842
843 if (zclient) {
844 vty_out(vty, "%d failures=%d\n", zclient->sock, zclient->fail);
845 } else {
846 vty_out(vty, "<null zclient>\n");
847 }
848 }
849
850 struct zclient *pim_zebra_zclient_get(void)
851 {
852 if (zclient)
853 return zclient;
854 else
855 return NULL;
856 }
857
858 void pim_zebra_interface_set_master(struct interface *vrf,
859 struct interface *ifp)
860 {
861 zclient_interface_set_master(zclient, vrf, ifp);
862 }