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