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