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