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