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