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