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