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