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