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
);
74 if_update_to_new_vrf(ifp
, new_vrf_id
);
80 pim_ifp
->pim
->mcast_if_count
--;
82 pim_ifp
->pim
->mcast_if_count
++;
87 #ifdef PIM_DEBUG_IFADDR_DUMP
88 static void dump_if_address(struct interface
*ifp
)
90 struct connected
*ifc
;
91 struct listnode
*node
;
93 zlog_debug("%s %s: interface %s addresses:", __FILE__
, __func__
,
96 for (ALL_LIST_ELEMENTS_RO(ifp
->connected
, node
, ifc
)) {
97 struct prefix
*p
= ifc
->address
;
99 if (p
->family
!= AF_INET
)
102 zlog_debug("%s %s: interface %s address %pI4 %s", __FILE__
,
103 __func__
, ifp
->name
, &p
->u
.prefix4
,
104 CHECK_FLAG(ifc
->flags
, ZEBRA_IFA_SECONDARY
)
111 static int pim_zebra_if_address_add(ZAPI_CALLBACK_ARGS
)
115 struct pim_interface
*pim_ifp
;
118 zebra api notifies address adds/dels events by using the same call
119 interface_add_read below, see comments in lib/zclient.c
121 zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_ADD, ...)
122 will add address to interface list by calling
123 connected_add_by_prefix()
125 c
= zebra_interface_address_read(cmd
, zclient
->ibuf
, vrf_id
);
129 pim_ifp
= c
->ifp
->info
;
132 if (PIM_DEBUG_ZEBRA
) {
133 zlog_debug("%s: %s(%u) connected IP address %pFX flags %u %s",
134 __func__
, c
->ifp
->name
, vrf_id
, p
, c
->flags
,
135 CHECK_FLAG(c
->flags
, ZEBRA_IFA_SECONDARY
)
139 #ifdef PIM_DEBUG_IFADDR_DUMP
140 dump_if_address(c
->ifp
);
145 if (p
->family
!= PIM_AF
)
146 SET_FLAG(c
->flags
, ZEBRA_IFA_SECONDARY
);
147 else if (!CHECK_FLAG(c
->flags
, ZEBRA_IFA_SECONDARY
)) {
148 /* trying to add primary address? */
149 pim_addr primary_addr
= pim_find_primary_addr(c
->ifp
);
150 pim_addr addr
= pim_addr_from_prefix(p
);
152 if (pim_addr_cmp(primary_addr
, addr
)) {
155 "%s: %s : forcing secondary flag on %pFX",
156 __func__
, c
->ifp
->name
, p
);
157 SET_FLAG(c
->flags
, ZEBRA_IFA_SECONDARY
);
160 #else /* PIM_IPV != 4 */
161 if (p
->family
!= PIM_AF
)
167 struct pim_instance
*pim
;
169 pim
= pim_get_pim_instance(vrf_id
);
172 zlog_debug("%s: Unable to find pim instance",
179 pim_rp_check_on_if_add(pim_ifp
);
182 if (if_is_loopback(c
->ifp
)) {
183 struct vrf
*vrf
= vrf_lookup_by_id(vrf_id
);
184 struct interface
*ifp
;
186 FOR_ALL_INTERFACES (vrf
, ifp
) {
187 if (!if_is_loopback(ifp
) && if_is_operative(ifp
))
188 pim_if_addr_add_all(ifp
);
194 static int pim_zebra_if_address_del(ZAPI_CALLBACK_ARGS
)
198 struct vrf
*vrf
= vrf_lookup_by_id(vrf_id
);
204 zebra api notifies address adds/dels events by using the same call
205 interface_add_read below, see comments in lib/zclient.c
207 zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_DELETE, ...)
208 will remove address from interface list by calling
209 connected_delete_by_prefix()
211 c
= zebra_interface_address_read(cmd
, zclient
->ibuf
, vrf_id
);
217 if (PIM_DEBUG_ZEBRA
) {
219 "%s: %s(%u) disconnected IP address %pFX flags %u %s",
220 __func__
, c
->ifp
->name
, vrf_id
, p
, c
->flags
,
221 CHECK_FLAG(c
->flags
, ZEBRA_IFA_SECONDARY
)
224 #ifdef PIM_DEBUG_IFADDR_DUMP
225 dump_if_address(c
->ifp
);
229 if (p
->family
== PIM_AF
) {
230 struct pim_instance
*pim
;
233 pim_if_addr_del(c
, 0);
235 pim_i_am_rp_re_evaluate(pim
);
242 void pim_zebra_update_all_interfaces(struct pim_instance
*pim
)
244 struct interface
*ifp
;
246 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
247 struct pim_interface
*pim_ifp
= ifp
->info
;
248 struct pim_iface_upstream_switch
*us
;
249 struct listnode
*node
;
254 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->upstream_switch_list
, node
,
258 rpf
.source_nexthop
.interface
= ifp
;
259 rpf
.rpf_addr
= us
->address
;
260 pim_joinprune_send(&rpf
, us
->us
);
261 pim_jp_agg_clear_group(us
->us
);
266 void pim_zebra_upstream_rpf_changed(struct pim_instance
*pim
,
267 struct pim_upstream
*up
,
270 if (old
->source_nexthop
.interface
) {
271 struct pim_neighbor
*nbr
;
273 nbr
= pim_neighbor_find(old
->source_nexthop
.interface
,
274 old
->rpf_addr
, true);
277 pim_jp_agg_remove_group(nbr
->upstream_jp_agg
, up
, nbr
);
280 * We have detected a case where we might need
281 * to rescan the inherited o_list so do it.
283 if (up
->channel_oil
->oil_inherited_rescan
) {
284 pim_upstream_inherited_olist_decide(pim
, up
);
285 up
->channel_oil
->oil_inherited_rescan
= 0;
288 if (up
->join_state
== PIM_UPSTREAM_JOINED
) {
290 * If we come up real fast we can be here
291 * where the mroute has not been installed
294 if (!up
->channel_oil
->installed
)
295 pim_upstream_mroute_add(up
->channel_oil
,
299 * RFC 4601: 4.5.7. Sending (S,G)
300 * Join/Prune Messages
302 * Transitions from Joined State
304 * RPF'(S,G) changes not due to an Assert
306 * The upstream (S,G) state machine remains
307 * in Joined state. Send Join(S,G) to the new
308 * upstream neighbor, which is the new value
309 * of RPF'(S,G). Send Prune(S,G) to the old
310 * upstream neighbor, which is the old value
311 * of RPF'(S,G). Set the Join Timer (JT) to
312 * expire after t_periodic seconds.
314 pim_jp_agg_switch_interface(old
, &up
->rpf
, up
);
316 pim_upstream_join_timer_restart(up
, old
);
317 } /* up->join_state == PIM_UPSTREAM_JOINED */
322 * We have detected a case where we might need
323 * to rescan the inherited o_list so do it.
325 if (up
->channel_oil
->oil_inherited_rescan
) {
326 pim_upstream_inherited_olist_decide(pim
, up
);
327 up
->channel_oil
->oil_inherited_rescan
= 0;
330 if (up
->join_state
== PIM_UPSTREAM_JOINED
)
331 pim_jp_agg_switch_interface(old
, &up
->rpf
, up
);
333 if (!up
->channel_oil
->installed
)
334 pim_upstream_mroute_add(up
->channel_oil
, __func__
);
337 /* FIXME can join_desired actually be changed by pim_rpf_update()
338 * returning PIM_RPF_CHANGED ?
340 pim_upstream_update_join_desired(pim
, up
);
343 __attribute__((unused
))
344 static int pim_zebra_vxlan_sg_proc(ZAPI_CALLBACK_ARGS
)
347 struct pim_instance
*pim
;
351 pim
= pim_get_pim_instance(vrf_id
);
357 prefixlen
= stream_getl(s
);
358 stream_get(&sg
.src
, s
, prefixlen
);
359 stream_get(&sg
.grp
, s
, prefixlen
);
362 zlog_debug("%u:recv SG %s %pSG", vrf_id
,
363 (cmd
== ZEBRA_VXLAN_SG_ADD
) ? "add" : "del", &sg
);
365 if (cmd
== ZEBRA_VXLAN_SG_ADD
)
366 pim_vxlan_sg_add(pim
, &sg
);
368 pim_vxlan_sg_del(pim
, &sg
);
373 __attribute__((unused
))
374 static void pim_zebra_vxlan_replay(void)
376 struct stream
*s
= NULL
;
379 if (!zclient
|| zclient
->sock
< 0)
385 zclient_create_header(s
, ZEBRA_VXLAN_SG_REPLAY
, VRF_DEFAULT
);
386 stream_putw_at(s
, 0, stream_get_endp(s
));
388 zclient_send_message(zclient
);
391 void pim_scan_oil(struct pim_instance
*pim
)
393 struct channel_oil
*c_oil
;
395 pim
->scan_oil_last
= pim_time_monotonic_sec();
396 ++pim
->scan_oil_events
;
398 frr_each (rb_pim_oil
, &pim
->channel_oil_head
, c_oil
)
399 pim_upstream_mroute_iif_update(c_oil
, __func__
);
402 static void on_rpf_cache_refresh(struct event
*t
)
404 struct pim_instance
*pim
= EVENT_ARG(t
);
406 /* update kernel multicast forwarding cache (MFC) */
409 pim
->rpf_cache_refresh_last
= pim_time_monotonic_sec();
410 ++pim
->rpf_cache_refresh_events
;
412 // It is called as part of pim_neighbor_add
416 void sched_rpf_cache_refresh(struct pim_instance
*pim
)
418 ++pim
->rpf_cache_refresh_requests
;
420 pim_rpf_set_refresh_time(pim
);
422 if (pim
->rpf_cache_refresher
) {
423 /* Refresh timer is already running */
427 /* Start refresh timer */
429 if (PIM_DEBUG_ZEBRA
) {
430 zlog_debug("%s: triggering %ld msec timer", __func__
,
431 router
->rpf_cache_refresh_delay_msec
);
434 event_add_timer_msec(router
->master
, on_rpf_cache_refresh
, pim
,
435 router
->rpf_cache_refresh_delay_msec
,
436 &pim
->rpf_cache_refresher
);
439 static void pim_zebra_connected(struct zclient
*zclient
)
442 /* Send the client registration */
443 bfd_client_sendmsg(zclient
, ZEBRA_BFD_CLIENT_REGISTER
, router
->vrf_id
);
446 zclient_send_reg_requests(zclient
, router
->vrf_id
);
449 /* request for VxLAN BUM group addresses */
450 pim_zebra_vxlan_replay();
454 static void pim_zebra_capabilities(struct zclient_capabilities
*cap
)
456 router
->mlag_role
= cap
->role
;
457 router
->multipath
= cap
->ecmp
;
460 static zclient_handler
*const pim_handlers
[] = {
461 [ZEBRA_INTERFACE_ADDRESS_ADD
] = pim_zebra_if_address_add
,
462 [ZEBRA_INTERFACE_ADDRESS_DELETE
] = pim_zebra_if_address_del
,
464 [ZEBRA_NEXTHOP_UPDATE
] = pim_parse_nexthop_update
,
465 [ZEBRA_ROUTER_ID_UPDATE
] = pim_router_id_update_zebra
,
466 [ZEBRA_INTERFACE_VRF_UPDATE
] = pim_zebra_interface_vrf_update
,
469 [ZEBRA_VXLAN_SG_ADD
] = pim_zebra_vxlan_sg_proc
,
470 [ZEBRA_VXLAN_SG_DEL
] = pim_zebra_vxlan_sg_proc
,
472 [ZEBRA_MLAG_PROCESS_UP
] = pim_zebra_mlag_process_up
,
473 [ZEBRA_MLAG_PROCESS_DOWN
] = pim_zebra_mlag_process_down
,
474 [ZEBRA_MLAG_FORWARD_MSG
] = pim_zebra_mlag_handle_msg
,
478 void pim_zebra_init(void)
480 /* Socket for receiving updates from Zebra daemon */
481 zclient
= zclient_new(router
->master
, &zclient_options_default
,
482 pim_handlers
, array_size(pim_handlers
));
484 zclient
->zebra_capabilities
= pim_zebra_capabilities
;
485 zclient
->zebra_connected
= pim_zebra_connected
;
487 zclient_init(zclient
, ZEBRA_ROUTE_PIM
, 0, &pimd_privs
);
488 if (PIM_DEBUG_PIM_TRACE
) {
489 zlog_notice("%s: zclient socket initialized", __func__
);
492 zclient_lookup_new();
495 void pim_forward_start(struct pim_ifchannel
*ch
)
497 struct pim_upstream
*up
= ch
->upstream
;
500 if (PIM_DEBUG_PIM_TRACE
)
501 zlog_debug("%s: (S,G)=%pSG oif=%s (%pPA)", __func__
, &ch
->sg
,
502 ch
->interface
->name
, &up
->upstream_addr
);
504 if (PIM_IF_FLAG_TEST_PROTO_IGMP(ch
->flags
))
505 mask
= PIM_OIF_FLAG_PROTO_GM
;
507 if (PIM_IF_FLAG_TEST_PROTO_PIM(ch
->flags
))
508 mask
|= PIM_OIF_FLAG_PROTO_PIM
;
510 pim_channel_add_oif(up
->channel_oil
, ch
->interface
,
514 void pim_forward_stop(struct pim_ifchannel
*ch
)
516 struct pim_upstream
*up
= ch
->upstream
;
518 if (PIM_DEBUG_PIM_TRACE
) {
519 zlog_debug("%s: (S,G)=%s oif=%s installed: %d",
520 __func__
, ch
->sg_str
, ch
->interface
->name
,
521 up
->channel_oil
->installed
);
525 * If a channel is being removed, check to see if we still need
526 * to inherit the interface. If so make sure it is added in
528 if (pim_upstream_evaluate_join_desired_interface(up
, ch
, ch
->parent
))
529 pim_channel_add_oif(up
->channel_oil
, ch
->interface
,
530 PIM_OIF_FLAG_PROTO_PIM
, __func__
);
532 pim_channel_del_oif(up
->channel_oil
, ch
->interface
,
533 PIM_OIF_FLAG_PROTO_PIM
, __func__
);
536 void pim_zebra_zclient_update(struct vty
*vty
)
538 vty_out(vty
, "Zclient update socket: ");
541 vty_out(vty
, "%d failures=%d\n", zclient
->sock
, zclient
->fail
);
543 vty_out(vty
, "<null zclient>\n");
547 struct zclient
*pim_zebra_zclient_get(void)
555 void pim_zebra_interface_set_master(struct interface
*vrf
,
556 struct interface
*ifp
)
558 zclient_interface_set_master(zclient
, vrf
, ifp
);