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