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