]> git.proxmox.com Git - mirror_frr.git/blob - pimd/pim_zebra.c
cd0dd5c4520e0cd21edd8b440409b2723fb03b16
[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(pim_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(pim_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 if (PIM_DEBUG_MROUTE)
892 {
893 char group_str[100];
894 char source_str[100];
895 pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
896 pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str));
897 zlog_warn("%s %s: nonexistent protocol mask %u removed OIF %s (vif_index=%d, min_ttl=%d) from channel (S,G)=(%s,%s)",
898 __FILE__, __PRETTY_FUNCTION__,
899 proto_mask, oif->name, pim_ifp->mroute_vif_index,
900 channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index],
901 source_str, group_str);
902 }
903 return -2;
904 }
905
906 /* Mark that protocol is no longer interested in this OIF */
907 channel_oil->oif_flags[pim_ifp->mroute_vif_index] &= ~proto_mask;
908
909 /* Allow multiple protocols to unsubscribe same interface from
910 channel (S,G) multiple times, by silently ignoring requests while
911 there is at least one protocol interested in the channel */
912 if (channel_oil->oif_flags[pim_ifp->mroute_vif_index] & PIM_OIF_FLAG_PROTO_ANY) {
913
914 /* Check the OIF keeps existing before returning, and only log
915 warning otherwise */
916 if (channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] < 1) {
917 char group_str[100];
918 char source_str[100];
919 pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
920 pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str));
921 zlog_warn("%s %s: protocol mask %u removing nonexistent OIF %s (vif_index=%d, min_ttl=%d) from channel (S,G)=(%s,%s)",
922 __FILE__, __PRETTY_FUNCTION__,
923 proto_mask, oif->name, pim_ifp->mroute_vif_index,
924 channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index],
925 source_str, group_str);
926 }
927
928 return 0;
929 }
930
931 old_ttl = channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index];
932
933 if (old_ttl < 1) {
934 char group_str[100];
935 char source_str[100];
936 pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
937 pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str));
938 zlog_warn("%s %s: interface %s (vif_index=%d) is not output for channel (S,G)=(%s,%s)",
939 __FILE__, __PRETTY_FUNCTION__,
940 oif->name, pim_ifp->mroute_vif_index,
941 source_str, group_str);
942 return -3;
943 }
944
945 channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] = 0;
946
947 if (pim_mroute_add(channel_oil)) {
948 char group_str[100];
949 char source_str[100];
950 pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
951 pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str));
952 zlog_warn("%s %s: could not remove output interface %s (vif_index=%d) from channel (S,G)=(%s,%s)",
953 __FILE__, __PRETTY_FUNCTION__,
954 oif->name, pim_ifp->mroute_vif_index,
955 source_str, group_str);
956
957 channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] = old_ttl;
958 return -4;
959 }
960
961 --channel_oil->oil_size;
962
963 if (channel_oil->oil_size < 1) {
964 if (pim_mroute_del(channel_oil)) {
965 /* just log a warning in case of failure */
966 char group_str[100];
967 char source_str[100];
968 pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
969 pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str));
970 zlog_warn("%s %s: failure removing OIL for channel (S,G)=(%s,%s)",
971 __FILE__, __PRETTY_FUNCTION__,
972 source_str, group_str);
973 }
974 }
975
976 if (PIM_DEBUG_MROUTE) {
977 char group_str[100];
978 char source_str[100];
979 pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
980 pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str));
981 zlog_debug("%s %s: (S,G)=(%s,%s): proto_mask=%u OIF=%s vif_index=%d: DONE",
982 __FILE__, __PRETTY_FUNCTION__,
983 source_str, group_str,
984 proto_mask, oif->name, pim_ifp->mroute_vif_index);
985 }
986
987 return 0;
988 }
989
990 void igmp_source_forward_start(struct igmp_source *source)
991 {
992 struct igmp_group *group;
993 struct prefix_sg sg;
994 int result;
995
996 memset (&sg, 0, sizeof (struct prefix_sg));
997 sg.src = source->source_addr;
998 sg.grp = source->source_group->group_addr;
999
1000 if (PIM_DEBUG_IGMP_TRACE) {
1001 zlog_debug("%s: (S,G)=%s igmp_sock=%d oif=%s fwd=%d",
1002 __PRETTY_FUNCTION__,
1003 pim_str_sg_dump (&sg),
1004 source->source_group->group_igmp_sock->fd,
1005 source->source_group->group_igmp_sock->interface->name,
1006 IGMP_SOURCE_TEST_FORWARDING(source->source_flags));
1007 }
1008
1009 /* Prevent IGMP interface from installing multicast route multiple
1010 times */
1011 if (IGMP_SOURCE_TEST_FORWARDING(source->source_flags)) {
1012 return;
1013 }
1014
1015 group = source->source_group;
1016
1017 if (!source->source_channel_oil) {
1018 struct in_addr vif_source;
1019 struct pim_interface *pim_oif;
1020
1021 if (!pim_rp_set_upstream_addr (&vif_source, source->source_addr, sg.grp))
1022 return;
1023
1024 int input_iface_vif_index = fib_lookup_if_vif_index(vif_source);
1025 if (input_iface_vif_index < 1) {
1026 char source_str[100];
1027 pim_inet4_dump("<source?>", source->source_addr, source_str, sizeof(source_str));
1028 zlog_warn("%s %s: could not find input interface for source %s",
1029 __FILE__, __PRETTY_FUNCTION__,
1030 source_str);
1031 return;
1032 }
1033
1034 /*
1035 Protect IGMP against adding looped MFC entries created by both
1036 source and receiver attached to the same interface. See TODO
1037 T22.
1038 */
1039 pim_oif = source->source_group->group_igmp_sock->interface->info;
1040 if (!pim_oif) {
1041 zlog_warn("%s: multicast not enabled on oif=%s ?",
1042 __PRETTY_FUNCTION__,
1043 source->source_group->group_igmp_sock->interface->name);
1044 return;
1045 }
1046 if (pim_oif->mroute_vif_index < 1) {
1047 zlog_warn("%s %s: oif=%s vif_index=%d < 1",
1048 __FILE__, __PRETTY_FUNCTION__,
1049 source->source_group->group_igmp_sock->interface->name,
1050 pim_oif->mroute_vif_index);
1051 return;
1052 }
1053 if (input_iface_vif_index == pim_oif->mroute_vif_index) {
1054 /* ignore request for looped MFC entry */
1055 if (PIM_DEBUG_IGMP_TRACE) {
1056 zlog_debug("%s: ignoring request for looped MFC entry (S,G)=%s: igmp_sock=%d oif=%s vif_index=%d",
1057 __PRETTY_FUNCTION__,
1058 pim_str_sg_dump (&sg),
1059 source->source_group->group_igmp_sock->fd,
1060 source->source_group->group_igmp_sock->interface->name,
1061 input_iface_vif_index);
1062 }
1063 return;
1064 }
1065
1066 source->source_channel_oil = pim_channel_oil_add(&sg,
1067 input_iface_vif_index);
1068 if (!source->source_channel_oil) {
1069 zlog_warn("%s %s: could not create OIL for channel (S,G)=%s",
1070 __FILE__, __PRETTY_FUNCTION__,
1071 pim_str_sg_dump (&sg));
1072 return;
1073 }
1074 }
1075
1076 result = pim_channel_add_oif(source->source_channel_oil,
1077 group->group_igmp_sock->interface,
1078 PIM_OIF_FLAG_PROTO_IGMP);
1079 if (result) {
1080 zlog_warn("%s: add_oif() failed with return=%d",
1081 __func__, result);
1082 return;
1083 }
1084
1085 /*
1086 Feed IGMPv3-gathered local membership information into PIM
1087 per-interface (S,G) state.
1088 */
1089 pim_ifchannel_local_membership_add(group->group_igmp_sock->interface, &sg);
1090
1091 IGMP_SOURCE_DO_FORWARDING(source->source_flags);
1092 }
1093
1094 /*
1095 igmp_source_forward_stop: stop fowarding, but keep the source
1096 igmp_source_delete: stop fowarding, and delete the source
1097 */
1098 void igmp_source_forward_stop(struct igmp_source *source)
1099 {
1100 struct igmp_group *group;
1101 struct prefix_sg sg;
1102 int result;
1103
1104 memset (&sg, 0, sizeof (struct prefix_sg));
1105 sg.src = source->source_addr;
1106 sg.grp = source->source_group->group_addr;
1107
1108 if (PIM_DEBUG_IGMP_TRACE) {
1109 zlog_debug("%s: (S,G)=%s igmp_sock=%d oif=%s fwd=%d",
1110 __PRETTY_FUNCTION__,
1111 pim_str_sg_dump (&sg),
1112 source->source_group->group_igmp_sock->fd,
1113 source->source_group->group_igmp_sock->interface->name,
1114 IGMP_SOURCE_TEST_FORWARDING(source->source_flags));
1115 }
1116
1117 /* Prevent IGMP interface from removing multicast route multiple
1118 times */
1119 if (!IGMP_SOURCE_TEST_FORWARDING(source->source_flags)) {
1120 return;
1121 }
1122
1123 group = source->source_group;
1124
1125 /*
1126 It appears that in certain circumstances that
1127 igmp_source_forward_stop is called when IGMP forwarding
1128 was not enabled in oif_flags for this outgoing interface.
1129 Possibly because of multiple calls. When that happens, we
1130 enter the below if statement and this function returns early
1131 which in turn triggers the calling function to assert.
1132 Making the call to del_oif and ignoring the return code
1133 fixes the issue without ill effect, similar to
1134 pim_forward_stop below.
1135 */
1136 result = del_oif(source->source_channel_oil,
1137 group->group_igmp_sock->interface,
1138 PIM_OIF_FLAG_PROTO_IGMP);
1139 if (result) {
1140 zlog_warn("%s: del_oif() failed with return=%d",
1141 __func__, result);
1142 return;
1143 }
1144
1145 /*
1146 Feed IGMPv3-gathered local membership information into PIM
1147 per-interface (S,G) state.
1148 */
1149 pim_ifchannel_local_membership_del(group->group_igmp_sock->interface,
1150 &sg);
1151
1152 IGMP_SOURCE_DONT_FORWARDING(source->source_flags);
1153 }
1154
1155 void pim_forward_start(struct pim_ifchannel *ch)
1156 {
1157 struct pim_upstream *up = ch->upstream;
1158
1159 if (PIM_DEBUG_PIM_TRACE) {
1160 char source_str[100];
1161 char group_str[100];
1162 char upstream_str[100];
1163
1164 pim_inet4_dump("<source?>", ch->sg.src, source_str, sizeof(source_str));
1165 pim_inet4_dump("<group?>", ch->sg.grp, group_str, sizeof(group_str));
1166 pim_inet4_dump("<upstream?>", up->upstream_addr, upstream_str, sizeof(upstream_str));
1167 zlog_debug("%s: (S,G)=(%s,%s) oif=%s(%s)",
1168 __PRETTY_FUNCTION__,
1169 source_str, group_str, ch->interface->name, upstream_str);
1170 }
1171
1172 if (!up->channel_oil) {
1173 int input_iface_vif_index = fib_lookup_if_vif_index(up->upstream_addr);
1174 if (input_iface_vif_index < 1) {
1175 char source_str[100];
1176 pim_inet4_dump("<source?>", up->sg.src, source_str, sizeof(source_str));
1177 zlog_warn("%s %s: could not find input interface for source %s",
1178 __FILE__, __PRETTY_FUNCTION__,
1179 source_str);
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 zlog_warn("%s %s: could not create OIL for channel (S,G)=%s",
1187 __FILE__, __PRETTY_FUNCTION__,
1188 pim_str_sg_dump (&up->sg));
1189 return;
1190 }
1191 }
1192
1193 pim_channel_add_oif(up->channel_oil,
1194 ch->interface,
1195 PIM_OIF_FLAG_PROTO_PIM);
1196 }
1197
1198 void pim_forward_stop(struct pim_ifchannel *ch)
1199 {
1200 struct pim_upstream *up = ch->upstream;
1201
1202 if (PIM_DEBUG_PIM_TRACE) {
1203 zlog_debug("%s: (S,G)=%s oif=%s",
1204 __PRETTY_FUNCTION__,
1205 pim_str_sg_dump (&ch->sg), ch->interface->name);
1206 }
1207
1208 if (!up->channel_oil) {
1209 zlog_warn("%s: (S,G)=%s oif=%s missing channel OIL",
1210 __PRETTY_FUNCTION__,
1211 pim_str_sg_dump(&ch->sg), ch->interface->name);
1212
1213 return;
1214 }
1215
1216 del_oif(up->channel_oil,
1217 ch->interface,
1218 PIM_OIF_FLAG_PROTO_PIM);
1219 }