]> git.proxmox.com Git - mirror_frr.git/blame - pimd/pim_zebra.c
*: Convert prefix_free to double pointer
[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
d62a17ae 236 connected_free(c);
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)
292 pim_mroute_add(up->channel_oil,
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
SP
327 if (!up->channel_oil->installed)
328 pim_mroute_add(up->channel_oil, __PRETTY_FUNCTION__);
329 }
cc67ccf9 330
1250cb5d
SP
331 /* FIXME can join_desired actually be changed by pim_rpf_update()
332 * returning PIM_RPF_CHANGED ?
333 */
cc67ccf9
DS
334 pim_upstream_update_join_desired(pim, up);
335}
336
121f9dee 337static int pim_zebra_vxlan_sg_proc(ZAPI_CALLBACK_ARGS)
af7b561b
AK
338{
339 struct stream *s;
340 struct pim_instance *pim;
341 struct prefix_sg sg;
342
343 pim = pim_get_pim_instance(vrf_id);
344 if (!pim)
345 return 0;
346
347 s = zclient->ibuf;
348
349 sg.family = AF_INET;
350 sg.prefixlen = stream_getl(s);
351 stream_get(&sg.src.s_addr, s, sg.prefixlen);
352 stream_get(&sg.grp.s_addr, s, sg.prefixlen);
353
354 if (PIM_DEBUG_ZEBRA) {
355 char sg_str[PIM_SG_LEN];
356
357 pim_str_sg_set(&sg, sg_str);
358 zlog_debug("%u:recv SG %s %s", vrf_id,
121f9dee 359 (cmd == ZEBRA_VXLAN_SG_ADD)?"add":"del",
af7b561b
AK
360 sg_str);
361 }
362
121f9dee 363 if (cmd == ZEBRA_VXLAN_SG_ADD)
af7b561b
AK
364 pim_vxlan_sg_add(pim, &sg);
365 else
366 pim_vxlan_sg_del(pim, &sg);
367
368 return 0;
369}
370
ecbbc3a7
AK
371static void pim_zebra_vxlan_replay(void)
372{
373 struct stream *s = NULL;
374
375 /* Check socket. */
376 if (!zclient || zclient->sock < 0)
377 return;
378
379 s = zclient->obuf;
380 stream_reset(s);
381
382 zclient_create_header(s, ZEBRA_VXLAN_SG_REPLAY, VRF_DEFAULT);
383 stream_putw_at(s, 0, stream_get_endp(s));
384
385 zclient_send_message(zclient);
386}
387
d62a17ae 388void pim_scan_individual_oil(struct channel_oil *c_oil, int in_vif_index)
12e41d03 389{
d62a17ae 390 struct in_addr vif_source;
391 int input_iface_vif_index;
d62a17ae 392
732c209c 393 pim_rp_set_upstream_addr(c_oil->pim, &vif_source,
d9c9a9ee 394 c_oil->oil.mfcc_origin,
732c209c 395 c_oil->oil.mfcc_mcastgrp);
d62a17ae 396
397 if (in_vif_index)
398 input_iface_vif_index = in_vif_index;
399 else {
400 struct prefix src, grp;
401
402 src.family = AF_INET;
403 src.prefixlen = IPV4_MAX_BITLEN;
404 src.u.prefix4 = vif_source;
405 grp.family = AF_INET;
406 grp.prefixlen = IPV4_MAX_BITLEN;
407 grp.u.prefix4 = c_oil->oil.mfcc_mcastgrp;
408
409 if (PIM_DEBUG_ZEBRA) {
410 char source_str[INET_ADDRSTRLEN];
411 char group_str[INET_ADDRSTRLEN];
412 pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin,
413 source_str, sizeof(source_str));
414 pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp,
415 group_str, sizeof(group_str));
416 zlog_debug(
a895ac30 417 "%s: channel_oil (%s,%s) upstream info is not present.",
d62a17ae 418 __PRETTY_FUNCTION__, source_str, group_str);
419 }
420 input_iface_vif_index = pim_ecmp_fib_lookup_if_vif_index(
b938537b 421 c_oil->pim, &src, &grp);
d62a17ae 422 }
423
424 if (input_iface_vif_index < 1) {
425 if (PIM_DEBUG_ZEBRA) {
426 char source_str[INET_ADDRSTRLEN];
427 char group_str[INET_ADDRSTRLEN];
428 pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin,
429 source_str, sizeof(source_str));
430 pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp,
431 group_str, sizeof(group_str));
432 zlog_debug(
433 "%s %s: could not find input interface(%d) for (S,G)=(%s,%s)",
434 __FILE__, __PRETTY_FUNCTION__,
435 c_oil->oil.mfcc_parent, source_str, group_str);
436 }
437 pim_mroute_del(c_oil, __PRETTY_FUNCTION__);
438 return;
439 }
440
441 if (input_iface_vif_index == c_oil->oil.mfcc_parent) {
442 if (!c_oil->installed)
443 pim_mroute_add(c_oil, __PRETTY_FUNCTION__);
444
445 /* RPF unchanged */
446 return;
447 }
448
449 if (PIM_DEBUG_ZEBRA) {
7cfc7bcf
DS
450 struct interface *old_iif = pim_if_find_by_vif_index(
451 c_oil->pim, c_oil->oil.mfcc_parent);
452 struct interface *new_iif = pim_if_find_by_vif_index(
453 c_oil->pim, input_iface_vif_index);
d62a17ae 454 char source_str[INET_ADDRSTRLEN];
455 char group_str[INET_ADDRSTRLEN];
456 pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str,
457 sizeof(source_str));
458 pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str,
459 sizeof(group_str));
460 zlog_debug(
461 "%s %s: (S,G)=(%s,%s) input interface changed from %s vif_index=%d to %s vif_index=%d",
462 __FILE__, __PRETTY_FUNCTION__, source_str, group_str,
97f03dde
DS
463 (old_iif) ? old_iif->name : "<old_iif?>",
464 c_oil->oil.mfcc_parent,
465 (new_iif) ? new_iif->name : "<new_iif?>",
d62a17ae 466 input_iface_vif_index);
467 }
468
469 /* new iif loops to existing oif ? */
470 if (c_oil->oil.mfcc_ttls[input_iface_vif_index]) {
7cfc7bcf
DS
471 struct interface *new_iif = pim_if_find_by_vif_index(
472 c_oil->pim, input_iface_vif_index);
d62a17ae 473
474 if (PIM_DEBUG_ZEBRA) {
475 char source_str[INET_ADDRSTRLEN];
476 char group_str[INET_ADDRSTRLEN];
477 pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin,
478 source_str, sizeof(source_str));
479 pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp,
480 group_str, sizeof(group_str));
481 zlog_debug(
482 "%s %s: (S,G)=(%s,%s) new iif loops to existing oif: %s vif_index=%d",
483 __FILE__, __PRETTY_FUNCTION__, source_str,
97f03dde
DS
484 group_str,
485 (new_iif) ? new_iif->name : "<new_iif?>",
d62a17ae 486 input_iface_vif_index);
487 }
488 }
489
490 /* update iif vif_index */
afb2f470
DS
491 pim_channel_oil_change_iif(c_oil->pim, c_oil, input_iface_vif_index,
492 __PRETTY_FUNCTION__);
493 pim_mroute_add(c_oil, __PRETTY_FUNCTION__);
8a67a996
DS
494}
495
da11e325 496void pim_scan_oil(struct pim_instance *pim)
8a67a996 497{
d62a17ae 498 struct listnode *node;
499 struct listnode *nextnode;
500 struct channel_oil *c_oil;
501 ifindex_t ifindex;
502 int vif_index = 0;
503
bfc92019
DS
504 pim->scan_oil_last = pim_time_monotonic_sec();
505 ++pim->scan_oil_events;
d62a17ae 506
da11e325
DS
507 for (ALL_LIST_ELEMENTS(pim->channel_oil_list, node, nextnode, c_oil)) {
508 if (c_oil->up && c_oil->up->rpf.source_nexthop.interface) {
509 ifindex = c_oil->up->rpf.source_nexthop
510 .interface->ifindex;
511 vif_index =
512 pim_if_find_vifindex_by_ifindex(pim, ifindex);
513 /* Pass Current selected NH vif index to mroute
514 * download */
515 if (vif_index)
516 pim_scan_individual_oil(c_oil, vif_index);
517 } else
518 pim_scan_individual_oil(c_oil, 0);
d62a17ae 519 }
12e41d03
DL
520}
521
522static int on_rpf_cache_refresh(struct thread *t)
523{
da11e325
DS
524 struct pim_instance *pim = THREAD_ARG(t);
525
d62a17ae 526 /* update kernel multicast forwarding cache (MFC) */
da11e325 527 pim_scan_oil(pim);
12e41d03 528
bfc92019
DS
529 pim->rpf_cache_refresh_last = pim_time_monotonic_sec();
530 ++pim->rpf_cache_refresh_events;
12e41d03 531
d62a17ae 532 // It is called as part of pim_neighbor_add
533 // pim_rp_setup ();
534 return 0;
12e41d03
DL
535}
536
da11e325 537void sched_rpf_cache_refresh(struct pim_instance *pim)
12e41d03 538{
bfc92019 539 ++pim->rpf_cache_refresh_requests;
12e41d03 540
bfc92019 541 pim_rpf_set_refresh_time(pim);
e71bf8f7 542
da11e325 543 if (pim->rpf_cache_refresher) {
d62a17ae 544 /* Refresh timer is already running */
545 return;
546 }
12e41d03 547
d62a17ae 548 /* Start refresh timer */
12e41d03 549
d62a17ae 550 if (PIM_DEBUG_ZEBRA) {
551 zlog_debug("%s: triggering %ld msec timer", __PRETTY_FUNCTION__,
da03883e 552 router->rpf_cache_refresh_delay_msec);
d62a17ae 553 }
12e41d03 554
36417fcc 555 thread_add_timer_msec(router->master, on_rpf_cache_refresh, pim,
da03883e 556 router->rpf_cache_refresh_delay_msec,
da11e325 557 &pim->rpf_cache_refresher);
12e41d03
DL
558}
559
d62a17ae 560static void pim_zebra_connected(struct zclient *zclient)
48e8451b 561{
d62a17ae 562 /* Send the client registration */
0945d5ed 563 bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER, router->vrf_id);
ba4eb1bc 564
4dfe9ad2 565 zclient_send_reg_requests(zclient, router->vrf_id);
ecbbc3a7
AK
566
567 /* request for VxLAN BUM group addresses */
568 pim_zebra_vxlan_replay();
48e8451b 569}
8711a53d 570
ac567a6f
DS
571static void pim_zebra_capabilities(struct zclient_capabilities *cap)
572{
d6749d74 573 router->role = cap->role;
ac567a6f
DS
574}
575
eb05883f 576void pim_zebra_init(void)
12e41d03 577{
d62a17ae 578 /* Socket for receiving updates from Zebra daemon */
36417fcc 579 zclient = zclient_new(router->master, &zclient_options_default);
d62a17ae 580
ac567a6f 581 zclient->zebra_capabilities = pim_zebra_capabilities;
d62a17ae 582 zclient->zebra_connected = pim_zebra_connected;
583 zclient->router_id_update = pim_router_id_update_zebra;
d62a17ae 584 zclient->interface_address_add = pim_zebra_if_address_add;
585 zclient->interface_address_delete = pim_zebra_if_address_del;
ee568318 586 zclient->interface_vrf_update = pim_zebra_interface_vrf_update;
d62a17ae 587 zclient->nexthop_update = pim_parse_nexthop_update;
af7b561b
AK
588 zclient->vxlan_sg_add = pim_zebra_vxlan_sg_proc;
589 zclient->vxlan_sg_del = pim_zebra_vxlan_sg_proc;
d62a17ae 590
342213ea 591 zclient_init(zclient, ZEBRA_ROUTE_PIM, 0, &pimd_privs);
d62a17ae 592 if (PIM_DEBUG_PIM_TRACE) {
87270023 593 zlog_notice("%s: zclient socket initialized",
d62a17ae 594 __PRETTY_FUNCTION__);
595 }
596
597 zclient_lookup_new();
12e41d03
DL
598}
599
6f932b0c
DS
600void igmp_anysource_forward_start(struct pim_instance *pim,
601 struct igmp_group *group)
12e41d03 602{
d62a17ae 603 struct igmp_source *source;
604 struct in_addr src_addr = {.s_addr = 0};
605 /* Any source (*,G) is forwarded only if mode is EXCLUDE {empty} */
606 zassert(group->group_filtermode_isexcl);
607 zassert(listcount(group->group_source_list) < 1);
608
609 source = source_new(group, src_addr);
610 if (!source) {
611 zlog_warn("%s: Failure to create * source",
612 __PRETTY_FUNCTION__);
613 return;
614 }
615
6f932b0c 616 igmp_source_forward_start(pim, source);
12e41d03
DL
617}
618
619void igmp_anysource_forward_stop(struct igmp_group *group)
620{
d62a17ae 621 struct igmp_source *source;
622 struct in_addr star = {.s_addr = 0};
12e41d03 623
d62a17ae 624 source = igmp_find_source_by_addr(group, star);
625 if (source)
626 igmp_source_forward_stop(source);
12e41d03
DL
627}
628
6f439a70
DS
629static void igmp_source_forward_reevaluate_one(struct pim_instance *pim,
630 struct igmp_source *source)
15a5dafe 631{
d62a17ae 632 struct prefix_sg sg;
633 struct igmp_group *group = source->source_group;
634 struct pim_ifchannel *ch;
635
636 if ((source->source_addr.s_addr != INADDR_ANY)
637 || !IGMP_SOURCE_TEST_FORWARDING(source->source_flags))
638 return;
639
640 memset(&sg, 0, sizeof(struct prefix_sg));
641 sg.src = source->source_addr;
642 sg.grp = group->group_addr;
643
644 ch = pim_ifchannel_find(group->group_igmp_sock->interface, &sg);
6f439a70 645 if (pim_is_grp_ssm(pim, group->group_addr)) {
d62a17ae 646 /* If SSM group withdraw local membership */
647 if (ch
648 && (ch->local_ifmembership == PIM_IFMEMBERSHIP_INCLUDE)) {
649 if (PIM_DEBUG_PIM_EVENTS)
650 zlog_debug(
651 "local membership del for %s as G is now SSM",
652 pim_str_sg_dump(&sg));
653 pim_ifchannel_local_membership_del(
654 group->group_igmp_sock->interface, &sg);
655 }
656 } else {
657 /* If ASM group add local membership */
658 if (!ch
659 || (ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO)) {
660 if (PIM_DEBUG_PIM_EVENTS)
661 zlog_debug(
662 "local membership add for %s as G is now ASM",
663 pim_str_sg_dump(&sg));
664 pim_ifchannel_local_membership_add(
665 group->group_igmp_sock->interface, &sg);
666 }
667 }
15a5dafe 668}
669
5d59e408 670void igmp_source_forward_reevaluate_all(struct pim_instance *pim)
15a5dafe 671{
d62a17ae 672 struct interface *ifp;
673
5d59e408
DS
674 FOR_ALL_INTERFACES (pim->vrf, ifp) {
675 struct pim_interface *pim_ifp = ifp->info;
676 struct listnode *sock_node;
677 struct igmp_sock *igmp;
678
679 if (!pim_ifp)
d62a17ae 680 continue;
681
5d59e408
DS
682 /* scan igmp sockets */
683 for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node,
684 igmp)) {
685 struct listnode *grpnode;
686 struct igmp_group *grp;
687
688 /* scan igmp groups */
689 for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list,
690 grpnode, grp)) {
691 struct listnode *srcnode;
692 struct igmp_source *src;
693
694 /* scan group sources */
695 for (ALL_LIST_ELEMENTS_RO(
696 grp->group_source_list, srcnode,
697 src)) {
698 igmp_source_forward_reevaluate_one(pim,
699 src);
700 } /* scan group sources */
701 } /* scan igmp groups */
702 } /* scan igmp sockets */
703 } /* scan interfaces */
15a5dafe 704}
705
6f932b0c
DS
706void igmp_source_forward_start(struct pim_instance *pim,
707 struct igmp_source *source)
12e41d03 708{
75c61a18 709 struct pim_interface *pim_oif;
d62a17ae 710 struct igmp_group *group;
711 struct prefix_sg sg;
712 int result;
713 int input_iface_vif_index = 0;
714
715 memset(&sg, 0, sizeof(struct prefix_sg));
716 sg.src = source->source_addr;
717 sg.grp = source->source_group->group_addr;
718
719 if (PIM_DEBUG_IGMP_TRACE) {
720 zlog_debug(
721 "%s: (S,G)=%s igmp_sock=%d oif=%s fwd=%d",
722 __PRETTY_FUNCTION__, pim_str_sg_dump(&sg),
723 source->source_group->group_igmp_sock->fd,
724 source->source_group->group_igmp_sock->interface->name,
725 IGMP_SOURCE_TEST_FORWARDING(source->source_flags));
726 }
727
728 /* Prevent IGMP interface from installing multicast route multiple
729 times */
730 if (IGMP_SOURCE_TEST_FORWARDING(source->source_flags)) {
731 return;
8711a53d 732 }
d62a17ae 733
734 group = source->source_group;
75c61a18
DS
735 pim_oif = group->group_igmp_sock->interface->info;
736 if (!pim_oif) {
737 if (PIM_DEBUG_IGMP_TRACE) {
738 zlog_debug(
739 "%s: multicast not enabled on oif=%s ?",
740 __PRETTY_FUNCTION__,
741 source->source_group->group_igmp_sock
742 ->interface->name);
743 }
744 return;
745 }
d62a17ae 746
747 if (!source->source_channel_oil) {
748 struct in_addr vif_source;
d1a1b09c 749 struct prefix src, grp;
d62a17ae 750 struct pim_nexthop nexthop;
751 struct pim_upstream *up = NULL;
752
6f932b0c 753 if (!pim_rp_set_upstream_addr(pim, &vif_source,
732c209c
SP
754 source->source_addr, sg.grp)) {
755 /*Create a dummy channel oil */
8a3e7e9e
DS
756 source->source_channel_oil = pim_channel_oil_add(
757 pim, &sg, MAXVIFS, __PRETTY_FUNCTION__);
732c209c 758 }
d62a17ae 759
732c209c 760 else {
732c209c
SP
761 src.family = AF_INET;
762 src.prefixlen = IPV4_MAX_BITLEN;
763 src.u.prefix4 = vif_source; // RP or Src address
764 grp.family = AF_INET;
765 grp.prefixlen = IPV4_MAX_BITLEN;
766 grp.u.prefix4 = sg.grp;
767
43763b11
DS
768 up = pim_upstream_find(pim, &sg);
769 if (up) {
770 memcpy(&nexthop, &up->rpf.source_nexthop,
771 sizeof(struct pim_nexthop));
772 pim_ecmp_nexthop_lookup(pim, &nexthop, &src,
773 &grp, 0);
774 if (nexthop.interface)
775 input_iface_vif_index =
d62a17ae 776 pim_if_find_vifindex_by_ifindex(
43763b11
DS
777 pim,
778 nexthop.interface->ifindex);
732c209c
SP
779 } else
780 input_iface_vif_index =
43763b11
DS
781 pim_ecmp_fib_lookup_if_vif_index(
782 pim, &src, &grp);
d62a17ae 783
732c209c
SP
784 if (PIM_DEBUG_ZEBRA) {
785 char buf2[INET_ADDRSTRLEN];
d62a17ae 786
732c209c
SP
787 pim_inet4_dump("<source?>", vif_source, buf2,
788 sizeof(buf2));
789 zlog_debug("%s: NHT %s vif_source %s vif_index:%d ",
d62a17ae 790 __PRETTY_FUNCTION__,
791 pim_str_sg_dump(&sg),
732c209c 792 buf2, input_iface_vif_index);
d62a17ae 793 }
d62a17ae 794
732c209c
SP
795 if (input_iface_vif_index < 1) {
796 if (PIM_DEBUG_IGMP_TRACE) {
797 char source_str[INET_ADDRSTRLEN];
798 pim_inet4_dump("<source?>",
799 source->source_addr,
800 source_str, sizeof(source_str));
801 zlog_debug(
802 "%s %s: could not find input interface for source %s",
803 __FILE__, __PRETTY_FUNCTION__,
804 source_str);
805 }
806 source->source_channel_oil =
8a3e7e9e
DS
807 pim_channel_oil_add(
808 pim, &sg, MAXVIFS,
809 __PRETTY_FUNCTION__);
732c209c
SP
810 }
811
812 else {
813 /*
814 * Protect IGMP against adding looped MFC
815 * entries created by both source and receiver
816 * attached to the same interface. See TODO
50d06d9e 817 * T22. Block only when the intf is non DR
818 * DR must create upstream.
732c209c 819 */
50d06d9e 820 if ((input_iface_vif_index ==
821 pim_oif->mroute_vif_index) &&
822 !(PIM_I_am_DR(pim_oif))) {
732c209c
SP
823 /* ignore request for looped MFC entry
824 */
825 if (PIM_DEBUG_IGMP_TRACE) {
826 zlog_debug(
827 "%s: ignoring request for looped MFC entry (S,G)=%s: igmp_sock=%d oif=%s vif_index=%d",
828 __PRETTY_FUNCTION__,
829 pim_str_sg_dump(&sg),
830 source->source_group
831 ->group_igmp_sock->fd,
832 source->source_group
833 ->group_igmp_sock
834 ->interface->name,
835 input_iface_vif_index);
836 }
837 return;
838 }
839
840 source->source_channel_oil =
8a3e7e9e
DS
841 pim_channel_oil_add(
842 pim, &sg, input_iface_vif_index,
843 __PRETTY_FUNCTION__);
732c209c
SP
844 if (!source->source_channel_oil) {
845 if (PIM_DEBUG_IGMP_TRACE) {
846 zlog_debug(
847 "%s %s: could not create OIL for channel (S,G)=%s",
848 __FILE__,
849 __PRETTY_FUNCTION__,
850 pim_str_sg_dump(&sg));
851 }
852 return;
853 }
d62a17ae 854 }
d62a17ae 855 }
8711a53d 856 }
d62a17ae 857
858 result = pim_channel_add_oif(source->source_channel_oil,
859 group->group_igmp_sock->interface,
860 PIM_OIF_FLAG_PROTO_IGMP);
861 if (result) {
862 if (PIM_DEBUG_MROUTE) {
863 zlog_warn("%s: add_oif() failed with return=%d",
864 __func__, result);
865 }
866 return;
8711a53d 867 }
d62a17ae 868
90a084e4
DS
869 if (!(PIM_I_am_DR(pim_oif))) {
870 if (PIM_DEBUG_IGMP_TRACE)
871 zlog_debug("%s: %s was received on %s interface but we are not DR for that interface",
872 __PRETTY_FUNCTION__,
873 pim_str_sg_dump(&sg),
874 group->group_igmp_sock->interface->name);
b96892db
DS
875
876 pim_channel_del_oif(source->source_channel_oil,
877 group->group_igmp_sock->interface,
878 PIM_OIF_FLAG_PROTO_IGMP);
75c61a18 879 return;
90a084e4 880 }
d62a17ae 881 /*
882 Feed IGMPv3-gathered local membership information into PIM
883 per-interface (S,G) state.
884 */
885 if (!pim_ifchannel_local_membership_add(
75c61a18 886 group->group_igmp_sock->interface, &sg)) {
d62a17ae 887 if (PIM_DEBUG_MROUTE)
888 zlog_warn("%s: Failure to add local membership for %s",
889 __PRETTY_FUNCTION__, pim_str_sg_dump(&sg));
b96892db
DS
890
891 pim_channel_del_oif(source->source_channel_oil,
892 group->group_igmp_sock->interface,
893 PIM_OIF_FLAG_PROTO_IGMP);
d62a17ae 894 return;
895 }
896
897 IGMP_SOURCE_DO_FORWARDING(source->source_flags);
12e41d03
DL
898}
899
900/*
901 igmp_source_forward_stop: stop fowarding, but keep the source
902 igmp_source_delete: stop fowarding, and delete the source
903 */
904void igmp_source_forward_stop(struct igmp_source *source)
905{
d62a17ae 906 struct igmp_group *group;
907 struct prefix_sg sg;
908 int result;
909
910 memset(&sg, 0, sizeof(struct prefix_sg));
911 sg.src = source->source_addr;
912 sg.grp = source->source_group->group_addr;
913
914 if (PIM_DEBUG_IGMP_TRACE) {
915 zlog_debug(
916 "%s: (S,G)=%s igmp_sock=%d oif=%s fwd=%d",
917 __PRETTY_FUNCTION__, pim_str_sg_dump(&sg),
918 source->source_group->group_igmp_sock->fd,
919 source->source_group->group_igmp_sock->interface->name,
920 IGMP_SOURCE_TEST_FORWARDING(source->source_flags));
921 }
922
923 /* Prevent IGMP interface from removing multicast route multiple
924 times */
925 if (!IGMP_SOURCE_TEST_FORWARDING(source->source_flags)) {
926 return;
927 }
928
929 group = source->source_group;
930
931 /*
932 It appears that in certain circumstances that
933 igmp_source_forward_stop is called when IGMP forwarding
934 was not enabled in oif_flags for this outgoing interface.
935 Possibly because of multiple calls. When that happens, we
936 enter the below if statement and this function returns early
937 which in turn triggers the calling function to assert.
938 Making the call to pim_channel_del_oif and ignoring the return code
939 fixes the issue without ill effect, similar to
940 pim_forward_stop below.
941 */
942 result = pim_channel_del_oif(source->source_channel_oil,
943 group->group_igmp_sock->interface,
944 PIM_OIF_FLAG_PROTO_IGMP);
945 if (result) {
946 if (PIM_DEBUG_IGMP_TRACE)
947 zlog_debug(
948 "%s: pim_channel_del_oif() failed with return=%d",
949 __func__, result);
950 return;
951 }
952
953 /*
954 Feed IGMPv3-gathered local membership information into PIM
955 per-interface (S,G) state.
956 */
957 pim_ifchannel_local_membership_del(group->group_igmp_sock->interface,
958 &sg);
959
960 IGMP_SOURCE_DONT_FORWARDING(source->source_flags);
12e41d03
DL
961}
962
963void pim_forward_start(struct pim_ifchannel *ch)
964{
d62a17ae 965 struct pim_upstream *up = ch->upstream;
966 uint32_t mask = PIM_OIF_FLAG_PROTO_PIM;
d62a17ae 967
968 if (PIM_DEBUG_PIM_TRACE) {
969 char source_str[INET_ADDRSTRLEN];
970 char group_str[INET_ADDRSTRLEN];
971 char upstream_str[INET_ADDRSTRLEN];
972
973 pim_inet4_dump("<source?>", ch->sg.src, source_str,
974 sizeof(source_str));
975 pim_inet4_dump("<group?>", ch->sg.grp, group_str,
976 sizeof(group_str));
977 pim_inet4_dump("<upstream?>", up->upstream_addr, upstream_str,
978 sizeof(upstream_str));
979 zlog_debug("%s: (S,G)=(%s,%s) oif=%s (%s)", __PRETTY_FUNCTION__,
980 source_str, group_str, ch->interface->name,
732c209c 981 inet_ntoa(up->upstream_addr));
d62a17ae 982 }
983
d62a17ae 984 if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP)
985 mask = PIM_OIF_FLAG_PROTO_IGMP;
986
987 pim_channel_add_oif(up->channel_oil, ch->interface, mask);
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,
1006 PIM_OIF_FLAG_PROTO_PIM);
1007 else
1008 pim_channel_del_oif(up->channel_oil, ch->interface,
1009 PIM_OIF_FLAG_PROTO_PIM);
aabb9a2f
DS
1010
1011 if (install_it && !up->channel_oil->installed)
1012 pim_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}