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