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