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