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