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