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