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