]> git.proxmox.com Git - mirror_frr.git/blame - pimd/pim_zebra.c
Merge pull request #4622 from donaldsharp/import_table_fix
[mirror_frr.git] / pimd / pim_zebra.c
CommitLineData
12e41d03 1/*
896014f4
DL
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 along
16 * with this program; see the file COPYING; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
12e41d03
DL
19
20#include <zebra.h>
21
12e41d03
DL
22#include "if.h"
23#include "log.h"
24#include "prefix.h"
25#include "zclient.h"
26#include "stream.h"
27#include "network.h"
dfe43e25
DW
28#include "vty.h"
29#include "plist.h"
ba4eb1bc 30#include "lib/bfd.h"
12e41d03
DL
31
32#include "pimd.h"
33#include "pim_pim.h"
34#include "pim_zebra.h"
35#include "pim_iface.h"
36#include "pim_str.h"
37#include "pim_oil.h"
38#include "pim_rpf.h"
39#include "pim_time.h"
40#include "pim_join.h"
41#include "pim_zlookup.h"
42#include "pim_ifchannel.h"
8f5f5e91 43#include "pim_rp.h"
2560106c 44#include "pim_igmpv3.h"
982bff89 45#include "pim_jp_agg.h"
1bc98276 46#include "pim_nht.h"
15a5dafe 47#include "pim_ssm.h"
af7b561b 48#include "pim_vxlan.h"
12e41d03
DL
49
50#undef PIM_DEBUG_IFADDR_DUMP
51#define PIM_DEBUG_IFADDR_DUMP
52
38f4935a
DS
53static struct zclient *zclient = NULL;
54
12e41d03 55
12e41d03 56/* Router-id update message from zebra. */
121f9dee 57static int pim_router_id_update_zebra(ZAPI_CALLBACK_ARGS)
12e41d03 58{
d62a17ae 59 struct prefix router_id;
12e41d03 60
d62a17ae 61 zebra_router_id_update_read(zclient->ibuf, &router_id);
12e41d03 62
d62a17ae 63 return 0;
12e41d03
DL
64}
65
121f9dee 66static int pim_zebra_if_add(ZAPI_CALLBACK_ARGS)
12e41d03 67{
d62a17ae 68 struct interface *ifp;
26bb1fd5 69 struct pim_instance *pim;
d62a17ae 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
26bb1fd5 79 pim = pim_get_pim_instance(vrf_id);
d62a17ae 80 if (PIM_DEBUG_ZEBRA) {
81 zlog_debug(
87ad28f4 82 "%s: %s index %d(%u) flags %ld metric %d mtu %d operative %d",
e0ae31b8 83 __PRETTY_FUNCTION__, ifp->name, ifp->ifindex, vrf_id,
d62a17ae 84 (long)ifp->flags, ifp->metric, ifp->mtu,
85 if_is_operative(ifp));
86 }
87
26bb1fd5
DS
88 if (if_is_operative(ifp)) {
89 struct pim_interface *pim_ifp;
90
91 pim_ifp = ifp->info;
92 /*
93 * If we have a pim_ifp already and this is an if_add
94 * that means that we probably have a vrf move event
95 * If that is the case, set the proper vrfness.
96 */
97 if (pim_ifp)
98 pim_ifp->pim = pim;
d62a17ae 99 pim_if_addr_add_all(ifp);
26bb1fd5 100 }
d62a17ae 101
90133de6
DS
102 /*
103 * If we are a vrf device that is up, open up the pim_socket for
104 * listening
105 * to incoming pim messages irrelevant if the user has configured us
106 * for pim or not.
107 */
108 if (pim_if_is_vrf_device(ifp)) {
109 struct pim_interface *pim_ifp;
110
111 if (!ifp->info) {
b1891fa0
AK
112 pim_ifp = pim_if_new(ifp, false, false, false,
113 false /*vxlan_term*/);
90133de6
DS
114 ifp->info = pim_ifp;
115 }
116
117 pim_sock_add(ifp);
118 }
119
0a2dcc1c
AK
120 if (!strncmp(ifp->name, PIM_VXLAN_TERM_DEV_NAME,
121 sizeof(PIM_VXLAN_TERM_DEV_NAME)))
122 pim_vxlan_add_term_dev(pim, ifp);
123
d62a17ae 124 return 0;
12e41d03
DL
125}
126
121f9dee 127static int pim_zebra_if_del(ZAPI_CALLBACK_ARGS)
12e41d03 128{
d62a17ae 129 struct interface *ifp;
0a2dcc1c 130 struct pim_instance *pim;
d62a17ae 131
132 /*
133 zebra api adds/dels interfaces using the same call
134 interface_add_read below, see comments in lib/zclient.c
135
136 comments in lib/zclient.c seem to indicate that calling
137 zebra_interface_add_read is the correct call, but that
138 results in an attemted out of bounds read which causes
139 pimd to assert. Other clients use zebra_interface_state_read
140 and it appears to work just fine.
141 */
142 ifp = zebra_interface_state_read(zclient->ibuf, vrf_id);
143 if (!ifp)
144 return 0;
145
146 if (PIM_DEBUG_ZEBRA) {
147 zlog_debug(
87ad28f4 148 "%s: %s index %d(%u) flags %ld metric %d mtu %d operative %d",
e0ae31b8 149 __PRETTY_FUNCTION__, ifp->name, ifp->ifindex, vrf_id,
d62a17ae 150 (long)ifp->flags, ifp->metric, ifp->mtu,
151 if_is_operative(ifp));
152 }
153
154 if (!if_is_operative(ifp))
155 pim_if_addr_del_all(ifp);
156
9d6c33ea
DS
157 if_set_index(ifp, IFINDEX_INTERNAL);
158
0a2dcc1c
AK
159 pim = pim_get_pim_instance(vrf_id);
160 if (pim && pim->vxlan.term_if == ifp)
161 pim_vxlan_del_term_dev(pim);
162
d62a17ae 163 return 0;
12e41d03
DL
164}
165
121f9dee 166static int pim_zebra_if_state_up(ZAPI_CALLBACK_ARGS)
12e41d03 167{
26bb1fd5 168 struct pim_instance *pim;
d62a17ae 169 struct interface *ifp;
e0ae31b8 170 uint32_t table_id;
d62a17ae 171
172 /*
173 zebra api notifies interface up/down events by using the same call
174 zebra_interface_state_read below, see comments in lib/zclient.c
175 */
176 ifp = zebra_interface_state_read(zclient->ibuf, vrf_id);
177 if (!ifp)
178 return 0;
179
180 if (PIM_DEBUG_ZEBRA) {
181 zlog_debug(
87ad28f4 182 "%s: %s index %d(%u) flags %ld metric %d mtu %d operative %d",
e0ae31b8 183 __PRETTY_FUNCTION__, ifp->name, ifp->ifindex, vrf_id,
d62a17ae 184 (long)ifp->flags, ifp->metric, ifp->mtu,
185 if_is_operative(ifp));
186 }
187
26bb1fd5 188 pim = pim_get_pim_instance(vrf_id);
d62a17ae 189 if (if_is_operative(ifp)) {
26bb1fd5
DS
190 struct pim_interface *pim_ifp;
191
192 pim_ifp = ifp->info;
193 /*
194 * If we have a pim_ifp already and this is an if_add
195 * that means that we probably have a vrf move event
196 * If that is the case, set the proper vrfness.
197 */
198 if (pim_ifp)
199 pim_ifp->pim = pim;
200
d62a17ae 201 /*
202 pim_if_addr_add_all() suffices for bringing up both IGMP and
203 PIM
204 */
205 pim_if_addr_add_all(ifp);
206 }
207
e0ae31b8
DS
208 /*
209 * If we have a pimreg device callback and it's for a specific
210 * table set the master appropriately
211 */
0651460e 212 if (sscanf(ifp->name, "pimreg%" SCNu32, &table_id) == 1) {
e0ae31b8 213 struct vrf *vrf;
a2addae8 214 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
e0ae31b8 215 if ((table_id == vrf->data.l.table_id)
a36898e7 216 && (ifp->vrf_id != vrf->vrf_id)) {
e0ae31b8 217 struct interface *master = if_lookup_by_name(
a36898e7 218 vrf->name, vrf->vrf_id);
e691f179
DS
219
220 if (!master) {
996c9314
LB
221 zlog_debug(
222 "%s: Unable to find Master interface for %s",
223 __PRETTY_FUNCTION__, vrf->name);
e691f179
DS
224 return 0;
225 }
e0ae31b8
DS
226 zclient_interface_set_master(zclient, master,
227 ifp);
228 }
229 }
230 }
d62a17ae 231 return 0;
12e41d03
DL
232}
233
121f9dee 234static int pim_zebra_if_state_down(ZAPI_CALLBACK_ARGS)
12e41d03 235{
d62a17ae 236 struct interface *ifp;
237
238 /*
239 zebra api notifies interface up/down events by using the same call
240 zebra_interface_state_read below, see comments in lib/zclient.c
241 */
242 ifp = zebra_interface_state_read(zclient->ibuf, vrf_id);
243 if (!ifp)
244 return 0;
245
246 if (PIM_DEBUG_ZEBRA) {
247 zlog_debug(
87ad28f4 248 "%s: %s index %d(%u) flags %ld metric %d mtu %d operative %d",
e0ae31b8 249 __PRETTY_FUNCTION__, ifp->name, ifp->ifindex, vrf_id,
d62a17ae 250 (long)ifp->flags, ifp->metric, ifp->mtu,
251 if_is_operative(ifp));
252 }
253
254 if (!if_is_operative(ifp)) {
255 pim_ifchannel_delete_all(ifp);
256 /*
257 pim_if_addr_del_all() suffices for shutting down IGMP,
258 but not for shutting down PIM
259 */
260 pim_if_addr_del_all(ifp);
261
262 /*
263 pim_sock_delete() closes the socket, stops read and timer
264 threads,
265 and kills all neighbors.
266 */
267 if (ifp->info) {
268 pim_sock_delete(ifp, "link down");
269 }
270 }
271
272 if (ifp->info)
273 pim_if_del_vif(ifp);
274
275 return 0;
12e41d03
DL
276}
277
121f9dee 278static int pim_zebra_interface_vrf_update(ZAPI_CALLBACK_ARGS)
ee568318
DS
279{
280 struct interface *ifp;
281 vrf_id_t new_vrf_id;
282
283 ifp = zebra_interface_vrf_update_read(zclient->ibuf, vrf_id,
284 &new_vrf_id);
285 if (!ifp)
286 return 0;
287
288 if (PIM_DEBUG_ZEBRA)
289 zlog_debug("%s: %s updating from %u to %u",
290 __PRETTY_FUNCTION__,
291 ifp->name, vrf_id, new_vrf_id);
292
a36898e7 293 if_update_to_new_vrf(ifp, new_vrf_id);
ee568318
DS
294
295 return 0;
296}
297
12e41d03
DL
298#ifdef PIM_DEBUG_IFADDR_DUMP
299static void dump_if_address(struct interface *ifp)
300{
d62a17ae 301 struct connected *ifc;
302 struct listnode *node;
303
304 zlog_debug("%s %s: interface %s addresses:", __FILE__,
305 __PRETTY_FUNCTION__, ifp->name);
306
307 for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) {
308 struct prefix *p = ifc->address;
309
310 if (p->family != AF_INET)
311 continue;
312
313 zlog_debug("%s %s: interface %s address %s %s", __FILE__,
314 __PRETTY_FUNCTION__, ifp->name,
315 inet_ntoa(p->u.prefix4),
316 CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY)
317 ? "secondary"
318 : "primary");
319 }
12e41d03
DL
320}
321#endif
322
121f9dee 323static int pim_zebra_if_address_add(ZAPI_CALLBACK_ARGS)
12e41d03 324{
d62a17ae 325 struct connected *c;
326 struct prefix *p;
327 struct pim_interface *pim_ifp;
26bb1fd5 328 struct pim_instance *pim;
d62a17ae 329
330 /*
331 zebra api notifies address adds/dels events by using the same call
332 interface_add_read below, see comments in lib/zclient.c
333
334 zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_ADD, ...)
335 will add address to interface list by calling
336 connected_add_by_prefix()
337 */
121f9dee 338 c = zebra_interface_address_read(cmd, zclient->ibuf, vrf_id);
d62a17ae 339 if (!c)
340 return 0;
341
342 pim_ifp = c->ifp->info;
343 p = c->address;
344
345 if (PIM_DEBUG_ZEBRA) {
346 char buf[BUFSIZ];
347 prefix2str(p, buf, BUFSIZ);
87ad28f4 348 zlog_debug("%s: %s(%u) connected IP address %s flags %u %s",
e0ae31b8 349 __PRETTY_FUNCTION__, c->ifp->name, vrf_id, buf,
996c9314
LB
350 c->flags,
351 CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY)
352 ? "secondary"
353 : "primary");
d62a17ae 354
12e41d03 355#ifdef PIM_DEBUG_IFADDR_DUMP
d62a17ae 356 dump_if_address(c->ifp);
12e41d03 357#endif
d62a17ae 358 }
12e41d03 359
d62a17ae 360 if (!CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY)) {
361 /* trying to add primary address */
12e41d03 362
d62a17ae 363 struct in_addr primary_addr = pim_find_primary_addr(c->ifp);
364 if (p->family != AF_INET
365 || primary_addr.s_addr != p->u.prefix4.s_addr) {
366 if (PIM_DEBUG_ZEBRA) {
367 /* but we had a primary address already */
12e41d03 368
d62a17ae 369 char buf[BUFSIZ];
12e41d03 370
d62a17ae 371 prefix2str(p, buf, BUFSIZ);
12e41d03 372
d62a17ae 373 zlog_warn(
374 "%s: %s : forcing secondary flag on %s",
375 __PRETTY_FUNCTION__, c->ifp->name, buf);
376 }
377 SET_FLAG(c->flags, ZEBRA_IFA_SECONDARY);
378 }
379 }
12e41d03 380
d62a17ae 381 pim_if_addr_add(c);
26bb1fd5
DS
382 if (pim_ifp) {
383 pim = pim_get_pim_instance(vrf_id);
384 pim_ifp->pim = pim;
385
d62a17ae 386 pim_rp_check_on_if_add(pim_ifp);
26bb1fd5 387 }
12e41d03 388
d62a17ae 389 if (if_is_loopback(c->ifp)) {
f4e14fdb 390 struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
d62a17ae 391 struct interface *ifp;
d8424057 392
451fda4f 393 FOR_ALL_INTERFACES (vrf, ifp) {
d62a17ae 394 if (!if_is_loopback(ifp) && if_is_operative(ifp))
395 pim_if_addr_add_all(ifp);
396 }
397 }
d8424057 398
d62a17ae 399 return 0;
12e41d03
DL
400}
401
121f9dee 402static int pim_zebra_if_address_del(ZAPI_CALLBACK_ARGS)
12e41d03 403{
d62a17ae 404 struct connected *c;
405 struct prefix *p;
fec883d9 406 struct vrf *vrf = vrf_lookup_by_id(vrf_id);
819f099b
DS
407 struct pim_instance *pim;
408
409 if (!vrf)
410 return 0;
411 pim = vrf->info;
d62a17ae 412
413 /*
414 zebra api notifies address adds/dels events by using the same call
415 interface_add_read below, see comments in lib/zclient.c
416
417 zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_DELETE, ...)
418 will remove address from interface list by calling
419 connected_delete_by_prefix()
420 */
121f9dee 421 c = zebra_interface_address_read(cmd, zclient->ibuf, vrf_id);
d62a17ae 422 if (!c)
423 return 0;
424
425 p = c->address;
426 if (p->family == AF_INET) {
427 if (PIM_DEBUG_ZEBRA) {
428 char buf[BUFSIZ];
429 prefix2str(p, buf, BUFSIZ);
430 zlog_debug(
87ad28f4 431 "%s: %s(%u) disconnected IP address %s flags %u %s",
e0ae31b8 432 __PRETTY_FUNCTION__, c->ifp->name, vrf_id, buf,
d62a17ae 433 c->flags,
434 CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY)
435 ? "secondary"
436 : "primary");
6233f087 437
12e41d03 438#ifdef PIM_DEBUG_IFADDR_DUMP
d62a17ae 439 dump_if_address(c->ifp);
12e41d03 440#endif
d62a17ae 441 }
12e41d03 442
d62a17ae 443 pim_if_addr_del(c, 0);
fec883d9
DS
444 pim_rp_setup(pim);
445 pim_i_am_rp_re_evaluate(pim);
d62a17ae 446 }
6233f087 447
d62a17ae 448 connected_free(c);
449 return 0;
12e41d03
DL
450}
451
74389231
DS
452void pim_zebra_update_all_interfaces(struct pim_instance *pim)
453{
454 struct interface *ifp;
455
456 FOR_ALL_INTERFACES (pim->vrf, ifp) {
457 struct pim_interface *pim_ifp = ifp->info;
458 struct pim_iface_upstream_switch *us;
459 struct listnode *node;
460
461 if (!pim_ifp)
462 continue;
463
464 for (ALL_LIST_ELEMENTS_RO(pim_ifp->upstream_switch_list, node,
465 us)) {
466 struct pim_rpf rpf;
467
468 rpf.source_nexthop.interface = ifp;
469 rpf.rpf_addr.u.prefix4 = us->address;
470 pim_joinprune_send(&rpf, us->us);
471 pim_jp_agg_clear_group(us->us);
472 }
473 }
474}
475
cc67ccf9
DS
476void pim_zebra_upstream_rpf_changed(struct pim_instance *pim,
477 struct pim_upstream *up,
478 struct pim_rpf *old)
479{
1250cb5d
SP
480 if (old->source_nexthop.interface) {
481 struct pim_neighbor *nbr;
cc67ccf9 482
1250cb5d
SP
483 nbr = pim_neighbor_find(old->source_nexthop.interface,
484 old->rpf_addr.u.prefix4);
485 if (nbr)
486 pim_jp_agg_remove_group(nbr->upstream_jp_agg, up);
cc67ccf9 487
cc67ccf9 488 /*
1250cb5d
SP
489 * We have detected a case where we might need
490 * to rescan the inherited o_list so do it.
cc67ccf9 491 */
1250cb5d
SP
492 if (up->channel_oil->oil_inherited_rescan) {
493 pim_upstream_inherited_olist_decide(pim, up);
494 up->channel_oil->oil_inherited_rescan = 0;
495 }
cc67ccf9 496
1250cb5d
SP
497 if (up->join_state == PIM_UPSTREAM_JOINED) {
498 /*
499 * If we come up real fast we can be here
500 * where the mroute has not been installed
501 * so install it.
502 */
503 if (!up->channel_oil->installed)
504 pim_mroute_add(up->channel_oil,
505 __PRETTY_FUNCTION__);
506
507 /*
508 * RFC 4601: 4.5.7. Sending (S,G)
509 * Join/Prune Messages
510 *
511 * Transitions from Joined State
512 *
513 * RPF'(S,G) changes not due to an Assert
514 *
515 * The upstream (S,G) state machine remains
516 * in Joined state. Send Join(S,G) to the new
517 * upstream neighbor, which is the new value
518 * of RPF'(S,G). Send Prune(S,G) to the old
519 * upstream neighbor, which is the old value
520 * of RPF'(S,G). Set the Join Timer (JT) to
521 * expire after t_periodic seconds.
522 */
523 pim_jp_agg_switch_interface(old, &up->rpf, up);
524
525 pim_upstream_join_timer_restart(up, old);
526 } /* up->join_state == PIM_UPSTREAM_JOINED */
527 }
528
529 else {
cc67ccf9 530 /*
1250cb5d
SP
531 * We have detected a case where we might need
532 * to rescan the inherited o_list so do it.
cc67ccf9 533 */
1250cb5d
SP
534 if (up->channel_oil->oil_inherited_rescan) {
535 pim_upstream_inherited_olist_decide(pim, up);
536 up->channel_oil->oil_inherited_rescan = 0;
537 }
cc67ccf9 538
1250cb5d
SP
539 if (!up->channel_oil->installed)
540 pim_mroute_add(up->channel_oil, __PRETTY_FUNCTION__);
541 }
cc67ccf9 542
1250cb5d
SP
543 /* FIXME can join_desired actually be changed by pim_rpf_update()
544 * returning PIM_RPF_CHANGED ?
545 */
cc67ccf9
DS
546 pim_upstream_update_join_desired(pim, up);
547}
548
121f9dee 549static int pim_zebra_vxlan_sg_proc(ZAPI_CALLBACK_ARGS)
af7b561b
AK
550{
551 struct stream *s;
552 struct pim_instance *pim;
553 struct prefix_sg sg;
554
555 pim = pim_get_pim_instance(vrf_id);
556 if (!pim)
557 return 0;
558
559 s = zclient->ibuf;
560
561 sg.family = AF_INET;
562 sg.prefixlen = stream_getl(s);
563 stream_get(&sg.src.s_addr, s, sg.prefixlen);
564 stream_get(&sg.grp.s_addr, s, sg.prefixlen);
565
566 if (PIM_DEBUG_ZEBRA) {
567 char sg_str[PIM_SG_LEN];
568
569 pim_str_sg_set(&sg, sg_str);
570 zlog_debug("%u:recv SG %s %s", vrf_id,
121f9dee 571 (cmd == ZEBRA_VXLAN_SG_ADD)?"add":"del",
af7b561b
AK
572 sg_str);
573 }
574
121f9dee 575 if (cmd == ZEBRA_VXLAN_SG_ADD)
af7b561b
AK
576 pim_vxlan_sg_add(pim, &sg);
577 else
578 pim_vxlan_sg_del(pim, &sg);
579
580 return 0;
581}
582
d62a17ae 583void pim_scan_individual_oil(struct channel_oil *c_oil, int in_vif_index)
12e41d03 584{
d62a17ae 585 struct in_addr vif_source;
586 int input_iface_vif_index;
587 int old_vif_index;
588
732c209c 589 pim_rp_set_upstream_addr(c_oil->pim, &vif_source,
d9c9a9ee 590 c_oil->oil.mfcc_origin,
732c209c 591 c_oil->oil.mfcc_mcastgrp);
d62a17ae 592
593 if (in_vif_index)
594 input_iface_vif_index = in_vif_index;
595 else {
596 struct prefix src, grp;
597
598 src.family = AF_INET;
599 src.prefixlen = IPV4_MAX_BITLEN;
600 src.u.prefix4 = vif_source;
601 grp.family = AF_INET;
602 grp.prefixlen = IPV4_MAX_BITLEN;
603 grp.u.prefix4 = c_oil->oil.mfcc_mcastgrp;
604
605 if (PIM_DEBUG_ZEBRA) {
606 char source_str[INET_ADDRSTRLEN];
607 char group_str[INET_ADDRSTRLEN];
608 pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin,
609 source_str, sizeof(source_str));
610 pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp,
611 group_str, sizeof(group_str));
612 zlog_debug(
a895ac30 613 "%s: channel_oil (%s,%s) upstream info is not present.",
d62a17ae 614 __PRETTY_FUNCTION__, source_str, group_str);
615 }
616 input_iface_vif_index = pim_ecmp_fib_lookup_if_vif_index(
b938537b 617 c_oil->pim, &src, &grp);
d62a17ae 618 }
619
620 if (input_iface_vif_index < 1) {
621 if (PIM_DEBUG_ZEBRA) {
622 char source_str[INET_ADDRSTRLEN];
623 char group_str[INET_ADDRSTRLEN];
624 pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin,
625 source_str, sizeof(source_str));
626 pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp,
627 group_str, sizeof(group_str));
628 zlog_debug(
629 "%s %s: could not find input interface(%d) for (S,G)=(%s,%s)",
630 __FILE__, __PRETTY_FUNCTION__,
631 c_oil->oil.mfcc_parent, source_str, group_str);
632 }
633 pim_mroute_del(c_oil, __PRETTY_FUNCTION__);
634 return;
635 }
636
637 if (input_iface_vif_index == c_oil->oil.mfcc_parent) {
638 if (!c_oil->installed)
639 pim_mroute_add(c_oil, __PRETTY_FUNCTION__);
640
641 /* RPF unchanged */
642 return;
643 }
644
645 if (PIM_DEBUG_ZEBRA) {
7cfc7bcf
DS
646 struct interface *old_iif = pim_if_find_by_vif_index(
647 c_oil->pim, c_oil->oil.mfcc_parent);
648 struct interface *new_iif = pim_if_find_by_vif_index(
649 c_oil->pim, input_iface_vif_index);
d62a17ae 650 char source_str[INET_ADDRSTRLEN];
651 char group_str[INET_ADDRSTRLEN];
652 pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str,
653 sizeof(source_str));
654 pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str,
655 sizeof(group_str));
656 zlog_debug(
657 "%s %s: (S,G)=(%s,%s) input interface changed from %s vif_index=%d to %s vif_index=%d",
658 __FILE__, __PRETTY_FUNCTION__, source_str, group_str,
97f03dde
DS
659 (old_iif) ? old_iif->name : "<old_iif?>",
660 c_oil->oil.mfcc_parent,
661 (new_iif) ? new_iif->name : "<new_iif?>",
d62a17ae 662 input_iface_vif_index);
663 }
664
665 /* new iif loops to existing oif ? */
666 if (c_oil->oil.mfcc_ttls[input_iface_vif_index]) {
7cfc7bcf
DS
667 struct interface *new_iif = pim_if_find_by_vif_index(
668 c_oil->pim, input_iface_vif_index);
d62a17ae 669
670 if (PIM_DEBUG_ZEBRA) {
671 char source_str[INET_ADDRSTRLEN];
672 char group_str[INET_ADDRSTRLEN];
673 pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin,
674 source_str, sizeof(source_str));
675 pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp,
676 group_str, sizeof(group_str));
677 zlog_debug(
678 "%s %s: (S,G)=(%s,%s) new iif loops to existing oif: %s vif_index=%d",
679 __FILE__, __PRETTY_FUNCTION__, source_str,
97f03dde
DS
680 group_str,
681 (new_iif) ? new_iif->name : "<new_iif?>",
d62a17ae 682 input_iface_vif_index);
683 }
684 }
685
686 /* update iif vif_index */
687 old_vif_index = c_oil->oil.mfcc_parent;
688 c_oil->oil.mfcc_parent = input_iface_vif_index;
689
690 /* update kernel multicast forwarding cache (MFC) */
691 if (pim_mroute_add(c_oil, __PRETTY_FUNCTION__)) {
692 if (PIM_DEBUG_MROUTE) {
693 /* just log warning */
7cfc7bcf
DS
694 struct interface *old_iif = pim_if_find_by_vif_index(
695 c_oil->pim, old_vif_index);
696 struct interface *new_iif = pim_if_find_by_vif_index(
697 c_oil->pim, input_iface_vif_index);
d62a17ae 698 char source_str[INET_ADDRSTRLEN];
699 char group_str[INET_ADDRSTRLEN];
700 pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin,
701 source_str, sizeof(source_str));
702 pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp,
703 group_str, sizeof(group_str));
704 zlog_debug(
705 "%s %s: (S,G)=(%s,%s) failure updating input interface from %s vif_index=%d to %s vif_index=%d",
706 __FILE__, __PRETTY_FUNCTION__, source_str,
707 group_str,
708 old_iif ? old_iif->name : "<old_iif?>",
709 c_oil->oil.mfcc_parent,
710 new_iif ? new_iif->name : "<new_iif?>",
711 input_iface_vif_index);
712 }
713 }
8a67a996
DS
714}
715
da11e325 716void pim_scan_oil(struct pim_instance *pim)
8a67a996 717{
d62a17ae 718 struct listnode *node;
719 struct listnode *nextnode;
720 struct channel_oil *c_oil;
721 ifindex_t ifindex;
722 int vif_index = 0;
723
bfc92019
DS
724 pim->scan_oil_last = pim_time_monotonic_sec();
725 ++pim->scan_oil_events;
d62a17ae 726
da11e325
DS
727 for (ALL_LIST_ELEMENTS(pim->channel_oil_list, node, nextnode, c_oil)) {
728 if (c_oil->up && c_oil->up->rpf.source_nexthop.interface) {
729 ifindex = c_oil->up->rpf.source_nexthop
730 .interface->ifindex;
731 vif_index =
732 pim_if_find_vifindex_by_ifindex(pim, ifindex);
733 /* Pass Current selected NH vif index to mroute
734 * download */
735 if (vif_index)
736 pim_scan_individual_oil(c_oil, vif_index);
737 } else
738 pim_scan_individual_oil(c_oil, 0);
d62a17ae 739 }
12e41d03
DL
740}
741
742static int on_rpf_cache_refresh(struct thread *t)
743{
da11e325
DS
744 struct pim_instance *pim = THREAD_ARG(t);
745
d62a17ae 746 /* update kernel multicast forwarding cache (MFC) */
da11e325 747 pim_scan_oil(pim);
12e41d03 748
bfc92019
DS
749 pim->rpf_cache_refresh_last = pim_time_monotonic_sec();
750 ++pim->rpf_cache_refresh_events;
12e41d03 751
d62a17ae 752 // It is called as part of pim_neighbor_add
753 // pim_rp_setup ();
754 return 0;
12e41d03
DL
755}
756
da11e325 757void sched_rpf_cache_refresh(struct pim_instance *pim)
12e41d03 758{
bfc92019 759 ++pim->rpf_cache_refresh_requests;
12e41d03 760
bfc92019 761 pim_rpf_set_refresh_time(pim);
e71bf8f7 762
da11e325 763 if (pim->rpf_cache_refresher) {
d62a17ae 764 /* Refresh timer is already running */
765 return;
766 }
12e41d03 767
d62a17ae 768 /* Start refresh timer */
12e41d03 769
d62a17ae 770 if (PIM_DEBUG_ZEBRA) {
771 zlog_debug("%s: triggering %ld msec timer", __PRETTY_FUNCTION__,
da03883e 772 router->rpf_cache_refresh_delay_msec);
d62a17ae 773 }
12e41d03 774
36417fcc 775 thread_add_timer_msec(router->master, on_rpf_cache_refresh, pim,
da03883e 776 router->rpf_cache_refresh_delay_msec,
da11e325 777 &pim->rpf_cache_refresher);
12e41d03
DL
778}
779
d62a17ae 780static void pim_zebra_connected(struct zclient *zclient)
48e8451b 781{
d62a17ae 782 /* Send the client registration */
0945d5ed 783 bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER, router->vrf_id);
ba4eb1bc 784
4dfe9ad2 785 zclient_send_reg_requests(zclient, router->vrf_id);
48e8451b 786}
8711a53d 787
ac567a6f
DS
788static void pim_zebra_capabilities(struct zclient_capabilities *cap)
789{
d6749d74 790 router->role = cap->role;
ac567a6f
DS
791}
792
eb05883f 793void pim_zebra_init(void)
12e41d03 794{
d62a17ae 795 /* Socket for receiving updates from Zebra daemon */
36417fcc 796 zclient = zclient_new(router->master, &zclient_options_default);
d62a17ae 797
ac567a6f 798 zclient->zebra_capabilities = pim_zebra_capabilities;
d62a17ae 799 zclient->zebra_connected = pim_zebra_connected;
800 zclient->router_id_update = pim_router_id_update_zebra;
801 zclient->interface_add = pim_zebra_if_add;
802 zclient->interface_delete = pim_zebra_if_del;
803 zclient->interface_up = pim_zebra_if_state_up;
804 zclient->interface_down = pim_zebra_if_state_down;
805 zclient->interface_address_add = pim_zebra_if_address_add;
806 zclient->interface_address_delete = pim_zebra_if_address_del;
ee568318 807 zclient->interface_vrf_update = pim_zebra_interface_vrf_update;
d62a17ae 808 zclient->nexthop_update = pim_parse_nexthop_update;
af7b561b
AK
809 zclient->vxlan_sg_add = pim_zebra_vxlan_sg_proc;
810 zclient->vxlan_sg_del = pim_zebra_vxlan_sg_proc;
d62a17ae 811
342213ea 812 zclient_init(zclient, ZEBRA_ROUTE_PIM, 0, &pimd_privs);
d62a17ae 813 if (PIM_DEBUG_PIM_TRACE) {
87270023 814 zlog_notice("%s: zclient socket initialized",
d62a17ae 815 __PRETTY_FUNCTION__);
816 }
817
818 zclient_lookup_new();
12e41d03
DL
819}
820
6f932b0c
DS
821void igmp_anysource_forward_start(struct pim_instance *pim,
822 struct igmp_group *group)
12e41d03 823{
d62a17ae 824 struct igmp_source *source;
825 struct in_addr src_addr = {.s_addr = 0};
826 /* Any source (*,G) is forwarded only if mode is EXCLUDE {empty} */
827 zassert(group->group_filtermode_isexcl);
828 zassert(listcount(group->group_source_list) < 1);
829
830 source = source_new(group, src_addr);
831 if (!source) {
832 zlog_warn("%s: Failure to create * source",
833 __PRETTY_FUNCTION__);
834 return;
835 }
836
6f932b0c 837 igmp_source_forward_start(pim, source);
12e41d03
DL
838}
839
840void igmp_anysource_forward_stop(struct igmp_group *group)
841{
d62a17ae 842 struct igmp_source *source;
843 struct in_addr star = {.s_addr = 0};
12e41d03 844
d62a17ae 845 source = igmp_find_source_by_addr(group, star);
846 if (source)
847 igmp_source_forward_stop(source);
12e41d03
DL
848}
849
6f439a70
DS
850static void igmp_source_forward_reevaluate_one(struct pim_instance *pim,
851 struct igmp_source *source)
15a5dafe 852{
d62a17ae 853 struct prefix_sg sg;
854 struct igmp_group *group = source->source_group;
855 struct pim_ifchannel *ch;
856
857 if ((source->source_addr.s_addr != INADDR_ANY)
858 || !IGMP_SOURCE_TEST_FORWARDING(source->source_flags))
859 return;
860
861 memset(&sg, 0, sizeof(struct prefix_sg));
862 sg.src = source->source_addr;
863 sg.grp = group->group_addr;
864
865 ch = pim_ifchannel_find(group->group_igmp_sock->interface, &sg);
6f439a70 866 if (pim_is_grp_ssm(pim, group->group_addr)) {
d62a17ae 867 /* If SSM group withdraw local membership */
868 if (ch
869 && (ch->local_ifmembership == PIM_IFMEMBERSHIP_INCLUDE)) {
870 if (PIM_DEBUG_PIM_EVENTS)
871 zlog_debug(
872 "local membership del for %s as G is now SSM",
873 pim_str_sg_dump(&sg));
874 pim_ifchannel_local_membership_del(
875 group->group_igmp_sock->interface, &sg);
876 }
877 } else {
878 /* If ASM group add local membership */
879 if (!ch
880 || (ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO)) {
881 if (PIM_DEBUG_PIM_EVENTS)
882 zlog_debug(
883 "local membership add for %s as G is now ASM",
884 pim_str_sg_dump(&sg));
885 pim_ifchannel_local_membership_add(
886 group->group_igmp_sock->interface, &sg);
887 }
888 }
15a5dafe 889}
890
5d59e408 891void igmp_source_forward_reevaluate_all(struct pim_instance *pim)
15a5dafe 892{
d62a17ae 893 struct interface *ifp;
894
5d59e408
DS
895 FOR_ALL_INTERFACES (pim->vrf, ifp) {
896 struct pim_interface *pim_ifp = ifp->info;
897 struct listnode *sock_node;
898 struct igmp_sock *igmp;
899
900 if (!pim_ifp)
d62a17ae 901 continue;
902
5d59e408
DS
903 /* scan igmp sockets */
904 for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node,
905 igmp)) {
906 struct listnode *grpnode;
907 struct igmp_group *grp;
908
909 /* scan igmp groups */
910 for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list,
911 grpnode, grp)) {
912 struct listnode *srcnode;
913 struct igmp_source *src;
914
915 /* scan group sources */
916 for (ALL_LIST_ELEMENTS_RO(
917 grp->group_source_list, srcnode,
918 src)) {
919 igmp_source_forward_reevaluate_one(pim,
920 src);
921 } /* scan group sources */
922 } /* scan igmp groups */
923 } /* scan igmp sockets */
924 } /* scan interfaces */
15a5dafe 925}
926
6f932b0c
DS
927void igmp_source_forward_start(struct pim_instance *pim,
928 struct igmp_source *source)
12e41d03 929{
75c61a18 930 struct pim_interface *pim_oif;
d62a17ae 931 struct igmp_group *group;
932 struct prefix_sg sg;
933 int result;
934 int input_iface_vif_index = 0;
935
936 memset(&sg, 0, sizeof(struct prefix_sg));
937 sg.src = source->source_addr;
938 sg.grp = source->source_group->group_addr;
939
940 if (PIM_DEBUG_IGMP_TRACE) {
941 zlog_debug(
942 "%s: (S,G)=%s igmp_sock=%d oif=%s fwd=%d",
943 __PRETTY_FUNCTION__, pim_str_sg_dump(&sg),
944 source->source_group->group_igmp_sock->fd,
945 source->source_group->group_igmp_sock->interface->name,
946 IGMP_SOURCE_TEST_FORWARDING(source->source_flags));
947 }
948
949 /* Prevent IGMP interface from installing multicast route multiple
950 times */
951 if (IGMP_SOURCE_TEST_FORWARDING(source->source_flags)) {
952 return;
8711a53d 953 }
d62a17ae 954
955 group = source->source_group;
75c61a18
DS
956 pim_oif = group->group_igmp_sock->interface->info;
957 if (!pim_oif) {
958 if (PIM_DEBUG_IGMP_TRACE) {
959 zlog_debug(
960 "%s: multicast not enabled on oif=%s ?",
961 __PRETTY_FUNCTION__,
962 source->source_group->group_igmp_sock
963 ->interface->name);
964 }
965 return;
966 }
d62a17ae 967
968 if (!source->source_channel_oil) {
969 struct in_addr vif_source;
d1a1b09c 970 struct prefix src, grp;
d62a17ae 971 struct pim_nexthop nexthop;
972 struct pim_upstream *up = NULL;
973
6f932b0c 974 if (!pim_rp_set_upstream_addr(pim, &vif_source,
732c209c
SP
975 source->source_addr, sg.grp)) {
976 /*Create a dummy channel oil */
8a3e7e9e
DS
977 source->source_channel_oil = pim_channel_oil_add(
978 pim, &sg, MAXVIFS, __PRETTY_FUNCTION__);
732c209c 979 }
d62a17ae 980
732c209c 981 else {
732c209c
SP
982 src.family = AF_INET;
983 src.prefixlen = IPV4_MAX_BITLEN;
984 src.u.prefix4 = vif_source; // RP or Src address
985 grp.family = AF_INET;
986 grp.prefixlen = IPV4_MAX_BITLEN;
987 grp.u.prefix4 = sg.grp;
988
43763b11
DS
989 up = pim_upstream_find(pim, &sg);
990 if (up) {
991 memcpy(&nexthop, &up->rpf.source_nexthop,
992 sizeof(struct pim_nexthop));
993 pim_ecmp_nexthop_lookup(pim, &nexthop, &src,
994 &grp, 0);
995 if (nexthop.interface)
996 input_iface_vif_index =
d62a17ae 997 pim_if_find_vifindex_by_ifindex(
43763b11
DS
998 pim,
999 nexthop.interface->ifindex);
732c209c
SP
1000 } else
1001 input_iface_vif_index =
43763b11
DS
1002 pim_ecmp_fib_lookup_if_vif_index(
1003 pim, &src, &grp);
d62a17ae 1004
732c209c
SP
1005 if (PIM_DEBUG_ZEBRA) {
1006 char buf2[INET_ADDRSTRLEN];
d62a17ae 1007
732c209c
SP
1008 pim_inet4_dump("<source?>", vif_source, buf2,
1009 sizeof(buf2));
1010 zlog_debug("%s: NHT %s vif_source %s vif_index:%d ",
d62a17ae 1011 __PRETTY_FUNCTION__,
1012 pim_str_sg_dump(&sg),
732c209c 1013 buf2, input_iface_vif_index);
d62a17ae 1014 }
d62a17ae 1015
732c209c
SP
1016 if (input_iface_vif_index < 1) {
1017 if (PIM_DEBUG_IGMP_TRACE) {
1018 char source_str[INET_ADDRSTRLEN];
1019 pim_inet4_dump("<source?>",
1020 source->source_addr,
1021 source_str, sizeof(source_str));
1022 zlog_debug(
1023 "%s %s: could not find input interface for source %s",
1024 __FILE__, __PRETTY_FUNCTION__,
1025 source_str);
1026 }
1027 source->source_channel_oil =
8a3e7e9e
DS
1028 pim_channel_oil_add(
1029 pim, &sg, MAXVIFS,
1030 __PRETTY_FUNCTION__);
732c209c
SP
1031 }
1032
1033 else {
1034 /*
1035 * Protect IGMP against adding looped MFC
1036 * entries created by both source and receiver
1037 * attached to the same interface. See TODO
50d06d9e 1038 * T22. Block only when the intf is non DR
1039 * DR must create upstream.
732c209c 1040 */
50d06d9e 1041 if ((input_iface_vif_index ==
1042 pim_oif->mroute_vif_index) &&
1043 !(PIM_I_am_DR(pim_oif))) {
732c209c
SP
1044 /* ignore request for looped MFC entry
1045 */
1046 if (PIM_DEBUG_IGMP_TRACE) {
1047 zlog_debug(
1048 "%s: ignoring request for looped MFC entry (S,G)=%s: igmp_sock=%d oif=%s vif_index=%d",
1049 __PRETTY_FUNCTION__,
1050 pim_str_sg_dump(&sg),
1051 source->source_group
1052 ->group_igmp_sock->fd,
1053 source->source_group
1054 ->group_igmp_sock
1055 ->interface->name,
1056 input_iface_vif_index);
1057 }
1058 return;
1059 }
1060
1061 source->source_channel_oil =
8a3e7e9e
DS
1062 pim_channel_oil_add(
1063 pim, &sg, input_iface_vif_index,
1064 __PRETTY_FUNCTION__);
732c209c
SP
1065 if (!source->source_channel_oil) {
1066 if (PIM_DEBUG_IGMP_TRACE) {
1067 zlog_debug(
1068 "%s %s: could not create OIL for channel (S,G)=%s",
1069 __FILE__,
1070 __PRETTY_FUNCTION__,
1071 pim_str_sg_dump(&sg));
1072 }
1073 return;
1074 }
d62a17ae 1075 }
d62a17ae 1076 }
8711a53d 1077 }
d62a17ae 1078
1079 result = pim_channel_add_oif(source->source_channel_oil,
1080 group->group_igmp_sock->interface,
1081 PIM_OIF_FLAG_PROTO_IGMP);
1082 if (result) {
1083 if (PIM_DEBUG_MROUTE) {
1084 zlog_warn("%s: add_oif() failed with return=%d",
1085 __func__, result);
1086 }
1087 return;
8711a53d 1088 }
d62a17ae 1089
90a084e4
DS
1090 if (!(PIM_I_am_DR(pim_oif))) {
1091 if (PIM_DEBUG_IGMP_TRACE)
1092 zlog_debug("%s: %s was received on %s interface but we are not DR for that interface",
1093 __PRETTY_FUNCTION__,
1094 pim_str_sg_dump(&sg),
1095 group->group_igmp_sock->interface->name);
b96892db
DS
1096
1097 pim_channel_del_oif(source->source_channel_oil,
1098 group->group_igmp_sock->interface,
1099 PIM_OIF_FLAG_PROTO_IGMP);
75c61a18 1100 return;
90a084e4 1101 }
d62a17ae 1102 /*
1103 Feed IGMPv3-gathered local membership information into PIM
1104 per-interface (S,G) state.
1105 */
1106 if (!pim_ifchannel_local_membership_add(
75c61a18 1107 group->group_igmp_sock->interface, &sg)) {
d62a17ae 1108 if (PIM_DEBUG_MROUTE)
1109 zlog_warn("%s: Failure to add local membership for %s",
1110 __PRETTY_FUNCTION__, pim_str_sg_dump(&sg));
b96892db
DS
1111
1112 pim_channel_del_oif(source->source_channel_oil,
1113 group->group_igmp_sock->interface,
1114 PIM_OIF_FLAG_PROTO_IGMP);
d62a17ae 1115 return;
1116 }
1117
1118 IGMP_SOURCE_DO_FORWARDING(source->source_flags);
12e41d03
DL
1119}
1120
1121/*
1122 igmp_source_forward_stop: stop fowarding, but keep the source
1123 igmp_source_delete: stop fowarding, and delete the source
1124 */
1125void igmp_source_forward_stop(struct igmp_source *source)
1126{
d62a17ae 1127 struct igmp_group *group;
1128 struct prefix_sg sg;
1129 int result;
1130
1131 memset(&sg, 0, sizeof(struct prefix_sg));
1132 sg.src = source->source_addr;
1133 sg.grp = source->source_group->group_addr;
1134
1135 if (PIM_DEBUG_IGMP_TRACE) {
1136 zlog_debug(
1137 "%s: (S,G)=%s igmp_sock=%d oif=%s fwd=%d",
1138 __PRETTY_FUNCTION__, pim_str_sg_dump(&sg),
1139 source->source_group->group_igmp_sock->fd,
1140 source->source_group->group_igmp_sock->interface->name,
1141 IGMP_SOURCE_TEST_FORWARDING(source->source_flags));
1142 }
1143
1144 /* Prevent IGMP interface from removing multicast route multiple
1145 times */
1146 if (!IGMP_SOURCE_TEST_FORWARDING(source->source_flags)) {
1147 return;
1148 }
1149
1150 group = source->source_group;
1151
1152 /*
1153 It appears that in certain circumstances that
1154 igmp_source_forward_stop is called when IGMP forwarding
1155 was not enabled in oif_flags for this outgoing interface.
1156 Possibly because of multiple calls. When that happens, we
1157 enter the below if statement and this function returns early
1158 which in turn triggers the calling function to assert.
1159 Making the call to pim_channel_del_oif and ignoring the return code
1160 fixes the issue without ill effect, similar to
1161 pim_forward_stop below.
1162 */
1163 result = pim_channel_del_oif(source->source_channel_oil,
1164 group->group_igmp_sock->interface,
1165 PIM_OIF_FLAG_PROTO_IGMP);
1166 if (result) {
1167 if (PIM_DEBUG_IGMP_TRACE)
1168 zlog_debug(
1169 "%s: pim_channel_del_oif() failed with return=%d",
1170 __func__, result);
1171 return;
1172 }
1173
1174 /*
1175 Feed IGMPv3-gathered local membership information into PIM
1176 per-interface (S,G) state.
1177 */
1178 pim_ifchannel_local_membership_del(group->group_igmp_sock->interface,
1179 &sg);
1180
1181 IGMP_SOURCE_DONT_FORWARDING(source->source_flags);
12e41d03
DL
1182}
1183
1184void pim_forward_start(struct pim_ifchannel *ch)
1185{
d62a17ae 1186 struct pim_upstream *up = ch->upstream;
1187 uint32_t mask = PIM_OIF_FLAG_PROTO_PIM;
1188 int input_iface_vif_index = 0;
6f932b0c
DS
1189 struct pim_instance *pim;
1190 struct pim_interface *pim_ifp;
1191
1192 pim_ifp = ch->interface->info;
1193 pim = pim_ifp->pim;
d62a17ae 1194
1195 if (PIM_DEBUG_PIM_TRACE) {
1196 char source_str[INET_ADDRSTRLEN];
1197 char group_str[INET_ADDRSTRLEN];
1198 char upstream_str[INET_ADDRSTRLEN];
1199
1200 pim_inet4_dump("<source?>", ch->sg.src, source_str,
1201 sizeof(source_str));
1202 pim_inet4_dump("<group?>", ch->sg.grp, group_str,
1203 sizeof(group_str));
1204 pim_inet4_dump("<upstream?>", up->upstream_addr, upstream_str,
1205 sizeof(upstream_str));
1206 zlog_debug("%s: (S,G)=(%s,%s) oif=%s (%s)", __PRETTY_FUNCTION__,
1207 source_str, group_str, ch->interface->name,
732c209c 1208 inet_ntoa(up->upstream_addr));
d62a17ae 1209 }
1210
1211 /* Resolve IIF for upstream as mroute_del sets mfcc_parent to MAXVIFS,
1212 as part of mroute_del called by pim_forward_stop.
1213 */
732c209c 1214 if ((up->upstream_addr.s_addr != INADDR_ANY) && (!up->channel_oil)) {
d1a1b09c 1215 struct prefix src, grp;
d62a17ae 1216
d62a17ae 1217 grp.family = AF_INET;
1218 grp.prefixlen = IPV4_MAX_BITLEN;
1219 grp.u.prefix4 = up->sg.grp;
43763b11
DS
1220 src.family = AF_INET;
1221 src.prefixlen = IPV4_MAX_BITLEN;
1222 src.u.prefix4 = up->sg.src;
1223
1224 if (pim_ecmp_nexthop_lookup(pim, &up->rpf.source_nexthop, &src,
1225 &grp, 0))
1226 input_iface_vif_index = pim_if_find_vifindex_by_ifindex(
1227 pim, up->rpf.source_nexthop.interface->ifindex);
d62a17ae 1228
1229 if (input_iface_vif_index < 1) {
1230 if (PIM_DEBUG_PIM_TRACE) {
1231 char source_str[INET_ADDRSTRLEN];
1232 pim_inet4_dump("<source?>", up->sg.src,
1233 source_str, sizeof(source_str));
1234 zlog_debug(
1235 "%s %s: could not find input interface for source %s",
1236 __FILE__, __PRETTY_FUNCTION__,
1237 source_str);
1238 }
8a3e7e9e
DS
1239 up->channel_oil = pim_channel_oil_add(
1240 pim, &up->sg, MAXVIFS, __PRETTY_FUNCTION__);
d62a17ae 1241 }
732c209c 1242
11884868 1243 else
8a3e7e9e
DS
1244 up->channel_oil = pim_channel_oil_add(
1245 pim, &up->sg, input_iface_vif_index,
1246 __PRETTY_FUNCTION__);
732c209c 1247
d62a17ae 1248 if (PIM_DEBUG_TRACE) {
7cfc7bcf 1249 struct interface *in_intf = pim_if_find_by_vif_index(
6f932b0c 1250 pim, input_iface_vif_index);
d62a17ae 1251 zlog_debug(
1252 "%s: Update channel_oil IIF %s VIFI %d entry %s ",
1253 __PRETTY_FUNCTION__,
732c209c 1254 in_intf ? in_intf->name : "Unknown",
d62a17ae 1255 input_iface_vif_index, up->sg_str);
1256 }
732c209c 1257
8a3e7e9e
DS
1258 up->channel_oil =
1259 pim_channel_oil_add(pim, &up->sg, input_iface_vif_index,
1260 __PRETTY_FUNCTION__);
d62a17ae 1261 }
1262
1263 if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP)
1264 mask = PIM_OIF_FLAG_PROTO_IGMP;
1265
1266 pim_channel_add_oif(up->channel_oil, ch->interface, mask);
12e41d03
DL
1267}
1268
aabb9a2f 1269void pim_forward_stop(struct pim_ifchannel *ch, bool install_it)
12e41d03 1270{
d62a17ae 1271 struct pim_upstream *up = ch->upstream;
12e41d03 1272
d62a17ae 1273 if (PIM_DEBUG_PIM_TRACE) {
aabb9a2f
DS
1274 zlog_debug("%s: (S,G)=%s oif=%s install_it: %d installed: %d",
1275 __PRETTY_FUNCTION__, ch->sg_str, ch->interface->name,
1276 install_it, up->channel_oil->installed);
d62a17ae 1277 }
12e41d03 1278
2164ed5d
DS
1279 /*
1280 * If a channel is being removed, check to see if we still need
1281 * to inherit the interface. If so make sure it is added in
1282 */
1283 if (pim_upstream_evaluate_join_desired_interface(up, ch, ch->parent))
1284 pim_channel_add_oif(up->channel_oil, ch->interface,
1285 PIM_OIF_FLAG_PROTO_PIM);
1286 else
1287 pim_channel_del_oif(up->channel_oil, ch->interface,
1288 PIM_OIF_FLAG_PROTO_PIM);
aabb9a2f
DS
1289
1290 if (install_it && !up->channel_oil->installed)
1291 pim_mroute_add(up->channel_oil, __PRETTY_FUNCTION__);
12e41d03 1292}
8799b66b 1293
d62a17ae 1294void pim_zebra_zclient_update(struct vty *vty)
8799b66b 1295{
d62a17ae 1296 vty_out(vty, "Zclient update socket: ");
1297
1298 if (zclient) {
1299 vty_out(vty, "%d failures=%d\n", zclient->sock, zclient->fail);
1300 } else {
1301 vty_out(vty, "<null zclient>\n");
1302 }
8799b66b 1303}
1bc98276 1304
d62a17ae 1305struct zclient *pim_zebra_zclient_get(void)
1bc98276 1306{
d62a17ae 1307 if (zclient)
1308 return zclient;
1309 else
1310 return NULL;
1bc98276 1311}