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