]> git.proxmox.com Git - mirror_frr.git/blame - pimd/pim_zebra.c
Merge pull request #5430 from taruta811/build-docker-centos
[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)
275 pim_jp_agg_remove_group(nbr->upstream_jp_agg, up);
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)
293 pim_mroute_add(up->channel_oil,
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
1250cb5d
SP
328 if (!up->channel_oil->installed)
329 pim_mroute_add(up->channel_oil, __PRETTY_FUNCTION__);
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)
444 pim_mroute_add(c_oil, __PRETTY_FUNCTION__);
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__);
494 pim_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;
46c2687c
SK
591 zclient->mlag_process_up = pim_zebra_mlag_process_up;
592 zclient->mlag_process_down = pim_zebra_mlag_process_down;
593 zclient->mlag_handle_msg = pim_zebra_mlag_handle_msg;
d62a17ae 594
342213ea 595 zclient_init(zclient, ZEBRA_ROUTE_PIM, 0, &pimd_privs);
d62a17ae 596 if (PIM_DEBUG_PIM_TRACE) {
87270023 597 zlog_notice("%s: zclient socket initialized",
d62a17ae 598 __PRETTY_FUNCTION__);
599 }
600
601 zclient_lookup_new();
12e41d03
DL
602}
603
6f932b0c
DS
604void igmp_anysource_forward_start(struct pim_instance *pim,
605 struct igmp_group *group)
12e41d03 606{
d62a17ae 607 struct igmp_source *source;
608 struct in_addr src_addr = {.s_addr = 0};
609 /* Any source (*,G) is forwarded only if mode is EXCLUDE {empty} */
610 zassert(group->group_filtermode_isexcl);
611 zassert(listcount(group->group_source_list) < 1);
612
613 source = source_new(group, src_addr);
614 if (!source) {
615 zlog_warn("%s: Failure to create * source",
616 __PRETTY_FUNCTION__);
617 return;
618 }
619
6f932b0c 620 igmp_source_forward_start(pim, source);
12e41d03
DL
621}
622
623void igmp_anysource_forward_stop(struct igmp_group *group)
624{
d62a17ae 625 struct igmp_source *source;
626 struct in_addr star = {.s_addr = 0};
12e41d03 627
d62a17ae 628 source = igmp_find_source_by_addr(group, star);
629 if (source)
630 igmp_source_forward_stop(source);
12e41d03
DL
631}
632
6f439a70
DS
633static void igmp_source_forward_reevaluate_one(struct pim_instance *pim,
634 struct igmp_source *source)
15a5dafe 635{
d62a17ae 636 struct prefix_sg sg;
637 struct igmp_group *group = source->source_group;
638 struct pim_ifchannel *ch;
639
640 if ((source->source_addr.s_addr != INADDR_ANY)
641 || !IGMP_SOURCE_TEST_FORWARDING(source->source_flags))
642 return;
643
644 memset(&sg, 0, sizeof(struct prefix_sg));
645 sg.src = source->source_addr;
646 sg.grp = group->group_addr;
647
648 ch = pim_ifchannel_find(group->group_igmp_sock->interface, &sg);
6f439a70 649 if (pim_is_grp_ssm(pim, group->group_addr)) {
d62a17ae 650 /* If SSM group withdraw local membership */
651 if (ch
652 && (ch->local_ifmembership == PIM_IFMEMBERSHIP_INCLUDE)) {
653 if (PIM_DEBUG_PIM_EVENTS)
654 zlog_debug(
655 "local membership del for %s as G is now SSM",
656 pim_str_sg_dump(&sg));
657 pim_ifchannel_local_membership_del(
658 group->group_igmp_sock->interface, &sg);
659 }
660 } else {
661 /* If ASM group add local membership */
662 if (!ch
663 || (ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO)) {
664 if (PIM_DEBUG_PIM_EVENTS)
665 zlog_debug(
666 "local membership add for %s as G is now ASM",
667 pim_str_sg_dump(&sg));
668 pim_ifchannel_local_membership_add(
669 group->group_igmp_sock->interface, &sg);
670 }
671 }
15a5dafe 672}
673
5d59e408 674void igmp_source_forward_reevaluate_all(struct pim_instance *pim)
15a5dafe 675{
d62a17ae 676 struct interface *ifp;
677
5d59e408
DS
678 FOR_ALL_INTERFACES (pim->vrf, ifp) {
679 struct pim_interface *pim_ifp = ifp->info;
680 struct listnode *sock_node;
681 struct igmp_sock *igmp;
682
683 if (!pim_ifp)
d62a17ae 684 continue;
685
5d59e408
DS
686 /* scan igmp sockets */
687 for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node,
688 igmp)) {
689 struct listnode *grpnode;
690 struct igmp_group *grp;
691
692 /* scan igmp groups */
693 for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list,
694 grpnode, grp)) {
695 struct listnode *srcnode;
696 struct igmp_source *src;
697
698 /* scan group sources */
699 for (ALL_LIST_ELEMENTS_RO(
700 grp->group_source_list, srcnode,
701 src)) {
702 igmp_source_forward_reevaluate_one(pim,
703 src);
704 } /* scan group sources */
705 } /* scan igmp groups */
706 } /* scan igmp sockets */
707 } /* scan interfaces */
15a5dafe 708}
709
6f932b0c
DS
710void igmp_source_forward_start(struct pim_instance *pim,
711 struct igmp_source *source)
12e41d03 712{
75c61a18 713 struct pim_interface *pim_oif;
d62a17ae 714 struct igmp_group *group;
715 struct prefix_sg sg;
716 int result;
717 int input_iface_vif_index = 0;
718
719 memset(&sg, 0, sizeof(struct prefix_sg));
720 sg.src = source->source_addr;
721 sg.grp = source->source_group->group_addr;
722
723 if (PIM_DEBUG_IGMP_TRACE) {
724 zlog_debug(
725 "%s: (S,G)=%s igmp_sock=%d oif=%s fwd=%d",
726 __PRETTY_FUNCTION__, pim_str_sg_dump(&sg),
727 source->source_group->group_igmp_sock->fd,
728 source->source_group->group_igmp_sock->interface->name,
729 IGMP_SOURCE_TEST_FORWARDING(source->source_flags));
730 }
731
732 /* Prevent IGMP interface from installing multicast route multiple
733 times */
734 if (IGMP_SOURCE_TEST_FORWARDING(source->source_flags)) {
735 return;
8711a53d 736 }
d62a17ae 737
738 group = source->source_group;
75c61a18
DS
739 pim_oif = group->group_igmp_sock->interface->info;
740 if (!pim_oif) {
741 if (PIM_DEBUG_IGMP_TRACE) {
742 zlog_debug(
743 "%s: multicast not enabled on oif=%s ?",
744 __PRETTY_FUNCTION__,
745 source->source_group->group_igmp_sock
746 ->interface->name);
747 }
748 return;
749 }
d62a17ae 750
751 if (!source->source_channel_oil) {
752 struct in_addr vif_source;
d1a1b09c 753 struct prefix src, grp;
d62a17ae 754 struct pim_nexthop nexthop;
755 struct pim_upstream *up = NULL;
756
6f932b0c 757 if (!pim_rp_set_upstream_addr(pim, &vif_source,
732c209c
SP
758 source->source_addr, sg.grp)) {
759 /*Create a dummy channel oil */
8a3e7e9e
DS
760 source->source_channel_oil = pim_channel_oil_add(
761 pim, &sg, MAXVIFS, __PRETTY_FUNCTION__);
732c209c 762 }
d62a17ae 763
732c209c 764 else {
732c209c
SP
765 src.family = AF_INET;
766 src.prefixlen = IPV4_MAX_BITLEN;
767 src.u.prefix4 = vif_source; // RP or Src address
768 grp.family = AF_INET;
769 grp.prefixlen = IPV4_MAX_BITLEN;
770 grp.u.prefix4 = sg.grp;
771
43763b11
DS
772 up = pim_upstream_find(pim, &sg);
773 if (up) {
774 memcpy(&nexthop, &up->rpf.source_nexthop,
775 sizeof(struct pim_nexthop));
776 pim_ecmp_nexthop_lookup(pim, &nexthop, &src,
777 &grp, 0);
778 if (nexthop.interface)
779 input_iface_vif_index =
d62a17ae 780 pim_if_find_vifindex_by_ifindex(
43763b11
DS
781 pim,
782 nexthop.interface->ifindex);
732c209c
SP
783 } else
784 input_iface_vif_index =
43763b11
DS
785 pim_ecmp_fib_lookup_if_vif_index(
786 pim, &src, &grp);
d62a17ae 787
732c209c
SP
788 if (PIM_DEBUG_ZEBRA) {
789 char buf2[INET_ADDRSTRLEN];
d62a17ae 790
732c209c
SP
791 pim_inet4_dump("<source?>", vif_source, buf2,
792 sizeof(buf2));
793 zlog_debug("%s: NHT %s vif_source %s vif_index:%d ",
d62a17ae 794 __PRETTY_FUNCTION__,
795 pim_str_sg_dump(&sg),
732c209c 796 buf2, input_iface_vif_index);
d62a17ae 797 }
d62a17ae 798
732c209c
SP
799 if (input_iface_vif_index < 1) {
800 if (PIM_DEBUG_IGMP_TRACE) {
801 char source_str[INET_ADDRSTRLEN];
802 pim_inet4_dump("<source?>",
803 source->source_addr,
804 source_str, sizeof(source_str));
805 zlog_debug(
806 "%s %s: could not find input interface for source %s",
807 __FILE__, __PRETTY_FUNCTION__,
808 source_str);
809 }
810 source->source_channel_oil =
8a3e7e9e
DS
811 pim_channel_oil_add(
812 pim, &sg, MAXVIFS,
813 __PRETTY_FUNCTION__);
732c209c
SP
814 }
815
816 else {
817 /*
818 * Protect IGMP against adding looped MFC
819 * entries created by both source and receiver
820 * attached to the same interface. See TODO
50d06d9e 821 * T22. Block only when the intf is non DR
822 * DR must create upstream.
732c209c 823 */
50d06d9e 824 if ((input_iface_vif_index ==
825 pim_oif->mroute_vif_index) &&
826 !(PIM_I_am_DR(pim_oif))) {
732c209c
SP
827 /* ignore request for looped MFC entry
828 */
829 if (PIM_DEBUG_IGMP_TRACE) {
830 zlog_debug(
831 "%s: ignoring request for looped MFC entry (S,G)=%s: igmp_sock=%d oif=%s vif_index=%d",
832 __PRETTY_FUNCTION__,
833 pim_str_sg_dump(&sg),
834 source->source_group
835 ->group_igmp_sock->fd,
836 source->source_group
837 ->group_igmp_sock
838 ->interface->name,
839 input_iface_vif_index);
840 }
841 return;
842 }
843
844 source->source_channel_oil =
8a3e7e9e
DS
845 pim_channel_oil_add(
846 pim, &sg, input_iface_vif_index,
847 __PRETTY_FUNCTION__);
732c209c
SP
848 if (!source->source_channel_oil) {
849 if (PIM_DEBUG_IGMP_TRACE) {
850 zlog_debug(
851 "%s %s: could not create OIL for channel (S,G)=%s",
852 __FILE__,
853 __PRETTY_FUNCTION__,
854 pim_str_sg_dump(&sg));
855 }
856 return;
857 }
d62a17ae 858 }
d62a17ae 859 }
8711a53d 860 }
d62a17ae 861
8e389ea9
DS
862 if (PIM_I_am_DR(pim_oif)) {
863 result = pim_channel_add_oif(source->source_channel_oil,
864 group->group_igmp_sock->interface,
865 PIM_OIF_FLAG_PROTO_IGMP);
866 if (result) {
867 if (PIM_DEBUG_MROUTE) {
868 zlog_warn("%s: add_oif() failed with return=%d",
869 __func__, result);
870 }
871 return;
d62a17ae 872 }
8e389ea9 873 } else {
90a084e4
DS
874 if (PIM_DEBUG_IGMP_TRACE)
875 zlog_debug("%s: %s was received on %s interface but we are not DR for that interface",
876 __PRETTY_FUNCTION__,
877 pim_str_sg_dump(&sg),
878 group->group_igmp_sock->interface->name);
b96892db 879
75c61a18 880 return;
90a084e4 881 }
d62a17ae 882 /*
883 Feed IGMPv3-gathered local membership information into PIM
884 per-interface (S,G) state.
885 */
886 if (!pim_ifchannel_local_membership_add(
75c61a18 887 group->group_igmp_sock->interface, &sg)) {
d62a17ae 888 if (PIM_DEBUG_MROUTE)
889 zlog_warn("%s: Failure to add local membership for %s",
890 __PRETTY_FUNCTION__, pim_str_sg_dump(&sg));
b96892db
DS
891
892 pim_channel_del_oif(source->source_channel_oil,
893 group->group_igmp_sock->interface,
894 PIM_OIF_FLAG_PROTO_IGMP);
d62a17ae 895 return;
896 }
897
898 IGMP_SOURCE_DO_FORWARDING(source->source_flags);
12e41d03
DL
899}
900
901/*
902 igmp_source_forward_stop: stop fowarding, but keep the source
903 igmp_source_delete: stop fowarding, and delete the source
904 */
905void igmp_source_forward_stop(struct igmp_source *source)
906{
d62a17ae 907 struct igmp_group *group;
908 struct prefix_sg sg;
909 int result;
910
911 memset(&sg, 0, sizeof(struct prefix_sg));
912 sg.src = source->source_addr;
913 sg.grp = source->source_group->group_addr;
914
915 if (PIM_DEBUG_IGMP_TRACE) {
916 zlog_debug(
917 "%s: (S,G)=%s igmp_sock=%d oif=%s fwd=%d",
918 __PRETTY_FUNCTION__, pim_str_sg_dump(&sg),
919 source->source_group->group_igmp_sock->fd,
920 source->source_group->group_igmp_sock->interface->name,
921 IGMP_SOURCE_TEST_FORWARDING(source->source_flags));
922 }
923
924 /* Prevent IGMP interface from removing multicast route multiple
925 times */
926 if (!IGMP_SOURCE_TEST_FORWARDING(source->source_flags)) {
927 return;
928 }
929
930 group = source->source_group;
931
932 /*
933 It appears that in certain circumstances that
934 igmp_source_forward_stop is called when IGMP forwarding
935 was not enabled in oif_flags for this outgoing interface.
936 Possibly because of multiple calls. When that happens, we
937 enter the below if statement and this function returns early
938 which in turn triggers the calling function to assert.
939 Making the call to pim_channel_del_oif and ignoring the return code
940 fixes the issue without ill effect, similar to
941 pim_forward_stop below.
942 */
943 result = pim_channel_del_oif(source->source_channel_oil,
944 group->group_igmp_sock->interface,
945 PIM_OIF_FLAG_PROTO_IGMP);
946 if (result) {
947 if (PIM_DEBUG_IGMP_TRACE)
948 zlog_debug(
949 "%s: pim_channel_del_oif() failed with return=%d",
950 __func__, result);
951 return;
952 }
953
954 /*
955 Feed IGMPv3-gathered local membership information into PIM
956 per-interface (S,G) state.
957 */
958 pim_ifchannel_local_membership_del(group->group_igmp_sock->interface,
959 &sg);
960
961 IGMP_SOURCE_DONT_FORWARDING(source->source_flags);
12e41d03
DL
962}
963
964void pim_forward_start(struct pim_ifchannel *ch)
965{
d62a17ae 966 struct pim_upstream *up = ch->upstream;
967 uint32_t mask = PIM_OIF_FLAG_PROTO_PIM;
d62a17ae 968
969 if (PIM_DEBUG_PIM_TRACE) {
970 char source_str[INET_ADDRSTRLEN];
971 char group_str[INET_ADDRSTRLEN];
972 char upstream_str[INET_ADDRSTRLEN];
973
974 pim_inet4_dump("<source?>", ch->sg.src, source_str,
975 sizeof(source_str));
976 pim_inet4_dump("<group?>", ch->sg.grp, group_str,
977 sizeof(group_str));
978 pim_inet4_dump("<upstream?>", up->upstream_addr, upstream_str,
979 sizeof(upstream_str));
980 zlog_debug("%s: (S,G)=(%s,%s) oif=%s (%s)", __PRETTY_FUNCTION__,
981 source_str, group_str, ch->interface->name,
732c209c 982 inet_ntoa(up->upstream_addr));
d62a17ae 983 }
984
d62a17ae 985 if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP)
986 mask = PIM_OIF_FLAG_PROTO_IGMP;
987
988 pim_channel_add_oif(up->channel_oil, ch->interface, mask);
12e41d03
DL
989}
990
aabb9a2f 991void pim_forward_stop(struct pim_ifchannel *ch, bool install_it)
12e41d03 992{
d62a17ae 993 struct pim_upstream *up = ch->upstream;
12e41d03 994
d62a17ae 995 if (PIM_DEBUG_PIM_TRACE) {
aabb9a2f
DS
996 zlog_debug("%s: (S,G)=%s oif=%s install_it: %d installed: %d",
997 __PRETTY_FUNCTION__, ch->sg_str, ch->interface->name,
998 install_it, up->channel_oil->installed);
d62a17ae 999 }
12e41d03 1000
2164ed5d
DS
1001 /*
1002 * If a channel is being removed, check to see if we still need
1003 * to inherit the interface. If so make sure it is added in
1004 */
1005 if (pim_upstream_evaluate_join_desired_interface(up, ch, ch->parent))
1006 pim_channel_add_oif(up->channel_oil, ch->interface,
1007 PIM_OIF_FLAG_PROTO_PIM);
1008 else
1009 pim_channel_del_oif(up->channel_oil, ch->interface,
1010 PIM_OIF_FLAG_PROTO_PIM);
aabb9a2f
DS
1011
1012 if (install_it && !up->channel_oil->installed)
1013 pim_mroute_add(up->channel_oil, __PRETTY_FUNCTION__);
12e41d03 1014}
8799b66b 1015
d62a17ae 1016void pim_zebra_zclient_update(struct vty *vty)
8799b66b 1017{
d62a17ae 1018 vty_out(vty, "Zclient update socket: ");
1019
1020 if (zclient) {
1021 vty_out(vty, "%d failures=%d\n", zclient->sock, zclient->fail);
1022 } else {
1023 vty_out(vty, "<null zclient>\n");
1024 }
8799b66b 1025}
1bc98276 1026
d62a17ae 1027struct zclient *pim_zebra_zclient_get(void)
1bc98276 1028{
d62a17ae 1029 if (zclient)
1030 return zclient;
1031 else
1032 return NULL;
1bc98276 1033}
ddbf3e60
DS
1034
1035void pim_zebra_interface_set_master(struct interface *vrf,
1036 struct interface *ifp)
1037{
1038 zclient_interface_set_master(zclient, vrf, ifp);
1039}