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