]> git.proxmox.com Git - mirror_frr.git/blob - pimd/pim_zebra.c
pimd: Clarify pim_mroute_[add|del] function debugging
[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
22 #include <zebra.h>
23
24 #include "zebra/rib.h"
25
26 #include "if.h"
27 #include "log.h"
28 #include "prefix.h"
29 #include "zclient.h"
30 #include "stream.h"
31 #include "network.h"
32 #include "vty.h"
33 #include "plist.h"
34
35 #include "pimd.h"
36 #include "pim_pim.h"
37 #include "pim_zebra.h"
38 #include "pim_iface.h"
39 #include "pim_str.h"
40 #include "pim_oil.h"
41 #include "pim_rpf.h"
42 #include "pim_time.h"
43 #include "pim_join.h"
44 #include "pim_zlookup.h"
45 #include "pim_ifchannel.h"
46 #include "pim_rp.h"
47 #include "pim_igmpv3.h"
48
49 #undef PIM_DEBUG_IFADDR_DUMP
50 #define PIM_DEBUG_IFADDR_DUMP
51
52 static int fib_lookup_if_vif_index(struct in_addr addr);
53 static int del_oif(struct channel_oil *channel_oil,
54 struct interface *oif,
55 uint32_t proto_mask);
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 /*
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 return 0;
193 }
194
195 #ifdef PIM_DEBUG_IFADDR_DUMP
196 static void dump_if_address(struct interface *ifp)
197 {
198 struct connected *ifc;
199 struct listnode *node;
200
201 zlog_debug("%s %s: interface %s addresses:",
202 __FILE__, __PRETTY_FUNCTION__,
203 ifp->name);
204
205 for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) {
206 struct prefix *p = ifc->address;
207
208 if (p->family != AF_INET)
209 continue;
210
211 zlog_debug("%s %s: interface %s address %s %s",
212 __FILE__, __PRETTY_FUNCTION__,
213 ifp->name,
214 inet_ntoa(p->u.prefix4),
215 CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY) ?
216 "secondary" : "primary");
217 }
218 }
219 #endif
220
221 static int pim_zebra_if_address_add(int command, struct zclient *zclient,
222 zebra_size_t length, vrf_id_t vrf_id)
223 {
224 struct connected *c;
225 struct prefix *p;
226 struct pim_interface *pim_ifp;
227
228 /*
229 zebra api notifies address adds/dels events by using the same call
230 interface_add_read below, see comments in lib/zclient.c
231
232 zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_ADD, ...)
233 will add address to interface list by calling
234 connected_add_by_prefix()
235 */
236 c = zebra_interface_address_read(command, zclient->ibuf, vrf_id);
237 if (!c)
238 return 0;
239
240 pim_ifp = c->ifp->info;
241 p = c->address;
242
243 if (PIM_DEBUG_ZEBRA) {
244 char buf[BUFSIZ];
245 prefix2str(p, buf, BUFSIZ);
246 zlog_debug("%s: %s connected IP address %s flags %u %s",
247 __PRETTY_FUNCTION__,
248 c->ifp->name, buf, c->flags,
249 CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY) ? "secondary" : "primary");
250
251 #ifdef PIM_DEBUG_IFADDR_DUMP
252 dump_if_address(c->ifp);
253 #endif
254 }
255
256 if (p->family != AF_INET)
257 {
258 struct listnode *cnode;
259 struct connected *conn;
260 int v4addrs = 0;
261
262 for (ALL_LIST_ELEMENTS_RO (c->ifp->connected, cnode, conn))
263 {
264 if (conn->address->family == AF_INET)
265 v4addrs++;
266 }
267 if (!v4addrs && pim_ifp)
268 {
269 pim_ifp->primary_address = pim_find_primary_addr (c->ifp);
270 pim_if_addr_add_all (c->ifp);
271 pim_if_add_vif (c->ifp);
272 }
273 return 0;
274 }
275
276 if (!CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY)) {
277 /* trying to add primary address */
278
279 struct in_addr primary_addr = pim_find_primary_addr(c->ifp);
280 if (primary_addr.s_addr != p->u.prefix4.s_addr) {
281 if (PIM_DEBUG_ZEBRA) {
282 /* but we had a primary address already */
283
284 char buf[BUFSIZ];
285
286 prefix2str(p, buf, BUFSIZ);
287
288 zlog_warn("%s: %s : forcing secondary flag on %s",
289 __PRETTY_FUNCTION__,
290 c->ifp->name, buf);
291 }
292 SET_FLAG(c->flags, ZEBRA_IFA_SECONDARY);
293 }
294 }
295
296 pim_if_addr_add(c);
297 if (pim_ifp)
298 pim_rp_check_on_if_add(pim_ifp);
299
300 if (if_is_loopback (c->ifp))
301 {
302 struct listnode *ifnode;
303 struct interface *ifp;
304
305 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp))
306 {
307 if (!if_is_loopback (ifp) && if_is_operative (ifp))
308 pim_if_addr_add_all (ifp);
309 }
310 }
311
312 return 0;
313 }
314
315 static int pim_zebra_if_address_del(int command, struct zclient *client,
316 zebra_size_t length, vrf_id_t vrf_id)
317 {
318 struct connected *c;
319 struct prefix *p;
320
321 /*
322 zebra api notifies address adds/dels events by using the same call
323 interface_add_read below, see comments in lib/zclient.c
324
325 zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_DELETE, ...)
326 will remove address from interface list by calling
327 connected_delete_by_prefix()
328 */
329 c = zebra_interface_address_read(command, client->ibuf, vrf_id);
330 if (!c)
331 return 0;
332
333 p = c->address;
334 if (p->family != AF_INET)
335 return 0;
336
337 if (PIM_DEBUG_ZEBRA) {
338 char buf[BUFSIZ];
339 prefix2str(p, buf, BUFSIZ);
340 zlog_debug("%s: %s disconnected IP address %s flags %u %s",
341 __PRETTY_FUNCTION__,
342 c->ifp->name, buf, c->flags,
343 CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY) ? "secondary" : "primary");
344
345 #ifdef PIM_DEBUG_IFADDR_DUMP
346 dump_if_address(c->ifp);
347 #endif
348 }
349
350 pim_if_addr_del(c, 0);
351 pim_rp_setup();
352 pim_i_am_rp_re_evaluate();
353
354 return 0;
355 }
356
357 static void scan_upstream_rpf_cache()
358 {
359 struct listnode *up_node;
360 struct listnode *up_nextnode;
361 struct pim_upstream *up;
362
363 for (ALL_LIST_ELEMENTS(pim_upstream_list, up_node, up_nextnode, up)) {
364 struct in_addr old_rpf_addr;
365 struct interface *old_interface;
366 enum pim_rpf_result rpf_result;
367
368 old_interface = up->rpf.source_nexthop.interface;
369 rpf_result = pim_rpf_update(up, &old_rpf_addr);
370 if (rpf_result == PIM_RPF_FAILURE)
371 continue;
372
373 if (rpf_result == PIM_RPF_CHANGED) {
374
375 if (up->join_state == PIM_UPSTREAM_JOINED) {
376 /*
377 * If we come up real fast we can be here
378 * where the mroute has not been installed
379 * so install it.
380 */
381 if (up->channel_oil && !up->channel_oil->installed)
382 pim_mroute_add (up->channel_oil, __PRETTY_FUNCTION__);
383
384 /*
385 RFC 4601: 4.5.7. Sending (S,G) Join/Prune Messages
386
387 Transitions from Joined State
388
389 RPF'(S,G) changes not due to an Assert
390
391 The upstream (S,G) state machine remains in Joined
392 state. Send Join(S,G) to the new upstream neighbor, which is
393 the new value of RPF'(S,G). Send Prune(S,G) to the old
394 upstream neighbor, which is the old value of RPF'(S,G). Set
395 the Join Timer (JT) to expire after t_periodic seconds.
396 */
397
398
399 /* send Prune(S,G) to the old upstream neighbor */
400 pim_joinprune_send(old_interface, old_rpf_addr,
401 up, 0 /* prune */);
402
403 /* send Join(S,G) to the current upstream neighbor */
404 pim_joinprune_send(up->rpf.source_nexthop.interface,
405 up->rpf.rpf_addr.u.prefix4,
406 up,
407 1 /* join */);
408
409 pim_upstream_join_timer_restart(up);
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 }
421
422 void
423 pim_scan_individual_oil (struct channel_oil *c_oil)
424 {
425 struct in_addr vif_source;
426 int input_iface_vif_index;
427 int old_vif_index;
428
429 if (!pim_rp_set_upstream_addr (&vif_source, c_oil->oil.mfcc_origin, c_oil->oil.mfcc_mcastgrp))
430 return;
431
432 input_iface_vif_index = fib_lookup_if_vif_index (vif_source);
433 if (input_iface_vif_index < 1)
434 {
435 if (PIM_DEBUG_ZEBRA)
436 {
437 char source_str[INET_ADDRSTRLEN];
438 char group_str[INET_ADDRSTRLEN];
439 pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str, sizeof(source_str));
440 pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
441 zlog_debug("%s %s: could not find input interface(%d) for (S,G)=(%s,%s)",
442 __FILE__, __PRETTY_FUNCTION__, c_oil->oil.mfcc_parent,
443 source_str, group_str);
444 }
445 pim_mroute_del (c_oil, __PRETTY_FUNCTION__);
446 return;
447 }
448
449 if (input_iface_vif_index == c_oil->oil.mfcc_parent)
450 {
451 if (!c_oil->installed)
452 pim_mroute_add (c_oil, __PRETTY_FUNCTION__);
453
454 /* RPF unchanged */
455 return;
456 }
457
458 if (PIM_DEBUG_ZEBRA)
459 {
460 struct interface *old_iif = pim_if_find_by_vif_index(c_oil->oil.mfcc_parent);
461 struct interface *new_iif = pim_if_find_by_vif_index(input_iface_vif_index);
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 %s: (S,G)=(%s,%s) input interface changed from %s vif_index=%d to %s vif_index=%d",
467 __FILE__, __PRETTY_FUNCTION__,
468 source_str, group_str,
469 old_iif->name, c_oil->oil.mfcc_parent,
470 new_iif->name, input_iface_vif_index);
471 }
472
473 /* new iif loops to existing oif ? */
474 if (c_oil->oil.mfcc_ttls[input_iface_vif_index])
475 {
476 struct interface *new_iif = pim_if_find_by_vif_index(input_iface_vif_index);
477
478 if (PIM_DEBUG_ZEBRA) {
479 char source_str[INET_ADDRSTRLEN];
480 char group_str[INET_ADDRSTRLEN];
481 pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str, sizeof(source_str));
482 pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
483 zlog_debug("%s %s: (S,G)=(%s,%s) new iif loops to existing oif: %s vif_index=%d",
484 __FILE__, __PRETTY_FUNCTION__,
485 source_str, group_str,
486 new_iif->name, input_iface_vif_index);
487 }
488
489 //del_oif(c_oil, new_iif, PIM_OIF_FLAG_PROTO_ANY);
490 }
491
492 /* update iif vif_index */
493 old_vif_index = c_oil->oil.mfcc_parent;
494 c_oil->oil.mfcc_parent = input_iface_vif_index;
495
496 /* update kernel multicast forwarding cache (MFC) */
497 if (pim_mroute_add(c_oil, __PRETTY_FUNCTION__))
498 {
499 if (PIM_DEBUG_MROUTE)
500 {
501 /* just log warning */
502 struct interface *old_iif = pim_if_find_by_vif_index(old_vif_index);
503 struct interface *new_iif = pim_if_find_by_vif_index(input_iface_vif_index);
504 char source_str[INET_ADDRSTRLEN];
505 char group_str[INET_ADDRSTRLEN];
506 pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str, sizeof(source_str));
507 pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
508 zlog_debug("%s %s: (S,G)=(%s,%s) failure updating input interface from %s vif_index=%d to %s vif_index=%d",
509 __FILE__, __PRETTY_FUNCTION__,
510 source_str, group_str,
511 old_iif ? old_iif->name : "<old_iif?>", c_oil->oil.mfcc_parent,
512 new_iif ? new_iif->name : "<new_iif?>", input_iface_vif_index);
513 }
514 }
515 }
516
517 void pim_scan_oil()
518 {
519 struct listnode *node;
520 struct listnode *nextnode;
521 struct channel_oil *c_oil;
522
523 qpim_scan_oil_last = pim_time_monotonic_sec();
524 ++qpim_scan_oil_events;
525
526 for (ALL_LIST_ELEMENTS(pim_channel_oil_list, node, nextnode, c_oil))
527 pim_scan_individual_oil (c_oil);
528 }
529
530 static int on_rpf_cache_refresh(struct thread *t)
531 {
532 zassert(qpim_rpf_cache_refresher);
533
534 qpim_rpf_cache_refresher = 0;
535
536 /* update PIM protocol state */
537 scan_upstream_rpf_cache();
538
539 /* update kernel multicast forwarding cache (MFC) */
540 pim_scan_oil();
541
542 qpim_rpf_cache_refresh_last = pim_time_monotonic_sec();
543 ++qpim_rpf_cache_refresh_events;
544
545 pim_rp_setup ();
546 return 0;
547 }
548
549 void sched_rpf_cache_refresh(void)
550 {
551 ++qpim_rpf_cache_refresh_requests;
552
553 pim_rpf_set_refresh_time ();
554
555 if (qpim_rpf_cache_refresher) {
556 /* Refresh timer is already running */
557 return;
558 }
559
560 /* Start refresh timer */
561
562 if (PIM_DEBUG_ZEBRA) {
563 zlog_debug("%s: triggering %ld msec timer",
564 __PRETTY_FUNCTION__,
565 qpim_rpf_cache_refresh_delay_msec);
566 }
567
568 THREAD_TIMER_MSEC_ON(master, qpim_rpf_cache_refresher,
569 on_rpf_cache_refresh,
570 0, qpim_rpf_cache_refresh_delay_msec);
571 }
572
573 static int redist_read_ipv4_route(int command, struct zclient *zclient,
574 zebra_size_t length, vrf_id_t vrf_id)
575 {
576 struct stream *s;
577 struct zapi_ipv4 api;
578 ifindex_t ifindex;
579 struct in_addr nexthop;
580 struct prefix_ipv4 p;
581 int min_len = 4;
582
583 if (length < min_len) {
584 zlog_warn("%s %s: short buffer: length=%d min=%d",
585 __FILE__, __PRETTY_FUNCTION__,
586 length, min_len);
587 return -1;
588 }
589
590 s = zclient->ibuf;
591 ifindex = 0;
592 nexthop.s_addr = 0;
593
594 /* Type, flags, message. */
595 api.type = stream_getc(s);
596 api.instance = stream_getw (s);
597 api.flags = stream_getl(s);
598 api.message = stream_getc(s);
599
600 /* IPv4 prefix length. */
601 memset(&p, 0, sizeof(struct prefix_ipv4));
602 p.family = AF_INET;
603 p.prefixlen = stream_getc(s);
604
605 min_len +=
606 PSIZE(p.prefixlen) +
607 CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP) ? 5 : 0 +
608 CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX) ? 5 : 0 +
609 CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE) ? 1 : 0 +
610 CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC) ? 4 : 0;
611
612 if (PIM_DEBUG_ZEBRA) {
613 zlog_debug("%s %s: length=%d min_len=%d flags=%s%s%s%s",
614 __FILE__, __PRETTY_FUNCTION__,
615 length, min_len,
616 CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP) ? "nh" : "",
617 CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX) ? " ifi" : "",
618 CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE) ? " dist" : "",
619 CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC) ? " metr" : "");
620 }
621
622 /* IPv4 prefix. */
623 stream_get(&p.prefix, s, PSIZE(p.prefixlen));
624
625 /* Nexthop, ifindex, distance, metric. */
626 if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) {
627 api.nexthop_num = stream_getc(s);
628 nexthop.s_addr = stream_get_ipv4(s);
629 }
630 if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) {
631 api.ifindex_num = stream_getc(s);
632 ifindex = stream_getl(s);
633 }
634
635 api.distance = CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE) ?
636 stream_getc(s) :
637 0;
638
639 api.metric = CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC) ?
640 stream_getl(s) :
641 0;
642
643 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_TAG))
644 api.tag = stream_getl (s);
645 else
646 api.tag = 0;
647
648 switch (command) {
649 case ZEBRA_REDISTRIBUTE_IPV4_ADD:
650 if (PIM_DEBUG_ZEBRA) {
651 char buf[2][INET_ADDRSTRLEN];
652 zlog_debug("%s: add %s %s/%d "
653 "nexthop %s ifindex %d metric%s %u distance%s %u",
654 __PRETTY_FUNCTION__,
655 zebra_route_string(api.type),
656 inet_ntop(AF_INET, &p.prefix, buf[0], sizeof(buf[0])),
657 p.prefixlen,
658 inet_ntop(AF_INET, &nexthop, buf[1], sizeof(buf[1])),
659 ifindex,
660 CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC) ? "-recv" : "-miss",
661 api.metric,
662 CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE) ? "-recv" : "-miss",
663 api.distance);
664 }
665 break;
666 case ZEBRA_REDISTRIBUTE_IPV4_DEL:
667 if (PIM_DEBUG_ZEBRA) {
668 char buf[2][INET_ADDRSTRLEN];
669 zlog_debug("%s: delete %s %s/%d "
670 "nexthop %s ifindex %d metric%s %u distance%s %u",
671 __PRETTY_FUNCTION__,
672 zebra_route_string(api.type),
673 inet_ntop(AF_INET, &p.prefix, buf[0], sizeof(buf[0])),
674 p.prefixlen,
675 inet_ntop(AF_INET, &nexthop, buf[1], sizeof(buf[1])),
676 ifindex,
677 CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC) ? "-recv" : "-miss",
678 api.metric,
679 CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE) ? "-recv" : "-miss",
680 api.distance);
681 }
682 break;
683 default:
684 zlog_warn("%s: unknown command=%d", __PRETTY_FUNCTION__, command);
685 return -1;
686 }
687
688 sched_rpf_cache_refresh();
689
690 pim_rp_setup ();
691 return 0;
692 }
693
694 static void
695 pim_zebra_connected (struct zclient *zclient)
696 {
697 zclient_send_reg_requests (zclient, VRF_DEFAULT);
698 }
699
700 void pim_zebra_init(char *zebra_sock_path)
701 {
702 int i;
703
704 if (zebra_sock_path)
705 zclient_serv_path_set(zebra_sock_path);
706
707 #ifdef HAVE_TCP_ZEBRA
708 zlog_notice("zclient update contacting ZEBRA daemon at socket TCP %s,%d", "127.0.0.1", ZEBRA_PORT);
709 #else
710 zlog_notice("zclient update contacting ZEBRA daemon at socket UNIX %s", zclient_serv_path_get());
711 #endif
712
713 /* Socket for receiving updates from Zebra daemon */
714 qpim_zclient_update = zclient_new (master);
715
716 qpim_zclient_update->zebra_connected = pim_zebra_connected;
717 qpim_zclient_update->router_id_update = pim_router_id_update_zebra;
718 qpim_zclient_update->interface_add = pim_zebra_if_add;
719 qpim_zclient_update->interface_delete = pim_zebra_if_del;
720 qpim_zclient_update->interface_up = pim_zebra_if_state_up;
721 qpim_zclient_update->interface_down = pim_zebra_if_state_down;
722 qpim_zclient_update->interface_address_add = pim_zebra_if_address_add;
723 qpim_zclient_update->interface_address_delete = pim_zebra_if_address_del;
724 qpim_zclient_update->redistribute_route_ipv4_add = redist_read_ipv4_route;
725 qpim_zclient_update->redistribute_route_ipv4_del = redist_read_ipv4_route;
726
727 zclient_init(qpim_zclient_update, ZEBRA_ROUTE_PIM, 0);
728 if (PIM_DEBUG_PIM_TRACE) {
729 zlog_info("zclient_init cleared redistribution request");
730 }
731
732 zassert(qpim_zclient_update->redist_default == ZEBRA_ROUTE_PIM);
733
734 /* Request all redistribution */
735 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
736 if (i == qpim_zclient_update->redist_default)
737 continue;
738 vrf_bitmap_set (qpim_zclient_update->redist[AFI_IP][i], VRF_DEFAULT);;
739 if (PIM_DEBUG_PIM_TRACE) {
740 zlog_debug("%s: requesting redistribution for %s (%i)",
741 __PRETTY_FUNCTION__, zebra_route_string(i), i);
742 }
743 }
744
745 /* Request default information */
746 zclient_redistribute_default (ZEBRA_REDISTRIBUTE_DEFAULT_ADD,
747 qpim_zclient_update, VRF_DEFAULT);
748
749 if (PIM_DEBUG_PIM_TRACE) {
750 zlog_info("%s: requesting default information redistribution",
751 __PRETTY_FUNCTION__);
752
753 zlog_notice("%s: zclient update socket initialized",
754 __PRETTY_FUNCTION__);
755 }
756
757 zclient_lookup_new();
758 }
759
760 void igmp_anysource_forward_start(struct igmp_group *group)
761 {
762 struct igmp_source *source;
763 struct in_addr src_addr = { .s_addr = 0 };
764 /* Any source (*,G) is forwarded only if mode is EXCLUDE {empty} */
765 zassert(group->group_filtermode_isexcl);
766 zassert(listcount(group->group_source_list) < 1);
767
768 source = source_new (group, src_addr);
769 if (!source)
770 {
771 zlog_warn ("%s: Failure to create * source", __PRETTY_FUNCTION__);
772 return;
773 }
774
775 igmp_source_forward_start (source);
776 }
777
778 void igmp_anysource_forward_stop(struct igmp_group *group)
779 {
780 struct igmp_source *source;
781 struct in_addr star = { .s_addr = 0 };
782
783 source = igmp_find_source_by_addr (group, star);
784 if (source)
785 igmp_source_forward_stop (source);
786 }
787
788 static int fib_lookup_if_vif_index(struct in_addr addr)
789 {
790 struct pim_zlookup_nexthop nexthop_tab[MULTIPATH_NUM];
791 int num_ifindex;
792 int vif_index;
793 ifindex_t first_ifindex;
794
795 num_ifindex = zclient_lookup_nexthop(nexthop_tab,
796 MULTIPATH_NUM, addr,
797 PIM_NEXTHOP_LOOKUP_MAX);
798 if (num_ifindex < 1) {
799 if (PIM_DEBUG_ZEBRA)
800 {
801 char addr_str[INET_ADDRSTRLEN];
802 pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str));
803 zlog_debug("%s %s: could not find nexthop ifindex for address %s",
804 __FILE__, __PRETTY_FUNCTION__,
805 addr_str);
806 }
807 return -1;
808 }
809
810 first_ifindex = nexthop_tab[0].ifindex;
811
812 if (num_ifindex > 1) {
813 if (PIM_DEBUG_ZEBRA)
814 {
815 char addr_str[INET_ADDRSTRLEN];
816 pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str));
817 zlog_debug("%s %s: FIXME ignoring multiple nexthop ifindex'es num_ifindex=%d for address %s (using only ifindex=%d)",
818 __FILE__, __PRETTY_FUNCTION__,
819 num_ifindex, addr_str, first_ifindex);
820 }
821 /* debug warning only, do not return */
822 }
823
824 if (PIM_DEBUG_ZEBRA) {
825 char addr_str[INET_ADDRSTRLEN];
826 pim_inet4_dump("<ifaddr?>", addr, addr_str, sizeof(addr_str));
827 zlog_debug("%s %s: found nexthop ifindex=%d (interface %s) for address %s",
828 __FILE__, __PRETTY_FUNCTION__,
829 first_ifindex, ifindex2ifname(first_ifindex), addr_str);
830 }
831
832 vif_index = pim_if_find_vifindex_by_ifindex(first_ifindex);
833
834 if (vif_index < 0) {
835 if (PIM_DEBUG_ZEBRA)
836 {
837 char addr_str[INET_ADDRSTRLEN];
838 pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str));
839 zlog_debug("%s %s: low vif_index=%d < 1 nexthop for address %s",
840 __FILE__, __PRETTY_FUNCTION__,
841 vif_index, addr_str);
842 }
843 return -2;
844 }
845
846 return vif_index;
847 }
848
849 static int del_oif(struct channel_oil *channel_oil,
850 struct interface *oif,
851 uint32_t proto_mask)
852 {
853 struct pim_interface *pim_ifp;
854 int old_ttl;
855
856 pim_ifp = oif->info;
857
858 if (PIM_DEBUG_MROUTE) {
859 char group_str[INET_ADDRSTRLEN];
860 char source_str[INET_ADDRSTRLEN];
861 pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
862 pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str));
863 zlog_debug("%s %s: (S,G)=(%s,%s): proto_mask=%u OIF=%s vif_index=%d",
864 __FILE__, __PRETTY_FUNCTION__,
865 source_str, group_str,
866 proto_mask, oif->name, pim_ifp->mroute_vif_index);
867 }
868
869 /* Prevent single protocol from unsubscribing same interface from
870 channel (S,G) multiple times */
871 if (!(channel_oil->oif_flags[pim_ifp->mroute_vif_index] & proto_mask)) {
872 if (PIM_DEBUG_MROUTE)
873 {
874 char group_str[INET_ADDRSTRLEN];
875 char source_str[INET_ADDRSTRLEN];
876 pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
877 pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str));
878 zlog_debug("%s %s: nonexistent protocol mask %u removed OIF %s (vif_index=%d, min_ttl=%d) from channel (S,G)=(%s,%s)",
879 __FILE__, __PRETTY_FUNCTION__,
880 proto_mask, oif->name, pim_ifp->mroute_vif_index,
881 channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index],
882 source_str, group_str);
883 }
884 return -2;
885 }
886
887 /* Mark that protocol is no longer interested in this OIF */
888 channel_oil->oif_flags[pim_ifp->mroute_vif_index] &= ~proto_mask;
889
890 /* Allow multiple protocols to unsubscribe same interface from
891 channel (S,G) multiple times, by silently ignoring requests while
892 there is at least one protocol interested in the channel */
893 if (channel_oil->oif_flags[pim_ifp->mroute_vif_index] & PIM_OIF_FLAG_PROTO_ANY) {
894
895 /* Check the OIF keeps existing before returning, and only log
896 warning otherwise */
897 if (channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] < 1) {
898 if (PIM_DEBUG_MROUTE)
899 {
900 char group_str[INET_ADDRSTRLEN];
901 char source_str[INET_ADDRSTRLEN];
902 pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
903 pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str));
904 zlog_debug("%s %s: protocol mask %u removing nonexistent OIF %s (vif_index=%d, min_ttl=%d) from channel (S,G)=(%s,%s)",
905 __FILE__, __PRETTY_FUNCTION__,
906 proto_mask, oif->name, pim_ifp->mroute_vif_index,
907 channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index],
908 source_str, group_str);
909 }
910 }
911
912 return 0;
913 }
914
915 old_ttl = channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index];
916
917 if (old_ttl < 1) {
918 if (PIM_DEBUG_MROUTE)
919 {
920 char group_str[INET_ADDRSTRLEN];
921 char source_str[INET_ADDRSTRLEN];
922 pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
923 pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str));
924 zlog_debug("%s %s: interface %s (vif_index=%d) is not output for channel (S,G)=(%s,%s)",
925 __FILE__, __PRETTY_FUNCTION__,
926 oif->name, pim_ifp->mroute_vif_index,
927 source_str, group_str);
928 }
929 return -3;
930 }
931
932 channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] = 0;
933
934 if (pim_mroute_add(channel_oil, __PRETTY_FUNCTION__)) {
935 char group_str[INET_ADDRSTRLEN];
936 char source_str[INET_ADDRSTRLEN];
937 pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
938 pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str));
939 zlog_warn("%s %s: could not remove output interface %s (vif_index=%d) from channel (S,G)=(%s,%s)",
940 __FILE__, __PRETTY_FUNCTION__,
941 oif->name, pim_ifp->mroute_vif_index,
942 source_str, group_str);
943
944 channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] = old_ttl;
945 return -4;
946 }
947
948 --channel_oil->oil_size;
949
950 if (channel_oil->oil_size < 1) {
951 if (pim_mroute_del(channel_oil, __PRETTY_FUNCTION__)) {
952 if (PIM_DEBUG_MROUTE)
953 {
954 /* just log a warning in case of failure */
955 char group_str[INET_ADDRSTRLEN];
956 char source_str[INET_ADDRSTRLEN];
957 pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
958 pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str));
959 zlog_debug("%s %s: failure removing OIL for channel (S,G)=(%s,%s)",
960 __FILE__, __PRETTY_FUNCTION__,
961 source_str, group_str);
962 }
963 }
964 }
965
966 if (PIM_DEBUG_MROUTE) {
967 char group_str[INET_ADDRSTRLEN];
968 char source_str[INET_ADDRSTRLEN];
969 pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
970 pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str));
971 zlog_debug("%s %s: (S,G)=(%s,%s): proto_mask=%u OIF=%s vif_index=%d: DONE",
972 __FILE__, __PRETTY_FUNCTION__,
973 source_str, group_str,
974 proto_mask, oif->name, pim_ifp->mroute_vif_index);
975 }
976
977 return 0;
978 }
979
980 void igmp_source_forward_start(struct igmp_source *source)
981 {
982 struct igmp_group *group;
983 struct prefix_sg sg;
984 int result;
985
986 memset (&sg, 0, sizeof (struct prefix_sg));
987 sg.src = source->source_addr;
988 sg.grp = source->source_group->group_addr;
989
990 if (PIM_DEBUG_IGMP_TRACE) {
991 zlog_debug("%s: (S,G)=%s igmp_sock=%d oif=%s fwd=%d",
992 __PRETTY_FUNCTION__,
993 pim_str_sg_dump (&sg),
994 source->source_group->group_igmp_sock->fd,
995 source->source_group->group_igmp_sock->interface->name,
996 IGMP_SOURCE_TEST_FORWARDING(source->source_flags));
997 }
998
999 /* Prevent IGMP interface from installing multicast route multiple
1000 times */
1001 if (IGMP_SOURCE_TEST_FORWARDING(source->source_flags)) {
1002 return;
1003 }
1004
1005 group = source->source_group;
1006
1007 if (!source->source_channel_oil) {
1008 struct in_addr vif_source;
1009 struct pim_interface *pim_oif;
1010
1011 if (!pim_rp_set_upstream_addr (&vif_source, source->source_addr, sg.grp))
1012 return;
1013
1014 int input_iface_vif_index = fib_lookup_if_vif_index(vif_source);
1015 if (input_iface_vif_index < 1) {
1016 if (PIM_DEBUG_IGMP_TRACE)
1017 {
1018 char source_str[INET_ADDRSTRLEN];
1019 pim_inet4_dump("<source?>", source->source_addr, source_str, sizeof(source_str));
1020 zlog_debug("%s %s: could not find input interface for source %s",
1021 __FILE__, __PRETTY_FUNCTION__,
1022 source_str);
1023 }
1024 return;
1025 }
1026
1027 /*
1028 Protect IGMP against adding looped MFC entries created by both
1029 source and receiver attached to the same interface. See TODO
1030 T22.
1031 */
1032 pim_oif = source->source_group->group_igmp_sock->interface->info;
1033 if (!pim_oif) {
1034 if (PIM_DEBUG_IGMP_TRACE)
1035 {
1036 zlog_debug("%s: multicast not enabled on oif=%s ?",
1037 __PRETTY_FUNCTION__,
1038 source->source_group->group_igmp_sock->interface->name);
1039 }
1040 return;
1041 }
1042
1043 if (input_iface_vif_index == pim_oif->mroute_vif_index) {
1044 /* ignore request for looped MFC entry */
1045 if (PIM_DEBUG_IGMP_TRACE) {
1046 zlog_debug("%s: ignoring request for looped MFC entry (S,G)=%s: igmp_sock=%d oif=%s vif_index=%d",
1047 __PRETTY_FUNCTION__,
1048 pim_str_sg_dump (&sg),
1049 source->source_group->group_igmp_sock->fd,
1050 source->source_group->group_igmp_sock->interface->name,
1051 input_iface_vif_index);
1052 }
1053 return;
1054 }
1055
1056 source->source_channel_oil = pim_channel_oil_add(&sg,
1057 input_iface_vif_index);
1058 if (!source->source_channel_oil) {
1059 if (PIM_DEBUG_IGMP_TRACE)
1060 {
1061 zlog_debug("%s %s: could not create OIL for channel (S,G)=%s",
1062 __FILE__, __PRETTY_FUNCTION__,
1063 pim_str_sg_dump (&sg));
1064 }
1065 return;
1066 }
1067 }
1068
1069 result = pim_channel_add_oif(source->source_channel_oil,
1070 group->group_igmp_sock->interface,
1071 PIM_OIF_FLAG_PROTO_IGMP);
1072 if (result) {
1073 if (PIM_DEBUG_MROUTE)
1074 {
1075 zlog_warn("%s: add_oif() failed with return=%d",
1076 __func__, result);
1077 }
1078 return;
1079 }
1080
1081 /*
1082 Feed IGMPv3-gathered local membership information into PIM
1083 per-interface (S,G) state.
1084 */
1085 pim_ifchannel_local_membership_add(group->group_igmp_sock->interface, &sg);
1086
1087 IGMP_SOURCE_DO_FORWARDING(source->source_flags);
1088 }
1089
1090 /*
1091 igmp_source_forward_stop: stop fowarding, but keep the source
1092 igmp_source_delete: stop fowarding, and delete the source
1093 */
1094 void igmp_source_forward_stop(struct igmp_source *source)
1095 {
1096 struct igmp_group *group;
1097 struct prefix_sg sg;
1098 int result;
1099
1100 memset (&sg, 0, sizeof (struct prefix_sg));
1101 sg.src = source->source_addr;
1102 sg.grp = source->source_group->group_addr;
1103
1104 if (PIM_DEBUG_IGMP_TRACE) {
1105 zlog_debug("%s: (S,G)=%s igmp_sock=%d oif=%s fwd=%d",
1106 __PRETTY_FUNCTION__,
1107 pim_str_sg_dump (&sg),
1108 source->source_group->group_igmp_sock->fd,
1109 source->source_group->group_igmp_sock->interface->name,
1110 IGMP_SOURCE_TEST_FORWARDING(source->source_flags));
1111 }
1112
1113 /* Prevent IGMP interface from removing multicast route multiple
1114 times */
1115 if (!IGMP_SOURCE_TEST_FORWARDING(source->source_flags)) {
1116 return;
1117 }
1118
1119 group = source->source_group;
1120
1121 /*
1122 It appears that in certain circumstances that
1123 igmp_source_forward_stop is called when IGMP forwarding
1124 was not enabled in oif_flags for this outgoing interface.
1125 Possibly because of multiple calls. When that happens, we
1126 enter the below if statement and this function returns early
1127 which in turn triggers the calling function to assert.
1128 Making the call to del_oif and ignoring the return code
1129 fixes the issue without ill effect, similar to
1130 pim_forward_stop below.
1131 */
1132 result = del_oif(source->source_channel_oil,
1133 group->group_igmp_sock->interface,
1134 PIM_OIF_FLAG_PROTO_IGMP);
1135 if (result) {
1136 if (PIM_DEBUG_IGMP_TRACE)
1137 zlog_debug("%s: del_oif() failed with return=%d",
1138 __func__, result);
1139 return;
1140 }
1141
1142 /*
1143 Feed IGMPv3-gathered local membership information into PIM
1144 per-interface (S,G) state.
1145 */
1146 pim_ifchannel_local_membership_del(group->group_igmp_sock->interface,
1147 &sg);
1148
1149 IGMP_SOURCE_DONT_FORWARDING(source->source_flags);
1150 }
1151
1152 void pim_forward_start(struct pim_ifchannel *ch)
1153 {
1154 struct pim_upstream *up = ch->upstream;
1155
1156 if (PIM_DEBUG_PIM_TRACE) {
1157 char source_str[INET_ADDRSTRLEN];
1158 char group_str[INET_ADDRSTRLEN];
1159 char upstream_str[INET_ADDRSTRLEN];
1160
1161 pim_inet4_dump("<source?>", ch->sg.src, source_str, sizeof(source_str));
1162 pim_inet4_dump("<group?>", ch->sg.grp, group_str, sizeof(group_str));
1163 pim_inet4_dump("<upstream?>", up->upstream_addr, upstream_str, sizeof(upstream_str));
1164 zlog_debug("%s: (S,G)=(%s,%s) oif=%s(%s)",
1165 __PRETTY_FUNCTION__,
1166 source_str, group_str, ch->interface->name, upstream_str);
1167 }
1168
1169 if (!up->channel_oil) {
1170 int input_iface_vif_index = fib_lookup_if_vif_index(up->upstream_addr);
1171 if (input_iface_vif_index < 1) {
1172 if (PIM_DEBUG_PIM_TRACE)
1173 {
1174 char source_str[INET_ADDRSTRLEN];
1175 pim_inet4_dump("<source?>", up->sg.src, source_str, sizeof(source_str));
1176 zlog_debug("%s %s: could not find input interface for source %s",
1177 __FILE__, __PRETTY_FUNCTION__,
1178 source_str);
1179 }
1180 return;
1181 }
1182
1183 up->channel_oil = pim_channel_oil_add(&up->sg,
1184 input_iface_vif_index);
1185 if (!up->channel_oil) {
1186 if (PIM_DEBUG_PIM_TRACE)
1187 zlog_debug("%s %s: could not create OIL for channel (S,G)=%s",
1188 __FILE__, __PRETTY_FUNCTION__,
1189 up->sg_str);
1190 return;
1191 }
1192 }
1193
1194 pim_channel_add_oif(up->channel_oil,
1195 ch->interface,
1196 PIM_OIF_FLAG_PROTO_PIM);
1197 }
1198
1199 void pim_forward_stop(struct pim_ifchannel *ch)
1200 {
1201 struct pim_upstream *up = ch->upstream;
1202
1203 if (PIM_DEBUG_PIM_TRACE) {
1204 zlog_debug("%s: (S,G)=%s oif=%s",
1205 __PRETTY_FUNCTION__,
1206 ch->sg_str, ch->interface->name);
1207 }
1208
1209 if (!up->channel_oil) {
1210 if (PIM_DEBUG_PIM_TRACE)
1211 zlog_debug("%s: (S,G)=%s oif=%s missing channel OIL",
1212 __PRETTY_FUNCTION__,
1213 ch->sg_str, ch->interface->name);
1214
1215 return;
1216 }
1217
1218 del_oif(up->channel_oil,
1219 ch->interface,
1220 PIM_OIF_FLAG_PROTO_PIM);
1221 }