]> git.proxmox.com Git - mirror_frr.git/blame - pimd/pim_zebra.c
Merge pull request #6732 from opensourcerouting/printfrr-prep
[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"
46c2687c 49#include "pim_mlag.h"
12e41d03
DL
50
51#undef PIM_DEBUG_IFADDR_DUMP
52#define PIM_DEBUG_IFADDR_DUMP
53
36b5b98f 54struct zclient *zclient;
38f4935a 55
12e41d03 56
12e41d03 57/* Router-id update message from zebra. */
121f9dee 58static int pim_router_id_update_zebra(ZAPI_CALLBACK_ARGS)
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
121f9dee 67static int pim_zebra_interface_vrf_update(ZAPI_CALLBACK_ARGS)
ee568318
DS
68{
69 struct interface *ifp;
70 vrf_id_t new_vrf_id;
71
72 ifp = zebra_interface_vrf_update_read(zclient->ibuf, vrf_id,
73 &new_vrf_id);
74 if (!ifp)
75 return 0;
76
77 if (PIM_DEBUG_ZEBRA)
15569c58
DA
78 zlog_debug("%s: %s updating from %u to %u", __func__, ifp->name,
79 vrf_id, new_vrf_id);
ee568318 80
a36898e7 81 if_update_to_new_vrf(ifp, new_vrf_id);
ee568318
DS
82
83 return 0;
84}
85
12e41d03
DL
86#ifdef PIM_DEBUG_IFADDR_DUMP
87static void dump_if_address(struct interface *ifp)
88{
d62a17ae 89 struct connected *ifc;
90 struct listnode *node;
91
5e81f5dd
DS
92 zlog_debug("%s %s: interface %s addresses:", __FILE__, __func__,
93 ifp->name);
d62a17ae 94
95 for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) {
96 struct prefix *p = ifc->address;
97
98 if (p->family != AF_INET)
99 continue;
100
101 zlog_debug("%s %s: interface %s address %s %s", __FILE__,
5e81f5dd 102 __func__, ifp->name, inet_ntoa(p->u.prefix4),
d62a17ae 103 CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY)
104 ? "secondary"
105 : "primary");
106 }
12e41d03
DL
107}
108#endif
109
121f9dee 110static int pim_zebra_if_address_add(ZAPI_CALLBACK_ARGS)
12e41d03 111{
d62a17ae 112 struct connected *c;
113 struct prefix *p;
114 struct pim_interface *pim_ifp;
26bb1fd5 115 struct pim_instance *pim;
d62a17ae 116
117 /*
118 zebra api notifies address adds/dels events by using the same call
119 interface_add_read below, see comments in lib/zclient.c
120
121 zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_ADD, ...)
122 will add address to interface list by calling
123 connected_add_by_prefix()
124 */
121f9dee 125 c = zebra_interface_address_read(cmd, zclient->ibuf, vrf_id);
d62a17ae 126 if (!c)
127 return 0;
128
129 pim_ifp = c->ifp->info;
130 p = c->address;
131
132 if (PIM_DEBUG_ZEBRA) {
133 char buf[BUFSIZ];
134 prefix2str(p, buf, BUFSIZ);
87ad28f4 135 zlog_debug("%s: %s(%u) connected IP address %s flags %u %s",
15569c58 136 __func__, c->ifp->name, vrf_id, buf, c->flags,
996c9314
LB
137 CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY)
138 ? "secondary"
139 : "primary");
d62a17ae 140
12e41d03 141#ifdef PIM_DEBUG_IFADDR_DUMP
d62a17ae 142 dump_if_address(c->ifp);
12e41d03 143#endif
d62a17ae 144 }
12e41d03 145
d62a17ae 146 if (!CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY)) {
147 /* trying to add primary address */
12e41d03 148
d62a17ae 149 struct in_addr primary_addr = pim_find_primary_addr(c->ifp);
150 if (p->family != AF_INET
151 || primary_addr.s_addr != p->u.prefix4.s_addr) {
152 if (PIM_DEBUG_ZEBRA) {
153 /* but we had a primary address already */
12e41d03 154
d62a17ae 155 char buf[BUFSIZ];
12e41d03 156
d62a17ae 157 prefix2str(p, buf, BUFSIZ);
12e41d03 158
d62a17ae 159 zlog_warn(
160 "%s: %s : forcing secondary flag on %s",
15569c58 161 __func__, c->ifp->name, buf);
d62a17ae 162 }
163 SET_FLAG(c->flags, ZEBRA_IFA_SECONDARY);
164 }
165 }
12e41d03 166
d62a17ae 167 pim_if_addr_add(c);
26bb1fd5
DS
168 if (pim_ifp) {
169 pim = pim_get_pim_instance(vrf_id);
170 pim_ifp->pim = pim;
171
d62a17ae 172 pim_rp_check_on_if_add(pim_ifp);
26bb1fd5 173 }
12e41d03 174
d62a17ae 175 if (if_is_loopback(c->ifp)) {
f4e14fdb 176 struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
d62a17ae 177 struct interface *ifp;
d8424057 178
451fda4f 179 FOR_ALL_INTERFACES (vrf, ifp) {
d62a17ae 180 if (!if_is_loopback(ifp) && if_is_operative(ifp))
181 pim_if_addr_add_all(ifp);
182 }
183 }
d8424057 184
d62a17ae 185 return 0;
12e41d03
DL
186}
187
121f9dee 188static int pim_zebra_if_address_del(ZAPI_CALLBACK_ARGS)
12e41d03 189{
d62a17ae 190 struct connected *c;
191 struct prefix *p;
fec883d9 192 struct vrf *vrf = vrf_lookup_by_id(vrf_id);
819f099b
DS
193 struct pim_instance *pim;
194
195 if (!vrf)
196 return 0;
197 pim = vrf->info;
d62a17ae 198
199 /*
200 zebra api notifies address adds/dels events by using the same call
201 interface_add_read below, see comments in lib/zclient.c
202
203 zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_DELETE, ...)
204 will remove address from interface list by calling
205 connected_delete_by_prefix()
206 */
121f9dee 207 c = zebra_interface_address_read(cmd, zclient->ibuf, vrf_id);
d62a17ae 208 if (!c)
209 return 0;
210
211 p = c->address;
212 if (p->family == AF_INET) {
213 if (PIM_DEBUG_ZEBRA) {
214 char buf[BUFSIZ];
215 prefix2str(p, buf, BUFSIZ);
216 zlog_debug(
87ad28f4 217 "%s: %s(%u) disconnected IP address %s flags %u %s",
15569c58 218 __func__, c->ifp->name, vrf_id, buf, c->flags,
d62a17ae 219 CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY)
220 ? "secondary"
221 : "primary");
6233f087 222
12e41d03 223#ifdef PIM_DEBUG_IFADDR_DUMP
d62a17ae 224 dump_if_address(c->ifp);
12e41d03 225#endif
d62a17ae 226 }
12e41d03 227
d62a17ae 228 pim_if_addr_del(c, 0);
fec883d9
DS
229 pim_rp_setup(pim);
230 pim_i_am_rp_re_evaluate(pim);
d62a17ae 231 }
6233f087 232
721c0857 233 connected_free(&c);
d62a17ae 234 return 0;
12e41d03
DL
235}
236
74389231
DS
237void pim_zebra_update_all_interfaces(struct pim_instance *pim)
238{
239 struct interface *ifp;
240
241 FOR_ALL_INTERFACES (pim->vrf, ifp) {
242 struct pim_interface *pim_ifp = ifp->info;
243 struct pim_iface_upstream_switch *us;
244 struct listnode *node;
245
246 if (!pim_ifp)
247 continue;
248
249 for (ALL_LIST_ELEMENTS_RO(pim_ifp->upstream_switch_list, node,
250 us)) {
251 struct pim_rpf rpf;
252
253 rpf.source_nexthop.interface = ifp;
254 rpf.rpf_addr.u.prefix4 = us->address;
255 pim_joinprune_send(&rpf, us->us);
256 pim_jp_agg_clear_group(us->us);
257 }
258 }
259}
260
cc67ccf9
DS
261void pim_zebra_upstream_rpf_changed(struct pim_instance *pim,
262 struct pim_upstream *up,
263 struct pim_rpf *old)
264{
1250cb5d
SP
265 if (old->source_nexthop.interface) {
266 struct pim_neighbor *nbr;
cc67ccf9 267
1250cb5d
SP
268 nbr = pim_neighbor_find(old->source_nexthop.interface,
269 old->rpf_addr.u.prefix4);
270 if (nbr)
c5cdf069 271 pim_jp_agg_remove_group(nbr->upstream_jp_agg, up, nbr);
cc67ccf9 272
cc67ccf9 273 /*
1250cb5d
SP
274 * We have detected a case where we might need
275 * to rescan the inherited o_list so do it.
cc67ccf9 276 */
1250cb5d
SP
277 if (up->channel_oil->oil_inherited_rescan) {
278 pim_upstream_inherited_olist_decide(pim, up);
279 up->channel_oil->oil_inherited_rescan = 0;
280 }
cc67ccf9 281
1250cb5d
SP
282 if (up->join_state == PIM_UPSTREAM_JOINED) {
283 /*
284 * If we come up real fast we can be here
285 * where the mroute has not been installed
286 * so install it.
287 */
288 if (!up->channel_oil->installed)
69e3538c 289 pim_upstream_mroute_add(up->channel_oil,
15569c58 290 __func__);
1250cb5d
SP
291
292 /*
293 * RFC 4601: 4.5.7. Sending (S,G)
294 * Join/Prune Messages
295 *
296 * Transitions from Joined State
297 *
298 * RPF'(S,G) changes not due to an Assert
299 *
300 * The upstream (S,G) state machine remains
301 * in Joined state. Send Join(S,G) to the new
302 * upstream neighbor, which is the new value
303 * of RPF'(S,G). Send Prune(S,G) to the old
304 * upstream neighbor, which is the old value
305 * of RPF'(S,G). Set the Join Timer (JT) to
306 * expire after t_periodic seconds.
307 */
308 pim_jp_agg_switch_interface(old, &up->rpf, up);
309
310 pim_upstream_join_timer_restart(up, old);
311 } /* up->join_state == PIM_UPSTREAM_JOINED */
312 }
313
314 else {
cc67ccf9 315 /*
1250cb5d
SP
316 * We have detected a case where we might need
317 * to rescan the inherited o_list so do it.
cc67ccf9 318 */
1250cb5d
SP
319 if (up->channel_oil->oil_inherited_rescan) {
320 pim_upstream_inherited_olist_decide(pim, up);
321 up->channel_oil->oil_inherited_rescan = 0;
322 }
cc67ccf9 323
db431af2
AK
324 if (up->join_state == PIM_UPSTREAM_JOINED)
325 pim_jp_agg_switch_interface(old, &up->rpf, up);
326
1250cb5d 327 if (!up->channel_oil->installed)
15569c58 328 pim_upstream_mroute_add(up->channel_oil, __func__);
1250cb5d 329 }
cc67ccf9 330
1250cb5d
SP
331 /* FIXME can join_desired actually be changed by pim_rpf_update()
332 * returning PIM_RPF_CHANGED ?
333 */
cc67ccf9
DS
334 pim_upstream_update_join_desired(pim, up);
335}
336
121f9dee 337static int pim_zebra_vxlan_sg_proc(ZAPI_CALLBACK_ARGS)
af7b561b
AK
338{
339 struct stream *s;
340 struct pim_instance *pim;
341 struct prefix_sg sg;
342
343 pim = pim_get_pim_instance(vrf_id);
344 if (!pim)
345 return 0;
346
347 s = zclient->ibuf;
348
349 sg.family = AF_INET;
350 sg.prefixlen = stream_getl(s);
351 stream_get(&sg.src.s_addr, s, sg.prefixlen);
352 stream_get(&sg.grp.s_addr, s, sg.prefixlen);
353
354 if (PIM_DEBUG_ZEBRA) {
355 char sg_str[PIM_SG_LEN];
356
357 pim_str_sg_set(&sg, sg_str);
358 zlog_debug("%u:recv SG %s %s", vrf_id,
121f9dee 359 (cmd == ZEBRA_VXLAN_SG_ADD)?"add":"del",
af7b561b
AK
360 sg_str);
361 }
362
121f9dee 363 if (cmd == ZEBRA_VXLAN_SG_ADD)
af7b561b
AK
364 pim_vxlan_sg_add(pim, &sg);
365 else
366 pim_vxlan_sg_del(pim, &sg);
367
368 return 0;
369}
370
ecbbc3a7
AK
371static void pim_zebra_vxlan_replay(void)
372{
373 struct stream *s = NULL;
374
375 /* Check socket. */
376 if (!zclient || zclient->sock < 0)
377 return;
378
379 s = zclient->obuf;
380 stream_reset(s);
381
382 zclient_create_header(s, ZEBRA_VXLAN_SG_REPLAY, VRF_DEFAULT);
383 stream_putw_at(s, 0, stream_get_endp(s));
384
385 zclient_send_message(zclient);
386}
387
da11e325 388void pim_scan_oil(struct pim_instance *pim)
8a67a996 389{
d62a17ae 390 struct channel_oil *c_oil;
d62a17ae 391
bfc92019
DS
392 pim->scan_oil_last = pim_time_monotonic_sec();
393 ++pim->scan_oil_events;
d62a17ae 394
7315ecda 395 frr_each (rb_pim_oil, &pim->channel_oil_head, c_oil)
7984af18 396 pim_upstream_mroute_iif_update(c_oil, __func__);
12e41d03
DL
397}
398
399static int on_rpf_cache_refresh(struct thread *t)
400{
da11e325
DS
401 struct pim_instance *pim = THREAD_ARG(t);
402
d62a17ae 403 /* update kernel multicast forwarding cache (MFC) */
da11e325 404 pim_scan_oil(pim);
12e41d03 405
bfc92019
DS
406 pim->rpf_cache_refresh_last = pim_time_monotonic_sec();
407 ++pim->rpf_cache_refresh_events;
12e41d03 408
d62a17ae 409 // It is called as part of pim_neighbor_add
410 // pim_rp_setup ();
411 return 0;
12e41d03
DL
412}
413
da11e325 414void sched_rpf_cache_refresh(struct pim_instance *pim)
12e41d03 415{
bfc92019 416 ++pim->rpf_cache_refresh_requests;
12e41d03 417
bfc92019 418 pim_rpf_set_refresh_time(pim);
e71bf8f7 419
da11e325 420 if (pim->rpf_cache_refresher) {
d62a17ae 421 /* Refresh timer is already running */
422 return;
423 }
12e41d03 424
d62a17ae 425 /* Start refresh timer */
12e41d03 426
d62a17ae 427 if (PIM_DEBUG_ZEBRA) {
15569c58 428 zlog_debug("%s: triggering %ld msec timer", __func__,
da03883e 429 router->rpf_cache_refresh_delay_msec);
d62a17ae 430 }
12e41d03 431
36417fcc 432 thread_add_timer_msec(router->master, on_rpf_cache_refresh, pim,
da03883e 433 router->rpf_cache_refresh_delay_msec,
da11e325 434 &pim->rpf_cache_refresher);
12e41d03
DL
435}
436
d62a17ae 437static void pim_zebra_connected(struct zclient *zclient)
48e8451b 438{
d62a17ae 439 /* Send the client registration */
0945d5ed 440 bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER, router->vrf_id);
ba4eb1bc 441
4dfe9ad2 442 zclient_send_reg_requests(zclient, router->vrf_id);
ecbbc3a7
AK
443
444 /* request for VxLAN BUM group addresses */
445 pim_zebra_vxlan_replay();
48e8451b 446}
8711a53d 447
ac567a6f
DS
448static void pim_zebra_capabilities(struct zclient_capabilities *cap)
449{
05ca004b 450 router->mlag_role = cap->role;
ac567a6f
DS
451}
452
eb05883f 453void pim_zebra_init(void)
12e41d03 454{
d62a17ae 455 /* Socket for receiving updates from Zebra daemon */
36417fcc 456 zclient = zclient_new(router->master, &zclient_options_default);
d62a17ae 457
ac567a6f 458 zclient->zebra_capabilities = pim_zebra_capabilities;
d62a17ae 459 zclient->zebra_connected = pim_zebra_connected;
460 zclient->router_id_update = pim_router_id_update_zebra;
d62a17ae 461 zclient->interface_address_add = pim_zebra_if_address_add;
462 zclient->interface_address_delete = pim_zebra_if_address_del;
ee568318 463 zclient->interface_vrf_update = pim_zebra_interface_vrf_update;
d62a17ae 464 zclient->nexthop_update = pim_parse_nexthop_update;
af7b561b
AK
465 zclient->vxlan_sg_add = pim_zebra_vxlan_sg_proc;
466 zclient->vxlan_sg_del = pim_zebra_vxlan_sg_proc;
46c2687c
SK
467 zclient->mlag_process_up = pim_zebra_mlag_process_up;
468 zclient->mlag_process_down = pim_zebra_mlag_process_down;
469 zclient->mlag_handle_msg = pim_zebra_mlag_handle_msg;
d62a17ae 470
342213ea 471 zclient_init(zclient, ZEBRA_ROUTE_PIM, 0, &pimd_privs);
d62a17ae 472 if (PIM_DEBUG_PIM_TRACE) {
15569c58 473 zlog_notice("%s: zclient socket initialized", __func__);
d62a17ae 474 }
475
476 zclient_lookup_new();
12e41d03
DL
477}
478
6f932b0c
DS
479void igmp_anysource_forward_start(struct pim_instance *pim,
480 struct igmp_group *group)
12e41d03 481{
d62a17ae 482 struct igmp_source *source;
483 struct in_addr src_addr = {.s_addr = 0};
484 /* Any source (*,G) is forwarded only if mode is EXCLUDE {empty} */
485 zassert(group->group_filtermode_isexcl);
486 zassert(listcount(group->group_source_list) < 1);
487
488 source = source_new(group, src_addr);
489 if (!source) {
15569c58 490 zlog_warn("%s: Failure to create * source", __func__);
d62a17ae 491 return;
492 }
493
6f932b0c 494 igmp_source_forward_start(pim, source);
12e41d03
DL
495}
496
497void igmp_anysource_forward_stop(struct igmp_group *group)
498{
d62a17ae 499 struct igmp_source *source;
500 struct in_addr star = {.s_addr = 0};
12e41d03 501
d62a17ae 502 source = igmp_find_source_by_addr(group, star);
503 if (source)
504 igmp_source_forward_stop(source);
12e41d03
DL
505}
506
6f439a70
DS
507static void igmp_source_forward_reevaluate_one(struct pim_instance *pim,
508 struct igmp_source *source)
15a5dafe 509{
d62a17ae 510 struct prefix_sg sg;
511 struct igmp_group *group = source->source_group;
512 struct pim_ifchannel *ch;
513
514 if ((source->source_addr.s_addr != INADDR_ANY)
515 || !IGMP_SOURCE_TEST_FORWARDING(source->source_flags))
516 return;
517
518 memset(&sg, 0, sizeof(struct prefix_sg));
519 sg.src = source->source_addr;
520 sg.grp = group->group_addr;
521
522 ch = pim_ifchannel_find(group->group_igmp_sock->interface, &sg);
6f439a70 523 if (pim_is_grp_ssm(pim, group->group_addr)) {
d62a17ae 524 /* If SSM group withdraw local membership */
525 if (ch
526 && (ch->local_ifmembership == PIM_IFMEMBERSHIP_INCLUDE)) {
527 if (PIM_DEBUG_PIM_EVENTS)
528 zlog_debug(
529 "local membership del for %s as G is now SSM",
530 pim_str_sg_dump(&sg));
531 pim_ifchannel_local_membership_del(
532 group->group_igmp_sock->interface, &sg);
533 }
534 } else {
535 /* If ASM group add local membership */
536 if (!ch
537 || (ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO)) {
538 if (PIM_DEBUG_PIM_EVENTS)
539 zlog_debug(
540 "local membership add for %s as G is now ASM",
541 pim_str_sg_dump(&sg));
542 pim_ifchannel_local_membership_add(
448139e7
AK
543 group->group_igmp_sock->interface, &sg,
544 false /*is_vxlan*/);
d62a17ae 545 }
546 }
15a5dafe 547}
548
5d59e408 549void igmp_source_forward_reevaluate_all(struct pim_instance *pim)
15a5dafe 550{
d62a17ae 551 struct interface *ifp;
552
5d59e408
DS
553 FOR_ALL_INTERFACES (pim->vrf, ifp) {
554 struct pim_interface *pim_ifp = ifp->info;
555 struct listnode *sock_node;
556 struct igmp_sock *igmp;
557
558 if (!pim_ifp)
d62a17ae 559 continue;
560
5d59e408
DS
561 /* scan igmp sockets */
562 for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node,
563 igmp)) {
564 struct listnode *grpnode;
565 struct igmp_group *grp;
566
567 /* scan igmp groups */
568 for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list,
569 grpnode, grp)) {
570 struct listnode *srcnode;
571 struct igmp_source *src;
572
573 /* scan group sources */
574 for (ALL_LIST_ELEMENTS_RO(
575 grp->group_source_list, srcnode,
576 src)) {
577 igmp_source_forward_reevaluate_one(pim,
578 src);
579 } /* scan group sources */
580 } /* scan igmp groups */
581 } /* scan igmp sockets */
582 } /* scan interfaces */
15a5dafe 583}
584
6f932b0c
DS
585void igmp_source_forward_start(struct pim_instance *pim,
586 struct igmp_source *source)
12e41d03 587{
75c61a18 588 struct pim_interface *pim_oif;
d62a17ae 589 struct igmp_group *group;
590 struct prefix_sg sg;
591 int result;
592 int input_iface_vif_index = 0;
593
594 memset(&sg, 0, sizeof(struct prefix_sg));
595 sg.src = source->source_addr;
596 sg.grp = source->source_group->group_addr;
597
598 if (PIM_DEBUG_IGMP_TRACE) {
599 zlog_debug(
15569c58
DA
600 "%s: (S,G)=%s igmp_sock=%d oif=%s fwd=%d", __func__,
601 pim_str_sg_dump(&sg),
d62a17ae 602 source->source_group->group_igmp_sock->fd,
603 source->source_group->group_igmp_sock->interface->name,
604 IGMP_SOURCE_TEST_FORWARDING(source->source_flags));
605 }
606
607 /* Prevent IGMP interface from installing multicast route multiple
608 times */
609 if (IGMP_SOURCE_TEST_FORWARDING(source->source_flags)) {
610 return;
8711a53d 611 }
d62a17ae 612
613 group = source->source_group;
75c61a18
DS
614 pim_oif = group->group_igmp_sock->interface->info;
615 if (!pim_oif) {
616 if (PIM_DEBUG_IGMP_TRACE) {
15569c58
DA
617 zlog_debug("%s: multicast not enabled on oif=%s ?",
618 __func__,
75c61a18 619 source->source_group->group_igmp_sock
15569c58 620 ->interface->name);
75c61a18
DS
621 }
622 return;
623 }
d62a17ae 624
625 if (!source->source_channel_oil) {
626 struct in_addr vif_source;
d1a1b09c 627 struct prefix src, grp;
d62a17ae 628 struct pim_nexthop nexthop;
629 struct pim_upstream *up = NULL;
630
6f932b0c 631 if (!pim_rp_set_upstream_addr(pim, &vif_source,
732c209c
SP
632 source->source_addr, sg.grp)) {
633 /*Create a dummy channel oil */
15569c58
DA
634 source->source_channel_oil =
635 pim_channel_oil_add(pim, &sg, __func__);
732c209c 636 }
d62a17ae 637
732c209c 638 else {
732c209c
SP
639 src.family = AF_INET;
640 src.prefixlen = IPV4_MAX_BITLEN;
641 src.u.prefix4 = vif_source; // RP or Src address
642 grp.family = AF_INET;
643 grp.prefixlen = IPV4_MAX_BITLEN;
644 grp.u.prefix4 = sg.grp;
645
43763b11
DS
646 up = pim_upstream_find(pim, &sg);
647 if (up) {
648 memcpy(&nexthop, &up->rpf.source_nexthop,
649 sizeof(struct pim_nexthop));
650 pim_ecmp_nexthop_lookup(pim, &nexthop, &src,
651 &grp, 0);
652 if (nexthop.interface)
653 input_iface_vif_index =
d62a17ae 654 pim_if_find_vifindex_by_ifindex(
43763b11
DS
655 pim,
656 nexthop.interface->ifindex);
732c209c
SP
657 } else
658 input_iface_vif_index =
43763b11
DS
659 pim_ecmp_fib_lookup_if_vif_index(
660 pim, &src, &grp);
d62a17ae 661
732c209c
SP
662 if (PIM_DEBUG_ZEBRA) {
663 char buf2[INET_ADDRSTRLEN];
d62a17ae 664
732c209c
SP
665 pim_inet4_dump("<source?>", vif_source, buf2,
666 sizeof(buf2));
15569c58
DA
667 zlog_debug(
668 "%s: NHT %s vif_source %s vif_index:%d ",
669 __func__, pim_str_sg_dump(&sg), buf2,
670 input_iface_vif_index);
d62a17ae 671 }
d62a17ae 672
732c209c
SP
673 if (input_iface_vif_index < 1) {
674 if (PIM_DEBUG_IGMP_TRACE) {
675 char source_str[INET_ADDRSTRLEN];
676 pim_inet4_dump("<source?>",
677 source->source_addr,
678 source_str, sizeof(source_str));
679 zlog_debug(
15569c58
DA
680 "%s %s: could not find input interface for source %s",
681 __FILE__, __func__, source_str);
732c209c
SP
682 }
683 source->source_channel_oil =
15569c58 684 pim_channel_oil_add(pim, &sg, __func__);
732c209c
SP
685 }
686
687 else {
688 /*
689 * Protect IGMP against adding looped MFC
690 * entries created by both source and receiver
691 * attached to the same interface. See TODO
50d06d9e 692 * T22. Block only when the intf is non DR
693 * DR must create upstream.
732c209c 694 */
50d06d9e 695 if ((input_iface_vif_index ==
696 pim_oif->mroute_vif_index) &&
697 !(PIM_I_am_DR(pim_oif))) {
732c209c
SP
698 /* ignore request for looped MFC entry
699 */
700 if (PIM_DEBUG_IGMP_TRACE) {
701 zlog_debug(
15569c58
DA
702 "%s: ignoring request for looped MFC entry (S,G)=%s: igmp_sock=%d oif=%s vif_index=%d",
703 __func__,
704 pim_str_sg_dump(&sg),
705 source->source_group
706 ->group_igmp_sock
707 ->fd,
708 source->source_group
709 ->group_igmp_sock
710 ->interface->name,
711 input_iface_vif_index);
732c209c
SP
712 }
713 return;
714 }
715
716 source->source_channel_oil =
15569c58 717 pim_channel_oil_add(pim, &sg, __func__);
732c209c
SP
718 if (!source->source_channel_oil) {
719 if (PIM_DEBUG_IGMP_TRACE) {
720 zlog_debug(
15569c58
DA
721 "%s %s: could not create OIL for channel (S,G)=%s",
722 __FILE__, __func__,
723 pim_str_sg_dump(&sg));
732c209c
SP
724 }
725 return;
726 }
d62a17ae 727 }
d62a17ae 728 }
8711a53d 729 }
d62a17ae 730
ac6ebcb0 731 if (PIM_I_am_DR(pim_oif) || PIM_I_am_DualActive(pim_oif)) {
8e389ea9
DS
732 result = pim_channel_add_oif(source->source_channel_oil,
733 group->group_igmp_sock->interface,
1b249e70 734 PIM_OIF_FLAG_PROTO_IGMP, __func__);
8e389ea9
DS
735 if (result) {
736 if (PIM_DEBUG_MROUTE) {
737 zlog_warn("%s: add_oif() failed with return=%d",
738 __func__, result);
739 }
740 return;
d62a17ae 741 }
8e389ea9 742 } else {
90a084e4 743 if (PIM_DEBUG_IGMP_TRACE)
15569c58
DA
744 zlog_debug(
745 "%s: %s was received on %s interface but we are not DR for that interface",
746 __func__, pim_str_sg_dump(&sg),
747 group->group_igmp_sock->interface->name);
b96892db 748
75c61a18 749 return;
90a084e4 750 }
d62a17ae 751 /*
752 Feed IGMPv3-gathered local membership information into PIM
753 per-interface (S,G) state.
754 */
755 if (!pim_ifchannel_local_membership_add(
448139e7
AK
756 group->group_igmp_sock->interface, &sg,
757 false /*is_vxlan*/)) {
d62a17ae 758 if (PIM_DEBUG_MROUTE)
759 zlog_warn("%s: Failure to add local membership for %s",
15569c58 760 __func__, pim_str_sg_dump(&sg));
b96892db
DS
761
762 pim_channel_del_oif(source->source_channel_oil,
763 group->group_igmp_sock->interface,
1b249e70 764 PIM_OIF_FLAG_PROTO_IGMP, __func__);
d62a17ae 765 return;
766 }
767
768 IGMP_SOURCE_DO_FORWARDING(source->source_flags);
12e41d03
DL
769}
770
771/*
772 igmp_source_forward_stop: stop fowarding, but keep the source
773 igmp_source_delete: stop fowarding, and delete the source
774 */
775void igmp_source_forward_stop(struct igmp_source *source)
776{
d62a17ae 777 struct igmp_group *group;
778 struct prefix_sg sg;
779 int result;
780
781 memset(&sg, 0, sizeof(struct prefix_sg));
782 sg.src = source->source_addr;
783 sg.grp = source->source_group->group_addr;
784
785 if (PIM_DEBUG_IGMP_TRACE) {
786 zlog_debug(
15569c58
DA
787 "%s: (S,G)=%s igmp_sock=%d oif=%s fwd=%d", __func__,
788 pim_str_sg_dump(&sg),
d62a17ae 789 source->source_group->group_igmp_sock->fd,
790 source->source_group->group_igmp_sock->interface->name,
791 IGMP_SOURCE_TEST_FORWARDING(source->source_flags));
792 }
793
794 /* Prevent IGMP interface from removing multicast route multiple
795 times */
796 if (!IGMP_SOURCE_TEST_FORWARDING(source->source_flags)) {
797 return;
798 }
799
800 group = source->source_group;
801
802 /*
803 It appears that in certain circumstances that
804 igmp_source_forward_stop is called when IGMP forwarding
805 was not enabled in oif_flags for this outgoing interface.
806 Possibly because of multiple calls. When that happens, we
807 enter the below if statement and this function returns early
808 which in turn triggers the calling function to assert.
809 Making the call to pim_channel_del_oif and ignoring the return code
810 fixes the issue without ill effect, similar to
811 pim_forward_stop below.
812 */
813 result = pim_channel_del_oif(source->source_channel_oil,
814 group->group_igmp_sock->interface,
1b249e70
AK
815 PIM_OIF_FLAG_PROTO_IGMP,
816 __func__);
d62a17ae 817 if (result) {
818 if (PIM_DEBUG_IGMP_TRACE)
819 zlog_debug(
820 "%s: pim_channel_del_oif() failed with return=%d",
821 __func__, result);
822 return;
823 }
824
825 /*
826 Feed IGMPv3-gathered local membership information into PIM
827 per-interface (S,G) state.
828 */
829 pim_ifchannel_local_membership_del(group->group_igmp_sock->interface,
830 &sg);
831
832 IGMP_SOURCE_DONT_FORWARDING(source->source_flags);
12e41d03
DL
833}
834
835void pim_forward_start(struct pim_ifchannel *ch)
836{
d62a17ae 837 struct pim_upstream *up = ch->upstream;
9443810e 838 uint32_t mask = 0;
d62a17ae 839
840 if (PIM_DEBUG_PIM_TRACE) {
841 char source_str[INET_ADDRSTRLEN];
842 char group_str[INET_ADDRSTRLEN];
843 char upstream_str[INET_ADDRSTRLEN];
844
845 pim_inet4_dump("<source?>", ch->sg.src, source_str,
846 sizeof(source_str));
847 pim_inet4_dump("<group?>", ch->sg.grp, group_str,
848 sizeof(group_str));
849 pim_inet4_dump("<upstream?>", up->upstream_addr, upstream_str,
850 sizeof(upstream_str));
15569c58 851 zlog_debug("%s: (S,G)=(%s,%s) oif=%s (%s)", __func__,
d62a17ae 852 source_str, group_str, ch->interface->name,
732c209c 853 inet_ntoa(up->upstream_addr));
d62a17ae 854 }
855
9443810e 856 if (PIM_IF_FLAG_TEST_PROTO_IGMP(ch->flags))
d62a17ae 857 mask = PIM_OIF_FLAG_PROTO_IGMP;
858
9443810e
SP
859 if (PIM_IF_FLAG_TEST_PROTO_PIM(ch->flags))
860 mask |= PIM_OIF_FLAG_PROTO_PIM;
861
1b249e70
AK
862 pim_channel_add_oif(up->channel_oil, ch->interface,
863 mask, __func__);
12e41d03
DL
864}
865
aabb9a2f 866void pim_forward_stop(struct pim_ifchannel *ch, bool install_it)
12e41d03 867{
d62a17ae 868 struct pim_upstream *up = ch->upstream;
12e41d03 869
d62a17ae 870 if (PIM_DEBUG_PIM_TRACE) {
aabb9a2f 871 zlog_debug("%s: (S,G)=%s oif=%s install_it: %d installed: %d",
15569c58 872 __func__, ch->sg_str, ch->interface->name,
aabb9a2f 873 install_it, up->channel_oil->installed);
d62a17ae 874 }
12e41d03 875
2164ed5d
DS
876 /*
877 * If a channel is being removed, check to see if we still need
878 * to inherit the interface. If so make sure it is added in
879 */
880 if (pim_upstream_evaluate_join_desired_interface(up, ch, ch->parent))
881 pim_channel_add_oif(up->channel_oil, ch->interface,
1b249e70 882 PIM_OIF_FLAG_PROTO_PIM, __func__);
2164ed5d
DS
883 else
884 pim_channel_del_oif(up->channel_oil, ch->interface,
1b249e70 885 PIM_OIF_FLAG_PROTO_PIM, __func__);
aabb9a2f
DS
886
887 if (install_it && !up->channel_oil->installed)
15569c58 888 pim_upstream_mroute_add(up->channel_oil, __func__);
12e41d03 889}
8799b66b 890
d62a17ae 891void pim_zebra_zclient_update(struct vty *vty)
8799b66b 892{
d62a17ae 893 vty_out(vty, "Zclient update socket: ");
894
895 if (zclient) {
896 vty_out(vty, "%d failures=%d\n", zclient->sock, zclient->fail);
897 } else {
898 vty_out(vty, "<null zclient>\n");
899 }
8799b66b 900}
1bc98276 901
d62a17ae 902struct zclient *pim_zebra_zclient_get(void)
1bc98276 903{
d62a17ae 904 if (zclient)
905 return zclient;
906 else
907 return NULL;
1bc98276 908}
ddbf3e60
DS
909
910void pim_zebra_interface_set_master(struct interface *vrf,
911 struct interface *ifp)
912{
913 zclient_interface_set_master(zclient, vrf, ifp);
914}