1 // SPDX-License-Identifier: GPL-2.0-or-later
4 * Copyright (C) 2008 Everton da Silva Marques
21 #include "pim_zebra.h"
22 #include "pim_iface.h"
28 #include "pim_zlookup.h"
29 #include "pim_ifchannel.h"
31 #include "pim_igmpv3.h"
32 #include "pim_jp_agg.h"
35 #include "pim_vxlan.h"
38 #undef PIM_DEBUG_IFADDR_DUMP
39 #define PIM_DEBUG_IFADDR_DUMP
41 struct zclient
*zclient
;
44 /* Router-id update message from zebra. */
45 static int pim_router_id_update_zebra(ZAPI_CALLBACK_ARGS
)
47 struct prefix router_id
;
49 zebra_router_id_update_read(zclient
->ibuf
, &router_id
);
54 static int pim_zebra_interface_vrf_update(ZAPI_CALLBACK_ARGS
)
56 struct interface
*ifp
;
58 struct pim_instance
*pim
;
59 struct pim_interface
*pim_ifp
;
61 ifp
= zebra_interface_vrf_update_read(zclient
->ibuf
, vrf_id
,
67 zlog_debug("%s: %s updating from %u to %u", __func__
, ifp
->name
,
70 pim
= pim_get_pim_instance(new_vrf_id
);
72 if_update_to_new_vrf(ifp
, new_vrf_id
);
78 pim_ifp
->pim
->mcast_if_count
--;
80 pim_ifp
->pim
->mcast_if_count
++;
85 #ifdef PIM_DEBUG_IFADDR_DUMP
86 static void dump_if_address(struct interface
*ifp
)
88 struct connected
*ifc
;
89 struct listnode
*node
;
91 zlog_debug("%s %s: interface %s addresses:", __FILE__
, __func__
,
94 for (ALL_LIST_ELEMENTS_RO(ifp
->connected
, node
, ifc
)) {
95 struct prefix
*p
= ifc
->address
;
97 if (p
->family
!= AF_INET
)
100 zlog_debug("%s %s: interface %s address %pI4 %s", __FILE__
,
101 __func__
, ifp
->name
, &p
->u
.prefix4
,
102 CHECK_FLAG(ifc
->flags
, ZEBRA_IFA_SECONDARY
)
109 static int pim_zebra_if_address_add(ZAPI_CALLBACK_ARGS
)
113 struct pim_interface
*pim_ifp
;
116 zebra api notifies address adds/dels events by using the same call
117 interface_add_read below, see comments in lib/zclient.c
119 zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_ADD, ...)
120 will add address to interface list by calling
121 connected_add_by_prefix()
123 c
= zebra_interface_address_read(cmd
, zclient
->ibuf
, vrf_id
);
127 pim_ifp
= c
->ifp
->info
;
130 if (PIM_DEBUG_ZEBRA
) {
131 zlog_debug("%s: %s(%u) connected IP address %pFX flags %u %s",
132 __func__
, c
->ifp
->name
, vrf_id
, p
, c
->flags
,
133 CHECK_FLAG(c
->flags
, ZEBRA_IFA_SECONDARY
)
137 #ifdef PIM_DEBUG_IFADDR_DUMP
138 dump_if_address(c
->ifp
);
143 if (p
->family
!= PIM_AF
)
144 SET_FLAG(c
->flags
, ZEBRA_IFA_SECONDARY
);
145 else if (!CHECK_FLAG(c
->flags
, ZEBRA_IFA_SECONDARY
)) {
146 /* trying to add primary address? */
147 pim_addr primary_addr
= pim_find_primary_addr(c
->ifp
);
148 pim_addr addr
= pim_addr_from_prefix(p
);
150 if (pim_addr_cmp(primary_addr
, addr
)) {
153 "%s: %s : forcing secondary flag on %pFX",
154 __func__
, c
->ifp
->name
, p
);
155 SET_FLAG(c
->flags
, ZEBRA_IFA_SECONDARY
);
158 #else /* PIM_IPV != 4 */
159 if (p
->family
!= PIM_AF
)
165 struct pim_instance
*pim
;
167 pim
= pim_get_pim_instance(vrf_id
);
170 zlog_debug("%s: Unable to find pim instance",
177 pim_rp_check_on_if_add(pim_ifp
);
180 if (if_is_loopback(c
->ifp
)) {
181 struct vrf
*vrf
= vrf_lookup_by_id(vrf_id
);
182 struct interface
*ifp
;
184 FOR_ALL_INTERFACES (vrf
, ifp
) {
185 if (!if_is_loopback(ifp
) && if_is_operative(ifp
))
186 pim_if_addr_add_all(ifp
);
192 static int pim_zebra_if_address_del(ZAPI_CALLBACK_ARGS
)
196 struct vrf
*vrf
= vrf_lookup_by_id(vrf_id
);
202 zebra api notifies address adds/dels events by using the same call
203 interface_add_read below, see comments in lib/zclient.c
205 zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_DELETE, ...)
206 will remove address from interface list by calling
207 connected_delete_by_prefix()
209 c
= zebra_interface_address_read(cmd
, zclient
->ibuf
, vrf_id
);
215 if (PIM_DEBUG_ZEBRA
) {
217 "%s: %s(%u) disconnected IP address %pFX flags %u %s",
218 __func__
, c
->ifp
->name
, vrf_id
, p
, c
->flags
,
219 CHECK_FLAG(c
->flags
, ZEBRA_IFA_SECONDARY
)
222 #ifdef PIM_DEBUG_IFADDR_DUMP
223 dump_if_address(c
->ifp
);
227 if (p
->family
== PIM_AF
) {
228 struct pim_instance
*pim
;
231 pim_if_addr_del(c
, 0);
233 pim_i_am_rp_re_evaluate(pim
);
240 void pim_zebra_update_all_interfaces(struct pim_instance
*pim
)
242 struct interface
*ifp
;
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
;
252 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->upstream_switch_list
, node
,
256 rpf
.source_nexthop
.interface
= ifp
;
257 rpf
.rpf_addr
= us
->address
;
258 pim_joinprune_send(&rpf
, us
->us
);
259 pim_jp_agg_clear_group(us
->us
);
264 void pim_zebra_upstream_rpf_changed(struct pim_instance
*pim
,
265 struct pim_upstream
*up
,
268 if (old
->source_nexthop
.interface
) {
269 struct pim_neighbor
*nbr
;
271 nbr
= pim_neighbor_find(old
->source_nexthop
.interface
,
272 old
->rpf_addr
, true);
275 pim_jp_agg_remove_group(nbr
->upstream_jp_agg
, up
, nbr
);
278 * We have detected a case where we might need
279 * to rescan the inherited o_list so do it.
281 if (up
->channel_oil
->oil_inherited_rescan
) {
282 pim_upstream_inherited_olist_decide(pim
, up
);
283 up
->channel_oil
->oil_inherited_rescan
= 0;
286 if (up
->join_state
== PIM_UPSTREAM_JOINED
) {
288 * If we come up real fast we can be here
289 * where the mroute has not been installed
292 if (!up
->channel_oil
->installed
)
293 pim_upstream_mroute_add(up
->channel_oil
,
297 * RFC 4601: 4.5.7. Sending (S,G)
298 * Join/Prune Messages
300 * Transitions from Joined State
302 * RPF'(S,G) changes not due to an Assert
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.
312 pim_jp_agg_switch_interface(old
, &up
->rpf
, up
);
314 pim_upstream_join_timer_restart(up
, old
);
315 } /* up->join_state == PIM_UPSTREAM_JOINED */
320 * We have detected a case where we might need
321 * to rescan the inherited o_list so do it.
323 if (up
->channel_oil
->oil_inherited_rescan
) {
324 pim_upstream_inherited_olist_decide(pim
, up
);
325 up
->channel_oil
->oil_inherited_rescan
= 0;
328 if (up
->join_state
== PIM_UPSTREAM_JOINED
)
329 pim_jp_agg_switch_interface(old
, &up
->rpf
, up
);
331 if (!up
->channel_oil
->installed
)
332 pim_upstream_mroute_add(up
->channel_oil
, __func__
);
335 /* FIXME can join_desired actually be changed by pim_rpf_update()
336 * returning PIM_RPF_CHANGED ?
338 pim_upstream_update_join_desired(pim
, up
);
341 __attribute__((unused
))
342 static int pim_zebra_vxlan_sg_proc(ZAPI_CALLBACK_ARGS
)
345 struct pim_instance
*pim
;
349 pim
= pim_get_pim_instance(vrf_id
);
355 prefixlen
= stream_getl(s
);
356 stream_get(&sg
.src
, s
, prefixlen
);
357 stream_get(&sg
.grp
, s
, prefixlen
);
360 zlog_debug("%u:recv SG %s %pSG", vrf_id
,
361 (cmd
== ZEBRA_VXLAN_SG_ADD
) ? "add" : "del", &sg
);
363 if (cmd
== ZEBRA_VXLAN_SG_ADD
)
364 pim_vxlan_sg_add(pim
, &sg
);
366 pim_vxlan_sg_del(pim
, &sg
);
371 __attribute__((unused
))
372 static void pim_zebra_vxlan_replay(void)
374 struct stream
*s
= NULL
;
377 if (!zclient
|| zclient
->sock
< 0)
383 zclient_create_header(s
, ZEBRA_VXLAN_SG_REPLAY
, VRF_DEFAULT
);
384 stream_putw_at(s
, 0, stream_get_endp(s
));
386 zclient_send_message(zclient
);
389 void pim_scan_oil(struct pim_instance
*pim
)
391 struct channel_oil
*c_oil
;
393 pim
->scan_oil_last
= pim_time_monotonic_sec();
394 ++pim
->scan_oil_events
;
396 frr_each (rb_pim_oil
, &pim
->channel_oil_head
, c_oil
)
397 pim_upstream_mroute_iif_update(c_oil
, __func__
);
400 static void on_rpf_cache_refresh(struct event
*t
)
402 struct pim_instance
*pim
= EVENT_ARG(t
);
404 /* update kernel multicast forwarding cache (MFC) */
407 pim
->rpf_cache_refresh_last
= pim_time_monotonic_sec();
408 ++pim
->rpf_cache_refresh_events
;
410 // It is called as part of pim_neighbor_add
414 void sched_rpf_cache_refresh(struct pim_instance
*pim
)
416 ++pim
->rpf_cache_refresh_requests
;
418 pim_rpf_set_refresh_time(pim
);
420 if (pim
->rpf_cache_refresher
) {
421 /* Refresh timer is already running */
425 /* Start refresh timer */
427 if (PIM_DEBUG_ZEBRA
) {
428 zlog_debug("%s: triggering %ld msec timer", __func__
,
429 router
->rpf_cache_refresh_delay_msec
);
432 event_add_timer_msec(router
->master
, on_rpf_cache_refresh
, pim
,
433 router
->rpf_cache_refresh_delay_msec
,
434 &pim
->rpf_cache_refresher
);
437 static void pim_zebra_connected(struct zclient
*zclient
)
440 /* Send the client registration */
441 bfd_client_sendmsg(zclient
, ZEBRA_BFD_CLIENT_REGISTER
, router
->vrf_id
);
444 zclient_send_reg_requests(zclient
, router
->vrf_id
);
447 /* request for VxLAN BUM group addresses */
448 pim_zebra_vxlan_replay();
452 static void pim_zebra_capabilities(struct zclient_capabilities
*cap
)
454 router
->mlag_role
= cap
->role
;
455 router
->multipath
= cap
->ecmp
;
458 static zclient_handler
*const pim_handlers
[] = {
459 [ZEBRA_INTERFACE_ADDRESS_ADD
] = pim_zebra_if_address_add
,
460 [ZEBRA_INTERFACE_ADDRESS_DELETE
] = pim_zebra_if_address_del
,
462 [ZEBRA_NEXTHOP_UPDATE
] = pim_parse_nexthop_update
,
463 [ZEBRA_ROUTER_ID_UPDATE
] = pim_router_id_update_zebra
,
464 [ZEBRA_INTERFACE_VRF_UPDATE
] = pim_zebra_interface_vrf_update
,
467 [ZEBRA_VXLAN_SG_ADD
] = pim_zebra_vxlan_sg_proc
,
468 [ZEBRA_VXLAN_SG_DEL
] = pim_zebra_vxlan_sg_proc
,
470 [ZEBRA_MLAG_PROCESS_UP
] = pim_zebra_mlag_process_up
,
471 [ZEBRA_MLAG_PROCESS_DOWN
] = pim_zebra_mlag_process_down
,
472 [ZEBRA_MLAG_FORWARD_MSG
] = pim_zebra_mlag_handle_msg
,
476 void pim_zebra_init(void)
478 /* Socket for receiving updates from Zebra daemon */
479 zclient
= zclient_new(router
->master
, &zclient_options_default
,
480 pim_handlers
, array_size(pim_handlers
));
482 zclient
->zebra_capabilities
= pim_zebra_capabilities
;
483 zclient
->zebra_connected
= pim_zebra_connected
;
485 zclient_init(zclient
, ZEBRA_ROUTE_PIM
, 0, &pimd_privs
);
486 if (PIM_DEBUG_PIM_TRACE
) {
487 zlog_notice("%s: zclient socket initialized", __func__
);
490 zclient_lookup_new();
493 void pim_forward_start(struct pim_ifchannel
*ch
)
495 struct pim_upstream
*up
= ch
->upstream
;
498 if (PIM_DEBUG_PIM_TRACE
)
499 zlog_debug("%s: (S,G)=%pSG oif=%s (%pPA)", __func__
, &ch
->sg
,
500 ch
->interface
->name
, &up
->upstream_addr
);
502 if (PIM_IF_FLAG_TEST_PROTO_IGMP(ch
->flags
))
503 mask
= PIM_OIF_FLAG_PROTO_GM
;
505 if (PIM_IF_FLAG_TEST_PROTO_PIM(ch
->flags
))
506 mask
|= PIM_OIF_FLAG_PROTO_PIM
;
508 pim_channel_add_oif(up
->channel_oil
, ch
->interface
,
512 void pim_forward_stop(struct pim_ifchannel
*ch
)
514 struct pim_upstream
*up
= ch
->upstream
;
516 if (PIM_DEBUG_PIM_TRACE
) {
517 zlog_debug("%s: (S,G)=%s oif=%s installed: %d",
518 __func__
, ch
->sg_str
, ch
->interface
->name
,
519 up
->channel_oil
->installed
);
523 * If a channel is being removed, check to see if we still need
524 * to inherit the interface. If so make sure it is added in
526 if (pim_upstream_evaluate_join_desired_interface(up
, ch
, ch
->parent
))
527 pim_channel_add_oif(up
->channel_oil
, ch
->interface
,
528 PIM_OIF_FLAG_PROTO_PIM
, __func__
);
530 pim_channel_del_oif(up
->channel_oil
, ch
->interface
,
531 PIM_OIF_FLAG_PROTO_PIM
, __func__
);
534 void pim_zebra_zclient_update(struct vty
*vty
)
536 vty_out(vty
, "Zclient update socket: ");
539 vty_out(vty
, "%d failures=%d\n", zclient
->sock
, zclient
->fail
);
541 vty_out(vty
, "<null zclient>\n");
545 struct zclient
*pim_zebra_zclient_get(void)
553 void pim_zebra_interface_set_master(struct interface
*vrf
,
554 struct interface
*ifp
)
556 zclient_interface_set_master(zclient
, vrf
, ifp
);