]> git.proxmox.com Git - mirror_frr.git/blob - pimd/pim_zebra.c
Merge pull request #5356 from v00lk/master
[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);
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_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->channel_oil->installed)
329 pim_mroute_add(up->channel_oil, __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_individual_oil(struct channel_oil *c_oil, int in_vif_index)
390 {
391 struct in_addr vif_source;
392 int input_iface_vif_index;
393
394 pim_rp_set_upstream_addr(c_oil->pim, &vif_source,
395 c_oil->oil.mfcc_origin,
396 c_oil->oil.mfcc_mcastgrp);
397
398 if (in_vif_index)
399 input_iface_vif_index = in_vif_index;
400 else {
401 struct prefix src, grp;
402
403 src.family = AF_INET;
404 src.prefixlen = IPV4_MAX_BITLEN;
405 src.u.prefix4 = vif_source;
406 grp.family = AF_INET;
407 grp.prefixlen = IPV4_MAX_BITLEN;
408 grp.u.prefix4 = c_oil->oil.mfcc_mcastgrp;
409
410 if (PIM_DEBUG_ZEBRA) {
411 char source_str[INET_ADDRSTRLEN];
412 char group_str[INET_ADDRSTRLEN];
413 pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin,
414 source_str, sizeof(source_str));
415 pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp,
416 group_str, sizeof(group_str));
417 zlog_debug(
418 "%s: channel_oil (%s,%s) upstream info is not present.",
419 __PRETTY_FUNCTION__, source_str, group_str);
420 }
421 input_iface_vif_index = pim_ecmp_fib_lookup_if_vif_index(
422 c_oil->pim, &src, &grp);
423 }
424
425 if (input_iface_vif_index < 1) {
426 if (PIM_DEBUG_ZEBRA) {
427 char source_str[INET_ADDRSTRLEN];
428 char group_str[INET_ADDRSTRLEN];
429 pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin,
430 source_str, sizeof(source_str));
431 pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp,
432 group_str, sizeof(group_str));
433 zlog_debug(
434 "%s %s: could not find input interface(%d) for (S,G)=(%s,%s)",
435 __FILE__, __PRETTY_FUNCTION__,
436 c_oil->oil.mfcc_parent, source_str, group_str);
437 }
438 pim_mroute_del(c_oil, __PRETTY_FUNCTION__);
439 return;
440 }
441
442 if (input_iface_vif_index == c_oil->oil.mfcc_parent) {
443 if (!c_oil->installed)
444 pim_mroute_add(c_oil, __PRETTY_FUNCTION__);
445
446 /* RPF unchanged */
447 return;
448 }
449
450 if (PIM_DEBUG_ZEBRA) {
451 struct interface *old_iif = pim_if_find_by_vif_index(
452 c_oil->pim, c_oil->oil.mfcc_parent);
453 struct interface *new_iif = pim_if_find_by_vif_index(
454 c_oil->pim, input_iface_vif_index);
455 char source_str[INET_ADDRSTRLEN];
456 char group_str[INET_ADDRSTRLEN];
457 pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str,
458 sizeof(source_str));
459 pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str,
460 sizeof(group_str));
461 zlog_debug(
462 "%s %s: (S,G)=(%s,%s) input interface changed from %s vif_index=%d to %s vif_index=%d",
463 __FILE__, __PRETTY_FUNCTION__, source_str, group_str,
464 (old_iif) ? old_iif->name : "<old_iif?>",
465 c_oil->oil.mfcc_parent,
466 (new_iif) ? new_iif->name : "<new_iif?>",
467 input_iface_vif_index);
468 }
469
470 /* new iif loops to existing oif ? */
471 if (c_oil->oil.mfcc_ttls[input_iface_vif_index]) {
472 struct interface *new_iif = pim_if_find_by_vif_index(
473 c_oil->pim, input_iface_vif_index);
474
475 if (PIM_DEBUG_ZEBRA) {
476 char source_str[INET_ADDRSTRLEN];
477 char group_str[INET_ADDRSTRLEN];
478 pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin,
479 source_str, sizeof(source_str));
480 pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp,
481 group_str, sizeof(group_str));
482 zlog_debug(
483 "%s %s: (S,G)=(%s,%s) new iif loops to existing oif: %s vif_index=%d",
484 __FILE__, __PRETTY_FUNCTION__, source_str,
485 group_str,
486 (new_iif) ? new_iif->name : "<new_iif?>",
487 input_iface_vif_index);
488 }
489 }
490
491 /* update iif vif_index */
492 pim_channel_oil_change_iif(c_oil->pim, c_oil, input_iface_vif_index,
493 __PRETTY_FUNCTION__);
494 pim_mroute_add(c_oil, __PRETTY_FUNCTION__);
495 }
496
497 void pim_scan_oil(struct pim_instance *pim)
498 {
499 struct listnode *node;
500 struct listnode *nextnode;
501 struct channel_oil *c_oil;
502 ifindex_t ifindex;
503 int vif_index = 0;
504
505 pim->scan_oil_last = pim_time_monotonic_sec();
506 ++pim->scan_oil_events;
507
508 for (ALL_LIST_ELEMENTS(pim->channel_oil_list, node, nextnode, c_oil)) {
509 if (c_oil->up && c_oil->up->rpf.source_nexthop.interface) {
510 ifindex = c_oil->up->rpf.source_nexthop
511 .interface->ifindex;
512 vif_index =
513 pim_if_find_vifindex_by_ifindex(pim, ifindex);
514 /* Pass Current selected NH vif index to mroute
515 * download */
516 if (vif_index)
517 pim_scan_individual_oil(c_oil, vif_index);
518 } else
519 pim_scan_individual_oil(c_oil, 0);
520 }
521 }
522
523 static int on_rpf_cache_refresh(struct thread *t)
524 {
525 struct pim_instance *pim = THREAD_ARG(t);
526
527 /* update kernel multicast forwarding cache (MFC) */
528 pim_scan_oil(pim);
529
530 pim->rpf_cache_refresh_last = pim_time_monotonic_sec();
531 ++pim->rpf_cache_refresh_events;
532
533 // It is called as part of pim_neighbor_add
534 // pim_rp_setup ();
535 return 0;
536 }
537
538 void sched_rpf_cache_refresh(struct pim_instance *pim)
539 {
540 ++pim->rpf_cache_refresh_requests;
541
542 pim_rpf_set_refresh_time(pim);
543
544 if (pim->rpf_cache_refresher) {
545 /* Refresh timer is already running */
546 return;
547 }
548
549 /* Start refresh timer */
550
551 if (PIM_DEBUG_ZEBRA) {
552 zlog_debug("%s: triggering %ld msec timer", __PRETTY_FUNCTION__,
553 router->rpf_cache_refresh_delay_msec);
554 }
555
556 thread_add_timer_msec(router->master, on_rpf_cache_refresh, pim,
557 router->rpf_cache_refresh_delay_msec,
558 &pim->rpf_cache_refresher);
559 }
560
561 static void pim_zebra_connected(struct zclient *zclient)
562 {
563 /* Send the client registration */
564 bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER, router->vrf_id);
565
566 zclient_send_reg_requests(zclient, router->vrf_id);
567
568 /* request for VxLAN BUM group addresses */
569 pim_zebra_vxlan_replay();
570 }
571
572 static void pim_zebra_capabilities(struct zclient_capabilities *cap)
573 {
574 router->role = cap->role;
575 }
576
577 void pim_zebra_init(void)
578 {
579 /* Socket for receiving updates from Zebra daemon */
580 zclient = zclient_new(router->master, &zclient_options_default);
581
582 zclient->zebra_capabilities = pim_zebra_capabilities;
583 zclient->zebra_connected = pim_zebra_connected;
584 zclient->router_id_update = pim_router_id_update_zebra;
585 zclient->interface_address_add = pim_zebra_if_address_add;
586 zclient->interface_address_delete = pim_zebra_if_address_del;
587 zclient->interface_vrf_update = pim_zebra_interface_vrf_update;
588 zclient->nexthop_update = pim_parse_nexthop_update;
589 zclient->vxlan_sg_add = pim_zebra_vxlan_sg_proc;
590 zclient->vxlan_sg_del = pim_zebra_vxlan_sg_proc;
591 zclient->mlag_process_up = pim_zebra_mlag_process_up;
592 zclient->mlag_process_down = pim_zebra_mlag_process_down;
593 zclient->mlag_handle_msg = pim_zebra_mlag_handle_msg;
594
595 zclient_init(zclient, ZEBRA_ROUTE_PIM, 0, &pimd_privs);
596 if (PIM_DEBUG_PIM_TRACE) {
597 zlog_notice("%s: zclient socket initialized",
598 __PRETTY_FUNCTION__);
599 }
600
601 zclient_lookup_new();
602 }
603
604 void igmp_anysource_forward_start(struct pim_instance *pim,
605 struct igmp_group *group)
606 {
607 struct igmp_source *source;
608 struct in_addr src_addr = {.s_addr = 0};
609 /* Any source (*,G) is forwarded only if mode is EXCLUDE {empty} */
610 zassert(group->group_filtermode_isexcl);
611 zassert(listcount(group->group_source_list) < 1);
612
613 source = source_new(group, src_addr);
614 if (!source) {
615 zlog_warn("%s: Failure to create * source",
616 __PRETTY_FUNCTION__);
617 return;
618 }
619
620 igmp_source_forward_start(pim, source);
621 }
622
623 void igmp_anysource_forward_stop(struct igmp_group *group)
624 {
625 struct igmp_source *source;
626 struct in_addr star = {.s_addr = 0};
627
628 source = igmp_find_source_by_addr(group, star);
629 if (source)
630 igmp_source_forward_stop(source);
631 }
632
633 static void igmp_source_forward_reevaluate_one(struct pim_instance *pim,
634 struct igmp_source *source)
635 {
636 struct prefix_sg sg;
637 struct igmp_group *group = source->source_group;
638 struct pim_ifchannel *ch;
639
640 if ((source->source_addr.s_addr != INADDR_ANY)
641 || !IGMP_SOURCE_TEST_FORWARDING(source->source_flags))
642 return;
643
644 memset(&sg, 0, sizeof(struct prefix_sg));
645 sg.src = source->source_addr;
646 sg.grp = group->group_addr;
647
648 ch = pim_ifchannel_find(group->group_igmp_sock->interface, &sg);
649 if (pim_is_grp_ssm(pim, group->group_addr)) {
650 /* If SSM group withdraw local membership */
651 if (ch
652 && (ch->local_ifmembership == PIM_IFMEMBERSHIP_INCLUDE)) {
653 if (PIM_DEBUG_PIM_EVENTS)
654 zlog_debug(
655 "local membership del for %s as G is now SSM",
656 pim_str_sg_dump(&sg));
657 pim_ifchannel_local_membership_del(
658 group->group_igmp_sock->interface, &sg);
659 }
660 } else {
661 /* If ASM group add local membership */
662 if (!ch
663 || (ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO)) {
664 if (PIM_DEBUG_PIM_EVENTS)
665 zlog_debug(
666 "local membership add for %s as G is now ASM",
667 pim_str_sg_dump(&sg));
668 pim_ifchannel_local_membership_add(
669 group->group_igmp_sock->interface, &sg);
670 }
671 }
672 }
673
674 void igmp_source_forward_reevaluate_all(struct pim_instance *pim)
675 {
676 struct interface *ifp;
677
678 FOR_ALL_INTERFACES (pim->vrf, ifp) {
679 struct pim_interface *pim_ifp = ifp->info;
680 struct listnode *sock_node;
681 struct igmp_sock *igmp;
682
683 if (!pim_ifp)
684 continue;
685
686 /* scan igmp sockets */
687 for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node,
688 igmp)) {
689 struct listnode *grpnode;
690 struct igmp_group *grp;
691
692 /* scan igmp groups */
693 for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list,
694 grpnode, grp)) {
695 struct listnode *srcnode;
696 struct igmp_source *src;
697
698 /* scan group sources */
699 for (ALL_LIST_ELEMENTS_RO(
700 grp->group_source_list, srcnode,
701 src)) {
702 igmp_source_forward_reevaluate_one(pim,
703 src);
704 } /* scan group sources */
705 } /* scan igmp groups */
706 } /* scan igmp sockets */
707 } /* scan interfaces */
708 }
709
710 void igmp_source_forward_start(struct pim_instance *pim,
711 struct igmp_source *source)
712 {
713 struct pim_interface *pim_oif;
714 struct igmp_group *group;
715 struct prefix_sg sg;
716 int result;
717 int input_iface_vif_index = 0;
718
719 memset(&sg, 0, sizeof(struct prefix_sg));
720 sg.src = source->source_addr;
721 sg.grp = source->source_group->group_addr;
722
723 if (PIM_DEBUG_IGMP_TRACE) {
724 zlog_debug(
725 "%s: (S,G)=%s igmp_sock=%d oif=%s fwd=%d",
726 __PRETTY_FUNCTION__, pim_str_sg_dump(&sg),
727 source->source_group->group_igmp_sock->fd,
728 source->source_group->group_igmp_sock->interface->name,
729 IGMP_SOURCE_TEST_FORWARDING(source->source_flags));
730 }
731
732 /* Prevent IGMP interface from installing multicast route multiple
733 times */
734 if (IGMP_SOURCE_TEST_FORWARDING(source->source_flags)) {
735 return;
736 }
737
738 group = source->source_group;
739 pim_oif = group->group_igmp_sock->interface->info;
740 if (!pim_oif) {
741 if (PIM_DEBUG_IGMP_TRACE) {
742 zlog_debug(
743 "%s: multicast not enabled on oif=%s ?",
744 __PRETTY_FUNCTION__,
745 source->source_group->group_igmp_sock
746 ->interface->name);
747 }
748 return;
749 }
750
751 if (!source->source_channel_oil) {
752 struct in_addr vif_source;
753 struct prefix src, grp;
754 struct pim_nexthop nexthop;
755 struct pim_upstream *up = NULL;
756
757 if (!pim_rp_set_upstream_addr(pim, &vif_source,
758 source->source_addr, sg.grp)) {
759 /*Create a dummy channel oil */
760 source->source_channel_oil = pim_channel_oil_add(
761 pim, &sg, MAXVIFS, __PRETTY_FUNCTION__);
762 }
763
764 else {
765 src.family = AF_INET;
766 src.prefixlen = IPV4_MAX_BITLEN;
767 src.u.prefix4 = vif_source; // RP or Src address
768 grp.family = AF_INET;
769 grp.prefixlen = IPV4_MAX_BITLEN;
770 grp.u.prefix4 = sg.grp;
771
772 up = pim_upstream_find(pim, &sg);
773 if (up) {
774 memcpy(&nexthop, &up->rpf.source_nexthop,
775 sizeof(struct pim_nexthop));
776 pim_ecmp_nexthop_lookup(pim, &nexthop, &src,
777 &grp, 0);
778 if (nexthop.interface)
779 input_iface_vif_index =
780 pim_if_find_vifindex_by_ifindex(
781 pim,
782 nexthop.interface->ifindex);
783 } else
784 input_iface_vif_index =
785 pim_ecmp_fib_lookup_if_vif_index(
786 pim, &src, &grp);
787
788 if (PIM_DEBUG_ZEBRA) {
789 char buf2[INET_ADDRSTRLEN];
790
791 pim_inet4_dump("<source?>", vif_source, buf2,
792 sizeof(buf2));
793 zlog_debug("%s: NHT %s vif_source %s vif_index:%d ",
794 __PRETTY_FUNCTION__,
795 pim_str_sg_dump(&sg),
796 buf2, input_iface_vif_index);
797 }
798
799 if (input_iface_vif_index < 1) {
800 if (PIM_DEBUG_IGMP_TRACE) {
801 char source_str[INET_ADDRSTRLEN];
802 pim_inet4_dump("<source?>",
803 source->source_addr,
804 source_str, sizeof(source_str));
805 zlog_debug(
806 "%s %s: could not find input interface for source %s",
807 __FILE__, __PRETTY_FUNCTION__,
808 source_str);
809 }
810 source->source_channel_oil =
811 pim_channel_oil_add(
812 pim, &sg, MAXVIFS,
813 __PRETTY_FUNCTION__);
814 }
815
816 else {
817 /*
818 * Protect IGMP against adding looped MFC
819 * entries created by both source and receiver
820 * attached to the same interface. See TODO
821 * T22. Block only when the intf is non DR
822 * DR must create upstream.
823 */
824 if ((input_iface_vif_index ==
825 pim_oif->mroute_vif_index) &&
826 !(PIM_I_am_DR(pim_oif))) {
827 /* ignore request for looped MFC entry
828 */
829 if (PIM_DEBUG_IGMP_TRACE) {
830 zlog_debug(
831 "%s: ignoring request for looped MFC entry (S,G)=%s: igmp_sock=%d oif=%s vif_index=%d",
832 __PRETTY_FUNCTION__,
833 pim_str_sg_dump(&sg),
834 source->source_group
835 ->group_igmp_sock->fd,
836 source->source_group
837 ->group_igmp_sock
838 ->interface->name,
839 input_iface_vif_index);
840 }
841 return;
842 }
843
844 source->source_channel_oil =
845 pim_channel_oil_add(
846 pim, &sg, input_iface_vif_index,
847 __PRETTY_FUNCTION__);
848 if (!source->source_channel_oil) {
849 if (PIM_DEBUG_IGMP_TRACE) {
850 zlog_debug(
851 "%s %s: could not create OIL for channel (S,G)=%s",
852 __FILE__,
853 __PRETTY_FUNCTION__,
854 pim_str_sg_dump(&sg));
855 }
856 return;
857 }
858 }
859 }
860 }
861
862 if (PIM_I_am_DR(pim_oif)) {
863 result = pim_channel_add_oif(source->source_channel_oil,
864 group->group_igmp_sock->interface,
865 PIM_OIF_FLAG_PROTO_IGMP);
866 if (result) {
867 if (PIM_DEBUG_MROUTE) {
868 zlog_warn("%s: add_oif() failed with return=%d",
869 __func__, result);
870 }
871 return;
872 }
873 } else {
874 if (PIM_DEBUG_IGMP_TRACE)
875 zlog_debug("%s: %s was received on %s interface but we are not DR for that interface",
876 __PRETTY_FUNCTION__,
877 pim_str_sg_dump(&sg),
878 group->group_igmp_sock->interface->name);
879
880 return;
881 }
882 /*
883 Feed IGMPv3-gathered local membership information into PIM
884 per-interface (S,G) state.
885 */
886 if (!pim_ifchannel_local_membership_add(
887 group->group_igmp_sock->interface, &sg)) {
888 if (PIM_DEBUG_MROUTE)
889 zlog_warn("%s: Failure to add local membership for %s",
890 __PRETTY_FUNCTION__, pim_str_sg_dump(&sg));
891
892 pim_channel_del_oif(source->source_channel_oil,
893 group->group_igmp_sock->interface,
894 PIM_OIF_FLAG_PROTO_IGMP);
895 return;
896 }
897
898 IGMP_SOURCE_DO_FORWARDING(source->source_flags);
899 }
900
901 /*
902 igmp_source_forward_stop: stop fowarding, but keep the source
903 igmp_source_delete: stop fowarding, and delete the source
904 */
905 void igmp_source_forward_stop(struct igmp_source *source)
906 {
907 struct igmp_group *group;
908 struct prefix_sg sg;
909 int result;
910
911 memset(&sg, 0, sizeof(struct prefix_sg));
912 sg.src = source->source_addr;
913 sg.grp = source->source_group->group_addr;
914
915 if (PIM_DEBUG_IGMP_TRACE) {
916 zlog_debug(
917 "%s: (S,G)=%s igmp_sock=%d oif=%s fwd=%d",
918 __PRETTY_FUNCTION__, pim_str_sg_dump(&sg),
919 source->source_group->group_igmp_sock->fd,
920 source->source_group->group_igmp_sock->interface->name,
921 IGMP_SOURCE_TEST_FORWARDING(source->source_flags));
922 }
923
924 /* Prevent IGMP interface from removing multicast route multiple
925 times */
926 if (!IGMP_SOURCE_TEST_FORWARDING(source->source_flags)) {
927 return;
928 }
929
930 group = source->source_group;
931
932 /*
933 It appears that in certain circumstances that
934 igmp_source_forward_stop is called when IGMP forwarding
935 was not enabled in oif_flags for this outgoing interface.
936 Possibly because of multiple calls. When that happens, we
937 enter the below if statement and this function returns early
938 which in turn triggers the calling function to assert.
939 Making the call to pim_channel_del_oif and ignoring the return code
940 fixes the issue without ill effect, similar to
941 pim_forward_stop below.
942 */
943 result = pim_channel_del_oif(source->source_channel_oil,
944 group->group_igmp_sock->interface,
945 PIM_OIF_FLAG_PROTO_IGMP);
946 if (result) {
947 if (PIM_DEBUG_IGMP_TRACE)
948 zlog_debug(
949 "%s: pim_channel_del_oif() failed with return=%d",
950 __func__, result);
951 return;
952 }
953
954 /*
955 Feed IGMPv3-gathered local membership information into PIM
956 per-interface (S,G) state.
957 */
958 pim_ifchannel_local_membership_del(group->group_igmp_sock->interface,
959 &sg);
960
961 IGMP_SOURCE_DONT_FORWARDING(source->source_flags);
962 }
963
964 void pim_forward_start(struct pim_ifchannel *ch)
965 {
966 struct pim_upstream *up = ch->upstream;
967 uint32_t mask = PIM_OIF_FLAG_PROTO_PIM;
968
969 if (PIM_DEBUG_PIM_TRACE) {
970 char source_str[INET_ADDRSTRLEN];
971 char group_str[INET_ADDRSTRLEN];
972 char upstream_str[INET_ADDRSTRLEN];
973
974 pim_inet4_dump("<source?>", ch->sg.src, source_str,
975 sizeof(source_str));
976 pim_inet4_dump("<group?>", ch->sg.grp, group_str,
977 sizeof(group_str));
978 pim_inet4_dump("<upstream?>", up->upstream_addr, upstream_str,
979 sizeof(upstream_str));
980 zlog_debug("%s: (S,G)=(%s,%s) oif=%s (%s)", __PRETTY_FUNCTION__,
981 source_str, group_str, ch->interface->name,
982 inet_ntoa(up->upstream_addr));
983 }
984
985 if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP)
986 mask = PIM_OIF_FLAG_PROTO_IGMP;
987
988 pim_channel_add_oif(up->channel_oil, ch->interface, mask);
989 }
990
991 void pim_forward_stop(struct pim_ifchannel *ch, bool install_it)
992 {
993 struct pim_upstream *up = ch->upstream;
994
995 if (PIM_DEBUG_PIM_TRACE) {
996 zlog_debug("%s: (S,G)=%s oif=%s install_it: %d installed: %d",
997 __PRETTY_FUNCTION__, ch->sg_str, ch->interface->name,
998 install_it, up->channel_oil->installed);
999 }
1000
1001 /*
1002 * If a channel is being removed, check to see if we still need
1003 * to inherit the interface. If so make sure it is added in
1004 */
1005 if (pim_upstream_evaluate_join_desired_interface(up, ch, ch->parent))
1006 pim_channel_add_oif(up->channel_oil, ch->interface,
1007 PIM_OIF_FLAG_PROTO_PIM);
1008 else
1009 pim_channel_del_oif(up->channel_oil, ch->interface,
1010 PIM_OIF_FLAG_PROTO_PIM);
1011
1012 if (install_it && !up->channel_oil->installed)
1013 pim_mroute_add(up->channel_oil, __PRETTY_FUNCTION__);
1014 }
1015
1016 void pim_zebra_zclient_update(struct vty *vty)
1017 {
1018 vty_out(vty, "Zclient update socket: ");
1019
1020 if (zclient) {
1021 vty_out(vty, "%d failures=%d\n", zclient->sock, zclient->fail);
1022 } else {
1023 vty_out(vty, "<null zclient>\n");
1024 }
1025 }
1026
1027 struct zclient *pim_zebra_zclient_get(void)
1028 {
1029 if (zclient)
1030 return zclient;
1031 else
1032 return NULL;
1033 }
1034
1035 void pim_zebra_interface_set_master(struct interface *vrf,
1036 struct interface *ifp)
1037 {
1038 zclient_interface_set_master(zclient, vrf, ifp);
1039 }