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