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