]> git.proxmox.com Git - mirror_frr.git/blob - pimd/pim_zebra.c
*: Switch all zclient->interface_add to interface create callback
[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_if_del(ZAPI_CALLBACK_ARGS)
67 {
68 struct interface *ifp;
69 struct pim_instance *pim;
70
71 ifp = zebra_interface_state_read(zclient->ibuf, vrf_id);
72 if (!ifp)
73 return 0;
74
75 if (PIM_DEBUG_ZEBRA) {
76 zlog_debug(
77 "%s: %s index %d(%u) flags %ld metric %d mtu %d operative %d",
78 __PRETTY_FUNCTION__, ifp->name, ifp->ifindex, vrf_id,
79 (long)ifp->flags, ifp->metric, ifp->mtu,
80 if_is_operative(ifp));
81 }
82
83 if (!if_is_operative(ifp))
84 pim_if_addr_del_all(ifp);
85
86 if_set_index(ifp, IFINDEX_INTERNAL);
87
88 pim = pim_get_pim_instance(vrf_id);
89 if (pim && pim->vxlan.term_if == ifp)
90 pim_vxlan_del_term_dev(pim);
91
92 return 0;
93 }
94
95 static int pim_zebra_if_state_up(ZAPI_CALLBACK_ARGS)
96 {
97 struct pim_instance *pim;
98 struct interface *ifp;
99 uint32_t table_id;
100
101 /*
102 zebra api notifies interface up/down events by using the same call
103 zebra_interface_state_read below, see comments in lib/zclient.c
104 */
105 ifp = zebra_interface_state_read(zclient->ibuf, vrf_id);
106 if (!ifp)
107 return 0;
108
109 if (PIM_DEBUG_ZEBRA) {
110 zlog_debug(
111 "%s: %s index %d(%u) flags %ld metric %d mtu %d operative %d",
112 __PRETTY_FUNCTION__, ifp->name, ifp->ifindex, vrf_id,
113 (long)ifp->flags, ifp->metric, ifp->mtu,
114 if_is_operative(ifp));
115 }
116
117 pim = pim_get_pim_instance(vrf_id);
118 if (if_is_operative(ifp)) {
119 struct pim_interface *pim_ifp;
120
121 pim_ifp = ifp->info;
122 /*
123 * If we have a pim_ifp already and this is an if_add
124 * that means that we probably have a vrf move event
125 * If that is the case, set the proper vrfness.
126 */
127 if (pim_ifp)
128 pim_ifp->pim = pim;
129
130 /*
131 pim_if_addr_add_all() suffices for bringing up both IGMP and
132 PIM
133 */
134 pim_if_addr_add_all(ifp);
135 }
136
137 /*
138 * If we have a pimreg device callback and it's for a specific
139 * table set the master appropriately
140 */
141 if (sscanf(ifp->name, "pimreg%" SCNu32, &table_id) == 1) {
142 struct vrf *vrf;
143 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
144 if ((table_id == vrf->data.l.table_id)
145 && (ifp->vrf_id != vrf->vrf_id)) {
146 struct interface *master = if_lookup_by_name(
147 vrf->name, vrf->vrf_id);
148
149 if (!master) {
150 zlog_debug(
151 "%s: Unable to find Master interface for %s",
152 __PRETTY_FUNCTION__, vrf->name);
153 return 0;
154 }
155 zclient_interface_set_master(zclient, master,
156 ifp);
157 }
158 }
159 }
160 return 0;
161 }
162
163 static int pim_zebra_if_state_down(ZAPI_CALLBACK_ARGS)
164 {
165 struct interface *ifp;
166
167 /*
168 zebra api notifies interface up/down events by using the same call
169 zebra_interface_state_read below, see comments in lib/zclient.c
170 */
171 ifp = zebra_interface_state_read(zclient->ibuf, vrf_id);
172 if (!ifp)
173 return 0;
174
175 if (PIM_DEBUG_ZEBRA) {
176 zlog_debug(
177 "%s: %s index %d(%u) flags %ld metric %d mtu %d operative %d",
178 __PRETTY_FUNCTION__, ifp->name, ifp->ifindex, vrf_id,
179 (long)ifp->flags, ifp->metric, ifp->mtu,
180 if_is_operative(ifp));
181 }
182
183 if (!if_is_operative(ifp)) {
184 pim_ifchannel_delete_all(ifp);
185 /*
186 pim_if_addr_del_all() suffices for shutting down IGMP,
187 but not for shutting down PIM
188 */
189 pim_if_addr_del_all(ifp);
190
191 /*
192 pim_sock_delete() closes the socket, stops read and timer
193 threads,
194 and kills all neighbors.
195 */
196 if (ifp->info) {
197 pim_sock_delete(ifp, "link down");
198 }
199 }
200
201 if (ifp->info)
202 pim_if_del_vif(ifp);
203
204 return 0;
205 }
206
207 static int pim_zebra_interface_vrf_update(ZAPI_CALLBACK_ARGS)
208 {
209 struct interface *ifp;
210 vrf_id_t new_vrf_id;
211
212 ifp = zebra_interface_vrf_update_read(zclient->ibuf, vrf_id,
213 &new_vrf_id);
214 if (!ifp)
215 return 0;
216
217 if (PIM_DEBUG_ZEBRA)
218 zlog_debug("%s: %s updating from %u to %u",
219 __PRETTY_FUNCTION__,
220 ifp->name, vrf_id, new_vrf_id);
221
222 if_update_to_new_vrf(ifp, new_vrf_id);
223
224 return 0;
225 }
226
227 #ifdef PIM_DEBUG_IFADDR_DUMP
228 static void dump_if_address(struct interface *ifp)
229 {
230 struct connected *ifc;
231 struct listnode *node;
232
233 zlog_debug("%s %s: interface %s addresses:", __FILE__,
234 __PRETTY_FUNCTION__, ifp->name);
235
236 for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) {
237 struct prefix *p = ifc->address;
238
239 if (p->family != AF_INET)
240 continue;
241
242 zlog_debug("%s %s: interface %s address %s %s", __FILE__,
243 __PRETTY_FUNCTION__, ifp->name,
244 inet_ntoa(p->u.prefix4),
245 CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY)
246 ? "secondary"
247 : "primary");
248 }
249 }
250 #endif
251
252 static int pim_zebra_if_address_add(ZAPI_CALLBACK_ARGS)
253 {
254 struct connected *c;
255 struct prefix *p;
256 struct pim_interface *pim_ifp;
257 struct pim_instance *pim;
258
259 /*
260 zebra api notifies address adds/dels events by using the same call
261 interface_add_read below, see comments in lib/zclient.c
262
263 zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_ADD, ...)
264 will add address to interface list by calling
265 connected_add_by_prefix()
266 */
267 c = zebra_interface_address_read(cmd, zclient->ibuf, vrf_id);
268 if (!c)
269 return 0;
270
271 pim_ifp = c->ifp->info;
272 p = c->address;
273
274 if (PIM_DEBUG_ZEBRA) {
275 char buf[BUFSIZ];
276 prefix2str(p, buf, BUFSIZ);
277 zlog_debug("%s: %s(%u) connected IP address %s flags %u %s",
278 __PRETTY_FUNCTION__, c->ifp->name, vrf_id, buf,
279 c->flags,
280 CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY)
281 ? "secondary"
282 : "primary");
283
284 #ifdef PIM_DEBUG_IFADDR_DUMP
285 dump_if_address(c->ifp);
286 #endif
287 }
288
289 if (!CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY)) {
290 /* trying to add primary address */
291
292 struct in_addr primary_addr = pim_find_primary_addr(c->ifp);
293 if (p->family != AF_INET
294 || primary_addr.s_addr != p->u.prefix4.s_addr) {
295 if (PIM_DEBUG_ZEBRA) {
296 /* but we had a primary address already */
297
298 char buf[BUFSIZ];
299
300 prefix2str(p, buf, BUFSIZ);
301
302 zlog_warn(
303 "%s: %s : forcing secondary flag on %s",
304 __PRETTY_FUNCTION__, c->ifp->name, buf);
305 }
306 SET_FLAG(c->flags, ZEBRA_IFA_SECONDARY);
307 }
308 }
309
310 pim_if_addr_add(c);
311 if (pim_ifp) {
312 pim = pim_get_pim_instance(vrf_id);
313 pim_ifp->pim = pim;
314
315 pim_rp_check_on_if_add(pim_ifp);
316 }
317
318 if (if_is_loopback(c->ifp)) {
319 struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
320 struct interface *ifp;
321
322 FOR_ALL_INTERFACES (vrf, ifp) {
323 if (!if_is_loopback(ifp) && if_is_operative(ifp))
324 pim_if_addr_add_all(ifp);
325 }
326 }
327
328 return 0;
329 }
330
331 static int pim_zebra_if_address_del(ZAPI_CALLBACK_ARGS)
332 {
333 struct connected *c;
334 struct prefix *p;
335 struct vrf *vrf = vrf_lookup_by_id(vrf_id);
336 struct pim_instance *pim;
337
338 if (!vrf)
339 return 0;
340 pim = vrf->info;
341
342 /*
343 zebra api notifies address adds/dels events by using the same call
344 interface_add_read below, see comments in lib/zclient.c
345
346 zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_DELETE, ...)
347 will remove address from interface list by calling
348 connected_delete_by_prefix()
349 */
350 c = zebra_interface_address_read(cmd, zclient->ibuf, vrf_id);
351 if (!c)
352 return 0;
353
354 p = c->address;
355 if (p->family == AF_INET) {
356 if (PIM_DEBUG_ZEBRA) {
357 char buf[BUFSIZ];
358 prefix2str(p, buf, BUFSIZ);
359 zlog_debug(
360 "%s: %s(%u) disconnected IP address %s flags %u %s",
361 __PRETTY_FUNCTION__, c->ifp->name, vrf_id, buf,
362 c->flags,
363 CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY)
364 ? "secondary"
365 : "primary");
366
367 #ifdef PIM_DEBUG_IFADDR_DUMP
368 dump_if_address(c->ifp);
369 #endif
370 }
371
372 pim_if_addr_del(c, 0);
373 pim_rp_setup(pim);
374 pim_i_am_rp_re_evaluate(pim);
375 }
376
377 connected_free(c);
378 return 0;
379 }
380
381 void pim_zebra_update_all_interfaces(struct pim_instance *pim)
382 {
383 struct interface *ifp;
384
385 FOR_ALL_INTERFACES (pim->vrf, ifp) {
386 struct pim_interface *pim_ifp = ifp->info;
387 struct pim_iface_upstream_switch *us;
388 struct listnode *node;
389
390 if (!pim_ifp)
391 continue;
392
393 for (ALL_LIST_ELEMENTS_RO(pim_ifp->upstream_switch_list, node,
394 us)) {
395 struct pim_rpf rpf;
396
397 rpf.source_nexthop.interface = ifp;
398 rpf.rpf_addr.u.prefix4 = us->address;
399 pim_joinprune_send(&rpf, us->us);
400 pim_jp_agg_clear_group(us->us);
401 }
402 }
403 }
404
405 void pim_zebra_upstream_rpf_changed(struct pim_instance *pim,
406 struct pim_upstream *up,
407 struct pim_rpf *old)
408 {
409 if (old->source_nexthop.interface) {
410 struct pim_neighbor *nbr;
411
412 nbr = pim_neighbor_find(old->source_nexthop.interface,
413 old->rpf_addr.u.prefix4);
414 if (nbr)
415 pim_jp_agg_remove_group(nbr->upstream_jp_agg, up);
416
417 /*
418 * We have detected a case where we might need
419 * to rescan the inherited o_list so do it.
420 */
421 if (up->channel_oil->oil_inherited_rescan) {
422 pim_upstream_inherited_olist_decide(pim, up);
423 up->channel_oil->oil_inherited_rescan = 0;
424 }
425
426 if (up->join_state == PIM_UPSTREAM_JOINED) {
427 /*
428 * If we come up real fast we can be here
429 * where the mroute has not been installed
430 * so install it.
431 */
432 if (!up->channel_oil->installed)
433 pim_mroute_add(up->channel_oil,
434 __PRETTY_FUNCTION__);
435
436 /*
437 * RFC 4601: 4.5.7. Sending (S,G)
438 * Join/Prune Messages
439 *
440 * Transitions from Joined State
441 *
442 * RPF'(S,G) changes not due to an Assert
443 *
444 * The upstream (S,G) state machine remains
445 * in Joined state. Send Join(S,G) to the new
446 * upstream neighbor, which is the new value
447 * of RPF'(S,G). Send Prune(S,G) to the old
448 * upstream neighbor, which is the old value
449 * of RPF'(S,G). Set the Join Timer (JT) to
450 * expire after t_periodic seconds.
451 */
452 pim_jp_agg_switch_interface(old, &up->rpf, up);
453
454 pim_upstream_join_timer_restart(up, old);
455 } /* up->join_state == PIM_UPSTREAM_JOINED */
456 }
457
458 else {
459 /*
460 * We have detected a case where we might need
461 * to rescan the inherited o_list so do it.
462 */
463 if (up->channel_oil->oil_inherited_rescan) {
464 pim_upstream_inherited_olist_decide(pim, up);
465 up->channel_oil->oil_inherited_rescan = 0;
466 }
467
468 if (!up->channel_oil->installed)
469 pim_mroute_add(up->channel_oil, __PRETTY_FUNCTION__);
470 }
471
472 /* FIXME can join_desired actually be changed by pim_rpf_update()
473 * returning PIM_RPF_CHANGED ?
474 */
475 pim_upstream_update_join_desired(pim, up);
476 }
477
478 static int pim_zebra_vxlan_sg_proc(ZAPI_CALLBACK_ARGS)
479 {
480 struct stream *s;
481 struct pim_instance *pim;
482 struct prefix_sg sg;
483
484 pim = pim_get_pim_instance(vrf_id);
485 if (!pim)
486 return 0;
487
488 s = zclient->ibuf;
489
490 sg.family = AF_INET;
491 sg.prefixlen = stream_getl(s);
492 stream_get(&sg.src.s_addr, s, sg.prefixlen);
493 stream_get(&sg.grp.s_addr, s, sg.prefixlen);
494
495 if (PIM_DEBUG_ZEBRA) {
496 char sg_str[PIM_SG_LEN];
497
498 pim_str_sg_set(&sg, sg_str);
499 zlog_debug("%u:recv SG %s %s", vrf_id,
500 (cmd == ZEBRA_VXLAN_SG_ADD)?"add":"del",
501 sg_str);
502 }
503
504 if (cmd == ZEBRA_VXLAN_SG_ADD)
505 pim_vxlan_sg_add(pim, &sg);
506 else
507 pim_vxlan_sg_del(pim, &sg);
508
509 return 0;
510 }
511
512 static void pim_zebra_vxlan_replay(void)
513 {
514 struct stream *s = NULL;
515
516 /* Check socket. */
517 if (!zclient || zclient->sock < 0)
518 return;
519
520 s = zclient->obuf;
521 stream_reset(s);
522
523 zclient_create_header(s, ZEBRA_VXLAN_SG_REPLAY, VRF_DEFAULT);
524 stream_putw_at(s, 0, stream_get_endp(s));
525
526 zclient_send_message(zclient);
527 }
528
529 void pim_scan_individual_oil(struct channel_oil *c_oil, int in_vif_index)
530 {
531 struct in_addr vif_source;
532 int input_iface_vif_index;
533
534 pim_rp_set_upstream_addr(c_oil->pim, &vif_source,
535 c_oil->oil.mfcc_origin,
536 c_oil->oil.mfcc_mcastgrp);
537
538 if (in_vif_index)
539 input_iface_vif_index = in_vif_index;
540 else {
541 struct prefix src, grp;
542
543 src.family = AF_INET;
544 src.prefixlen = IPV4_MAX_BITLEN;
545 src.u.prefix4 = vif_source;
546 grp.family = AF_INET;
547 grp.prefixlen = IPV4_MAX_BITLEN;
548 grp.u.prefix4 = c_oil->oil.mfcc_mcastgrp;
549
550 if (PIM_DEBUG_ZEBRA) {
551 char source_str[INET_ADDRSTRLEN];
552 char group_str[INET_ADDRSTRLEN];
553 pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin,
554 source_str, sizeof(source_str));
555 pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp,
556 group_str, sizeof(group_str));
557 zlog_debug(
558 "%s: channel_oil (%s,%s) upstream info is not present.",
559 __PRETTY_FUNCTION__, source_str, group_str);
560 }
561 input_iface_vif_index = pim_ecmp_fib_lookup_if_vif_index(
562 c_oil->pim, &src, &grp);
563 }
564
565 if (input_iface_vif_index < 1) {
566 if (PIM_DEBUG_ZEBRA) {
567 char source_str[INET_ADDRSTRLEN];
568 char group_str[INET_ADDRSTRLEN];
569 pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin,
570 source_str, sizeof(source_str));
571 pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp,
572 group_str, sizeof(group_str));
573 zlog_debug(
574 "%s %s: could not find input interface(%d) for (S,G)=(%s,%s)",
575 __FILE__, __PRETTY_FUNCTION__,
576 c_oil->oil.mfcc_parent, source_str, group_str);
577 }
578 pim_mroute_del(c_oil, __PRETTY_FUNCTION__);
579 return;
580 }
581
582 if (input_iface_vif_index == c_oil->oil.mfcc_parent) {
583 if (!c_oil->installed)
584 pim_mroute_add(c_oil, __PRETTY_FUNCTION__);
585
586 /* RPF unchanged */
587 return;
588 }
589
590 if (PIM_DEBUG_ZEBRA) {
591 struct interface *old_iif = pim_if_find_by_vif_index(
592 c_oil->pim, c_oil->oil.mfcc_parent);
593 struct interface *new_iif = pim_if_find_by_vif_index(
594 c_oil->pim, input_iface_vif_index);
595 char source_str[INET_ADDRSTRLEN];
596 char group_str[INET_ADDRSTRLEN];
597 pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str,
598 sizeof(source_str));
599 pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str,
600 sizeof(group_str));
601 zlog_debug(
602 "%s %s: (S,G)=(%s,%s) input interface changed from %s vif_index=%d to %s vif_index=%d",
603 __FILE__, __PRETTY_FUNCTION__, source_str, group_str,
604 (old_iif) ? old_iif->name : "<old_iif?>",
605 c_oil->oil.mfcc_parent,
606 (new_iif) ? new_iif->name : "<new_iif?>",
607 input_iface_vif_index);
608 }
609
610 /* new iif loops to existing oif ? */
611 if (c_oil->oil.mfcc_ttls[input_iface_vif_index]) {
612 struct interface *new_iif = pim_if_find_by_vif_index(
613 c_oil->pim, input_iface_vif_index);
614
615 if (PIM_DEBUG_ZEBRA) {
616 char source_str[INET_ADDRSTRLEN];
617 char group_str[INET_ADDRSTRLEN];
618 pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin,
619 source_str, sizeof(source_str));
620 pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp,
621 group_str, sizeof(group_str));
622 zlog_debug(
623 "%s %s: (S,G)=(%s,%s) new iif loops to existing oif: %s vif_index=%d",
624 __FILE__, __PRETTY_FUNCTION__, source_str,
625 group_str,
626 (new_iif) ? new_iif->name : "<new_iif?>",
627 input_iface_vif_index);
628 }
629 }
630
631 /* update iif vif_index */
632 pim_channel_oil_change_iif(c_oil->pim, c_oil, input_iface_vif_index,
633 __PRETTY_FUNCTION__);
634 pim_mroute_add(c_oil, __PRETTY_FUNCTION__);
635 }
636
637 void pim_scan_oil(struct pim_instance *pim)
638 {
639 struct listnode *node;
640 struct listnode *nextnode;
641 struct channel_oil *c_oil;
642 ifindex_t ifindex;
643 int vif_index = 0;
644
645 pim->scan_oil_last = pim_time_monotonic_sec();
646 ++pim->scan_oil_events;
647
648 for (ALL_LIST_ELEMENTS(pim->channel_oil_list, node, nextnode, c_oil)) {
649 if (c_oil->up && c_oil->up->rpf.source_nexthop.interface) {
650 ifindex = c_oil->up->rpf.source_nexthop
651 .interface->ifindex;
652 vif_index =
653 pim_if_find_vifindex_by_ifindex(pim, ifindex);
654 /* Pass Current selected NH vif index to mroute
655 * download */
656 if (vif_index)
657 pim_scan_individual_oil(c_oil, vif_index);
658 } else
659 pim_scan_individual_oil(c_oil, 0);
660 }
661 }
662
663 static int on_rpf_cache_refresh(struct thread *t)
664 {
665 struct pim_instance *pim = THREAD_ARG(t);
666
667 /* update kernel multicast forwarding cache (MFC) */
668 pim_scan_oil(pim);
669
670 pim->rpf_cache_refresh_last = pim_time_monotonic_sec();
671 ++pim->rpf_cache_refresh_events;
672
673 // It is called as part of pim_neighbor_add
674 // pim_rp_setup ();
675 return 0;
676 }
677
678 void sched_rpf_cache_refresh(struct pim_instance *pim)
679 {
680 ++pim->rpf_cache_refresh_requests;
681
682 pim_rpf_set_refresh_time(pim);
683
684 if (pim->rpf_cache_refresher) {
685 /* Refresh timer is already running */
686 return;
687 }
688
689 /* Start refresh timer */
690
691 if (PIM_DEBUG_ZEBRA) {
692 zlog_debug("%s: triggering %ld msec timer", __PRETTY_FUNCTION__,
693 router->rpf_cache_refresh_delay_msec);
694 }
695
696 thread_add_timer_msec(router->master, on_rpf_cache_refresh, pim,
697 router->rpf_cache_refresh_delay_msec,
698 &pim->rpf_cache_refresher);
699 }
700
701 static void pim_zebra_connected(struct zclient *zclient)
702 {
703 /* Send the client registration */
704 bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER, router->vrf_id);
705
706 zclient_send_reg_requests(zclient, router->vrf_id);
707
708 /* request for VxLAN BUM group addresses */
709 pim_zebra_vxlan_replay();
710 }
711
712 static void pim_zebra_capabilities(struct zclient_capabilities *cap)
713 {
714 router->role = cap->role;
715 }
716
717 void pim_zebra_init(void)
718 {
719 /* Socket for receiving updates from Zebra daemon */
720 zclient = zclient_new(router->master, &zclient_options_default);
721
722 zclient->zebra_capabilities = pim_zebra_capabilities;
723 zclient->zebra_connected = pim_zebra_connected;
724 zclient->router_id_update = pim_router_id_update_zebra;
725 zclient->interface_delete = pim_zebra_if_del;
726 zclient->interface_up = pim_zebra_if_state_up;
727 zclient->interface_down = pim_zebra_if_state_down;
728 zclient->interface_address_add = pim_zebra_if_address_add;
729 zclient->interface_address_delete = pim_zebra_if_address_del;
730 zclient->interface_vrf_update = pim_zebra_interface_vrf_update;
731 zclient->nexthop_update = pim_parse_nexthop_update;
732 zclient->vxlan_sg_add = pim_zebra_vxlan_sg_proc;
733 zclient->vxlan_sg_del = pim_zebra_vxlan_sg_proc;
734
735 zclient_init(zclient, ZEBRA_ROUTE_PIM, 0, &pimd_privs);
736 if (PIM_DEBUG_PIM_TRACE) {
737 zlog_notice("%s: zclient socket initialized",
738 __PRETTY_FUNCTION__);
739 }
740
741 zclient_lookup_new();
742 }
743
744 void igmp_anysource_forward_start(struct pim_instance *pim,
745 struct igmp_group *group)
746 {
747 struct igmp_source *source;
748 struct in_addr src_addr = {.s_addr = 0};
749 /* Any source (*,G) is forwarded only if mode is EXCLUDE {empty} */
750 zassert(group->group_filtermode_isexcl);
751 zassert(listcount(group->group_source_list) < 1);
752
753 source = source_new(group, src_addr);
754 if (!source) {
755 zlog_warn("%s: Failure to create * source",
756 __PRETTY_FUNCTION__);
757 return;
758 }
759
760 igmp_source_forward_start(pim, source);
761 }
762
763 void igmp_anysource_forward_stop(struct igmp_group *group)
764 {
765 struct igmp_source *source;
766 struct in_addr star = {.s_addr = 0};
767
768 source = igmp_find_source_by_addr(group, star);
769 if (source)
770 igmp_source_forward_stop(source);
771 }
772
773 static void igmp_source_forward_reevaluate_one(struct pim_instance *pim,
774 struct igmp_source *source)
775 {
776 struct prefix_sg sg;
777 struct igmp_group *group = source->source_group;
778 struct pim_ifchannel *ch;
779
780 if ((source->source_addr.s_addr != INADDR_ANY)
781 || !IGMP_SOURCE_TEST_FORWARDING(source->source_flags))
782 return;
783
784 memset(&sg, 0, sizeof(struct prefix_sg));
785 sg.src = source->source_addr;
786 sg.grp = group->group_addr;
787
788 ch = pim_ifchannel_find(group->group_igmp_sock->interface, &sg);
789 if (pim_is_grp_ssm(pim, group->group_addr)) {
790 /* If SSM group withdraw local membership */
791 if (ch
792 && (ch->local_ifmembership == PIM_IFMEMBERSHIP_INCLUDE)) {
793 if (PIM_DEBUG_PIM_EVENTS)
794 zlog_debug(
795 "local membership del for %s as G is now SSM",
796 pim_str_sg_dump(&sg));
797 pim_ifchannel_local_membership_del(
798 group->group_igmp_sock->interface, &sg);
799 }
800 } else {
801 /* If ASM group add local membership */
802 if (!ch
803 || (ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO)) {
804 if (PIM_DEBUG_PIM_EVENTS)
805 zlog_debug(
806 "local membership add for %s as G is now ASM",
807 pim_str_sg_dump(&sg));
808 pim_ifchannel_local_membership_add(
809 group->group_igmp_sock->interface, &sg);
810 }
811 }
812 }
813
814 void igmp_source_forward_reevaluate_all(struct pim_instance *pim)
815 {
816 struct interface *ifp;
817
818 FOR_ALL_INTERFACES (pim->vrf, ifp) {
819 struct pim_interface *pim_ifp = ifp->info;
820 struct listnode *sock_node;
821 struct igmp_sock *igmp;
822
823 if (!pim_ifp)
824 continue;
825
826 /* scan igmp sockets */
827 for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node,
828 igmp)) {
829 struct listnode *grpnode;
830 struct igmp_group *grp;
831
832 /* scan igmp groups */
833 for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list,
834 grpnode, grp)) {
835 struct listnode *srcnode;
836 struct igmp_source *src;
837
838 /* scan group sources */
839 for (ALL_LIST_ELEMENTS_RO(
840 grp->group_source_list, srcnode,
841 src)) {
842 igmp_source_forward_reevaluate_one(pim,
843 src);
844 } /* scan group sources */
845 } /* scan igmp groups */
846 } /* scan igmp sockets */
847 } /* scan interfaces */
848 }
849
850 void igmp_source_forward_start(struct pim_instance *pim,
851 struct igmp_source *source)
852 {
853 struct pim_interface *pim_oif;
854 struct igmp_group *group;
855 struct prefix_sg sg;
856 int result;
857 int input_iface_vif_index = 0;
858
859 memset(&sg, 0, sizeof(struct prefix_sg));
860 sg.src = source->source_addr;
861 sg.grp = source->source_group->group_addr;
862
863 if (PIM_DEBUG_IGMP_TRACE) {
864 zlog_debug(
865 "%s: (S,G)=%s igmp_sock=%d oif=%s fwd=%d",
866 __PRETTY_FUNCTION__, pim_str_sg_dump(&sg),
867 source->source_group->group_igmp_sock->fd,
868 source->source_group->group_igmp_sock->interface->name,
869 IGMP_SOURCE_TEST_FORWARDING(source->source_flags));
870 }
871
872 /* Prevent IGMP interface from installing multicast route multiple
873 times */
874 if (IGMP_SOURCE_TEST_FORWARDING(source->source_flags)) {
875 return;
876 }
877
878 group = source->source_group;
879 pim_oif = group->group_igmp_sock->interface->info;
880 if (!pim_oif) {
881 if (PIM_DEBUG_IGMP_TRACE) {
882 zlog_debug(
883 "%s: multicast not enabled on oif=%s ?",
884 __PRETTY_FUNCTION__,
885 source->source_group->group_igmp_sock
886 ->interface->name);
887 }
888 return;
889 }
890
891 if (!source->source_channel_oil) {
892 struct in_addr vif_source;
893 struct prefix src, grp;
894 struct pim_nexthop nexthop;
895 struct pim_upstream *up = NULL;
896
897 if (!pim_rp_set_upstream_addr(pim, &vif_source,
898 source->source_addr, sg.grp)) {
899 /*Create a dummy channel oil */
900 source->source_channel_oil = pim_channel_oil_add(
901 pim, &sg, MAXVIFS, __PRETTY_FUNCTION__);
902 }
903
904 else {
905 src.family = AF_INET;
906 src.prefixlen = IPV4_MAX_BITLEN;
907 src.u.prefix4 = vif_source; // RP or Src address
908 grp.family = AF_INET;
909 grp.prefixlen = IPV4_MAX_BITLEN;
910 grp.u.prefix4 = sg.grp;
911
912 up = pim_upstream_find(pim, &sg);
913 if (up) {
914 memcpy(&nexthop, &up->rpf.source_nexthop,
915 sizeof(struct pim_nexthop));
916 pim_ecmp_nexthop_lookup(pim, &nexthop, &src,
917 &grp, 0);
918 if (nexthop.interface)
919 input_iface_vif_index =
920 pim_if_find_vifindex_by_ifindex(
921 pim,
922 nexthop.interface->ifindex);
923 } else
924 input_iface_vif_index =
925 pim_ecmp_fib_lookup_if_vif_index(
926 pim, &src, &grp);
927
928 if (PIM_DEBUG_ZEBRA) {
929 char buf2[INET_ADDRSTRLEN];
930
931 pim_inet4_dump("<source?>", vif_source, buf2,
932 sizeof(buf2));
933 zlog_debug("%s: NHT %s vif_source %s vif_index:%d ",
934 __PRETTY_FUNCTION__,
935 pim_str_sg_dump(&sg),
936 buf2, input_iface_vif_index);
937 }
938
939 if (input_iface_vif_index < 1) {
940 if (PIM_DEBUG_IGMP_TRACE) {
941 char source_str[INET_ADDRSTRLEN];
942 pim_inet4_dump("<source?>",
943 source->source_addr,
944 source_str, sizeof(source_str));
945 zlog_debug(
946 "%s %s: could not find input interface for source %s",
947 __FILE__, __PRETTY_FUNCTION__,
948 source_str);
949 }
950 source->source_channel_oil =
951 pim_channel_oil_add(
952 pim, &sg, MAXVIFS,
953 __PRETTY_FUNCTION__);
954 }
955
956 else {
957 /*
958 * Protect IGMP against adding looped MFC
959 * entries created by both source and receiver
960 * attached to the same interface. See TODO
961 * T22. Block only when the intf is non DR
962 * DR must create upstream.
963 */
964 if ((input_iface_vif_index ==
965 pim_oif->mroute_vif_index) &&
966 !(PIM_I_am_DR(pim_oif))) {
967 /* ignore request for looped MFC entry
968 */
969 if (PIM_DEBUG_IGMP_TRACE) {
970 zlog_debug(
971 "%s: ignoring request for looped MFC entry (S,G)=%s: igmp_sock=%d oif=%s vif_index=%d",
972 __PRETTY_FUNCTION__,
973 pim_str_sg_dump(&sg),
974 source->source_group
975 ->group_igmp_sock->fd,
976 source->source_group
977 ->group_igmp_sock
978 ->interface->name,
979 input_iface_vif_index);
980 }
981 return;
982 }
983
984 source->source_channel_oil =
985 pim_channel_oil_add(
986 pim, &sg, input_iface_vif_index,
987 __PRETTY_FUNCTION__);
988 if (!source->source_channel_oil) {
989 if (PIM_DEBUG_IGMP_TRACE) {
990 zlog_debug(
991 "%s %s: could not create OIL for channel (S,G)=%s",
992 __FILE__,
993 __PRETTY_FUNCTION__,
994 pim_str_sg_dump(&sg));
995 }
996 return;
997 }
998 }
999 }
1000 }
1001
1002 result = pim_channel_add_oif(source->source_channel_oil,
1003 group->group_igmp_sock->interface,
1004 PIM_OIF_FLAG_PROTO_IGMP);
1005 if (result) {
1006 if (PIM_DEBUG_MROUTE) {
1007 zlog_warn("%s: add_oif() failed with return=%d",
1008 __func__, result);
1009 }
1010 return;
1011 }
1012
1013 if (!(PIM_I_am_DR(pim_oif))) {
1014 if (PIM_DEBUG_IGMP_TRACE)
1015 zlog_debug("%s: %s was received on %s interface but we are not DR for that interface",
1016 __PRETTY_FUNCTION__,
1017 pim_str_sg_dump(&sg),
1018 group->group_igmp_sock->interface->name);
1019
1020 pim_channel_del_oif(source->source_channel_oil,
1021 group->group_igmp_sock->interface,
1022 PIM_OIF_FLAG_PROTO_IGMP);
1023 return;
1024 }
1025 /*
1026 Feed IGMPv3-gathered local membership information into PIM
1027 per-interface (S,G) state.
1028 */
1029 if (!pim_ifchannel_local_membership_add(
1030 group->group_igmp_sock->interface, &sg)) {
1031 if (PIM_DEBUG_MROUTE)
1032 zlog_warn("%s: Failure to add local membership for %s",
1033 __PRETTY_FUNCTION__, pim_str_sg_dump(&sg));
1034
1035 pim_channel_del_oif(source->source_channel_oil,
1036 group->group_igmp_sock->interface,
1037 PIM_OIF_FLAG_PROTO_IGMP);
1038 return;
1039 }
1040
1041 IGMP_SOURCE_DO_FORWARDING(source->source_flags);
1042 }
1043
1044 /*
1045 igmp_source_forward_stop: stop fowarding, but keep the source
1046 igmp_source_delete: stop fowarding, and delete the source
1047 */
1048 void igmp_source_forward_stop(struct igmp_source *source)
1049 {
1050 struct igmp_group *group;
1051 struct prefix_sg sg;
1052 int result;
1053
1054 memset(&sg, 0, sizeof(struct prefix_sg));
1055 sg.src = source->source_addr;
1056 sg.grp = source->source_group->group_addr;
1057
1058 if (PIM_DEBUG_IGMP_TRACE) {
1059 zlog_debug(
1060 "%s: (S,G)=%s igmp_sock=%d oif=%s fwd=%d",
1061 __PRETTY_FUNCTION__, pim_str_sg_dump(&sg),
1062 source->source_group->group_igmp_sock->fd,
1063 source->source_group->group_igmp_sock->interface->name,
1064 IGMP_SOURCE_TEST_FORWARDING(source->source_flags));
1065 }
1066
1067 /* Prevent IGMP interface from removing multicast route multiple
1068 times */
1069 if (!IGMP_SOURCE_TEST_FORWARDING(source->source_flags)) {
1070 return;
1071 }
1072
1073 group = source->source_group;
1074
1075 /*
1076 It appears that in certain circumstances that
1077 igmp_source_forward_stop is called when IGMP forwarding
1078 was not enabled in oif_flags for this outgoing interface.
1079 Possibly because of multiple calls. When that happens, we
1080 enter the below if statement and this function returns early
1081 which in turn triggers the calling function to assert.
1082 Making the call to pim_channel_del_oif and ignoring the return code
1083 fixes the issue without ill effect, similar to
1084 pim_forward_stop below.
1085 */
1086 result = pim_channel_del_oif(source->source_channel_oil,
1087 group->group_igmp_sock->interface,
1088 PIM_OIF_FLAG_PROTO_IGMP);
1089 if (result) {
1090 if (PIM_DEBUG_IGMP_TRACE)
1091 zlog_debug(
1092 "%s: pim_channel_del_oif() failed with return=%d",
1093 __func__, result);
1094 return;
1095 }
1096
1097 /*
1098 Feed IGMPv3-gathered local membership information into PIM
1099 per-interface (S,G) state.
1100 */
1101 pim_ifchannel_local_membership_del(group->group_igmp_sock->interface,
1102 &sg);
1103
1104 IGMP_SOURCE_DONT_FORWARDING(source->source_flags);
1105 }
1106
1107 void pim_forward_start(struct pim_ifchannel *ch)
1108 {
1109 struct pim_upstream *up = ch->upstream;
1110 uint32_t mask = PIM_OIF_FLAG_PROTO_PIM;
1111 int input_iface_vif_index = 0;
1112 struct pim_instance *pim;
1113 struct pim_interface *pim_ifp;
1114
1115 pim_ifp = ch->interface->info;
1116 pim = pim_ifp->pim;
1117
1118 if (PIM_DEBUG_PIM_TRACE) {
1119 char source_str[INET_ADDRSTRLEN];
1120 char group_str[INET_ADDRSTRLEN];
1121 char upstream_str[INET_ADDRSTRLEN];
1122
1123 pim_inet4_dump("<source?>", ch->sg.src, source_str,
1124 sizeof(source_str));
1125 pim_inet4_dump("<group?>", ch->sg.grp, group_str,
1126 sizeof(group_str));
1127 pim_inet4_dump("<upstream?>", up->upstream_addr, upstream_str,
1128 sizeof(upstream_str));
1129 zlog_debug("%s: (S,G)=(%s,%s) oif=%s (%s)", __PRETTY_FUNCTION__,
1130 source_str, group_str, ch->interface->name,
1131 inet_ntoa(up->upstream_addr));
1132 }
1133
1134 /* Resolve IIF for upstream as mroute_del sets mfcc_parent to MAXVIFS,
1135 as part of mroute_del called by pim_forward_stop.
1136 */
1137 if ((up->upstream_addr.s_addr != INADDR_ANY) && (!up->channel_oil)) {
1138 struct prefix src, grp;
1139
1140 grp.family = AF_INET;
1141 grp.prefixlen = IPV4_MAX_BITLEN;
1142 grp.u.prefix4 = up->sg.grp;
1143 src.family = AF_INET;
1144 src.prefixlen = IPV4_MAX_BITLEN;
1145 src.u.prefix4 = up->sg.src;
1146
1147 if (pim_ecmp_nexthop_lookup(pim, &up->rpf.source_nexthop, &src,
1148 &grp, 0))
1149 input_iface_vif_index = pim_if_find_vifindex_by_ifindex(
1150 pim, up->rpf.source_nexthop.interface->ifindex);
1151
1152 if (input_iface_vif_index < 1) {
1153 if (PIM_DEBUG_PIM_TRACE) {
1154 char source_str[INET_ADDRSTRLEN];
1155 pim_inet4_dump("<source?>", up->sg.src,
1156 source_str, sizeof(source_str));
1157 zlog_debug(
1158 "%s %s: could not find input interface for source %s",
1159 __FILE__, __PRETTY_FUNCTION__,
1160 source_str);
1161 }
1162 pim_channel_oil_change_iif(pim, up->channel_oil,
1163 MAXVIFS,
1164 __PRETTY_FUNCTION__);
1165 }
1166
1167 else
1168 pim_channel_oil_change_iif(pim, up->channel_oil,
1169 input_iface_vif_index,
1170 __PRETTY_FUNCTION__);
1171
1172 if (PIM_DEBUG_TRACE) {
1173 struct interface *in_intf = pim_if_find_by_vif_index(
1174 pim, input_iface_vif_index);
1175 zlog_debug(
1176 "%s: Update channel_oil IIF %s VIFI %d entry %s ",
1177 __PRETTY_FUNCTION__,
1178 in_intf ? in_intf->name : "Unknown",
1179 input_iface_vif_index, up->sg_str);
1180 }
1181 }
1182
1183 if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP)
1184 mask = PIM_OIF_FLAG_PROTO_IGMP;
1185
1186 pim_channel_add_oif(up->channel_oil, ch->interface, mask);
1187 }
1188
1189 void pim_forward_stop(struct pim_ifchannel *ch, bool install_it)
1190 {
1191 struct pim_upstream *up = ch->upstream;
1192
1193 if (PIM_DEBUG_PIM_TRACE) {
1194 zlog_debug("%s: (S,G)=%s oif=%s install_it: %d installed: %d",
1195 __PRETTY_FUNCTION__, ch->sg_str, ch->interface->name,
1196 install_it, up->channel_oil->installed);
1197 }
1198
1199 /*
1200 * If a channel is being removed, check to see if we still need
1201 * to inherit the interface. If so make sure it is added in
1202 */
1203 if (pim_upstream_evaluate_join_desired_interface(up, ch, ch->parent))
1204 pim_channel_add_oif(up->channel_oil, ch->interface,
1205 PIM_OIF_FLAG_PROTO_PIM);
1206 else
1207 pim_channel_del_oif(up->channel_oil, ch->interface,
1208 PIM_OIF_FLAG_PROTO_PIM);
1209
1210 if (install_it && !up->channel_oil->installed)
1211 pim_mroute_add(up->channel_oil, __PRETTY_FUNCTION__);
1212 }
1213
1214 void pim_zebra_zclient_update(struct vty *vty)
1215 {
1216 vty_out(vty, "Zclient update socket: ");
1217
1218 if (zclient) {
1219 vty_out(vty, "%d failures=%d\n", zclient->sock, zclient->fail);
1220 } else {
1221 vty_out(vty, "<null zclient>\n");
1222 }
1223 }
1224
1225 struct zclient *pim_zebra_zclient_get(void)
1226 {
1227 if (zclient)
1228 return zclient;
1229 else
1230 return NULL;
1231 }