]> git.proxmox.com Git - mirror_frr.git/blame - pimd/pim_zebra.c
Merge pull request #12798 from donaldsharp/rib_match_multicast
[mirror_frr.git] / pimd / pim_zebra.c
CommitLineData
acddc0ed 1// SPDX-License-Identifier: GPL-2.0-or-later
12e41d03 2/*
896014f4
DL
3 * PIM for Quagga
4 * Copyright (C) 2008 Everton da Silva Marques
896014f4 5 */
12e41d03
DL
6
7#include <zebra.h>
8
12e41d03
DL
9#include "if.h"
10#include "log.h"
11#include "prefix.h"
12#include "zclient.h"
13#include "stream.h"
14#include "network.h"
dfe43e25
DW
15#include "vty.h"
16#include "plist.h"
ba4eb1bc 17#include "lib/bfd.h"
12e41d03
DL
18
19#include "pimd.h"
20#include "pim_pim.h"
21#include "pim_zebra.h"
22#include "pim_iface.h"
23#include "pim_str.h"
24#include "pim_oil.h"
25#include "pim_rpf.h"
26#include "pim_time.h"
27#include "pim_join.h"
28#include "pim_zlookup.h"
29#include "pim_ifchannel.h"
8f5f5e91 30#include "pim_rp.h"
2560106c 31#include "pim_igmpv3.h"
982bff89 32#include "pim_jp_agg.h"
1bc98276 33#include "pim_nht.h"
15a5dafe 34#include "pim_ssm.h"
af7b561b 35#include "pim_vxlan.h"
46c2687c 36#include "pim_mlag.h"
12e41d03
DL
37
38#undef PIM_DEBUG_IFADDR_DUMP
39#define PIM_DEBUG_IFADDR_DUMP
40
36b5b98f 41struct zclient *zclient;
38f4935a 42
12e41d03 43
12e41d03 44/* Router-id update message from zebra. */
121f9dee 45static int pim_router_id_update_zebra(ZAPI_CALLBACK_ARGS)
12e41d03 46{
d62a17ae 47 struct prefix router_id;
12e41d03 48
d62a17ae 49 zebra_router_id_update_read(zclient->ibuf, &router_id);
12e41d03 50
d62a17ae 51 return 0;
12e41d03
DL
52}
53
121f9dee 54static int pim_zebra_interface_vrf_update(ZAPI_CALLBACK_ARGS)
ee568318
DS
55{
56 struct interface *ifp;
57 vrf_id_t new_vrf_id;
58
59 ifp = zebra_interface_vrf_update_read(zclient->ibuf, vrf_id,
60 &new_vrf_id);
61 if (!ifp)
62 return 0;
63
64 if (PIM_DEBUG_ZEBRA)
15569c58
DA
65 zlog_debug("%s: %s updating from %u to %u", __func__, ifp->name,
66 vrf_id, new_vrf_id);
ee568318 67
a36898e7 68 if_update_to_new_vrf(ifp, new_vrf_id);
ee568318
DS
69
70 return 0;
71}
72
12e41d03
DL
73#ifdef PIM_DEBUG_IFADDR_DUMP
74static void dump_if_address(struct interface *ifp)
75{
d62a17ae 76 struct connected *ifc;
77 struct listnode *node;
78
5e81f5dd
DS
79 zlog_debug("%s %s: interface %s addresses:", __FILE__, __func__,
80 ifp->name);
d62a17ae 81
82 for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) {
83 struct prefix *p = ifc->address;
84
85 if (p->family != AF_INET)
86 continue;
87
ee2bbf7c
MS
88 zlog_debug("%s %s: interface %s address %pI4 %s", __FILE__,
89 __func__, ifp->name, &p->u.prefix4,
d62a17ae 90 CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY)
91 ? "secondary"
92 : "primary");
93 }
12e41d03
DL
94}
95#endif
96
121f9dee 97static int pim_zebra_if_address_add(ZAPI_CALLBACK_ARGS)
12e41d03 98{
d62a17ae 99 struct connected *c;
100 struct prefix *p;
101 struct pim_interface *pim_ifp;
102
103 /*
104 zebra api notifies address adds/dels events by using the same call
105 interface_add_read below, see comments in lib/zclient.c
106
107 zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_ADD, ...)
108 will add address to interface list by calling
109 connected_add_by_prefix()
110 */
121f9dee 111 c = zebra_interface_address_read(cmd, zclient->ibuf, vrf_id);
d62a17ae 112 if (!c)
113 return 0;
114
115 pim_ifp = c->ifp->info;
116 p = c->address;
117
118 if (PIM_DEBUG_ZEBRA) {
2dbe669b
DA
119 zlog_debug("%s: %s(%u) connected IP address %pFX flags %u %s",
120 __func__, c->ifp->name, vrf_id, p, c->flags,
996c9314
LB
121 CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY)
122 ? "secondary"
123 : "primary");
d62a17ae 124
12e41d03 125#ifdef PIM_DEBUG_IFADDR_DUMP
d62a17ae 126 dump_if_address(c->ifp);
12e41d03 127#endif
d62a17ae 128 }
12e41d03 129
94120cb2 130#if PIM_IPV == 4
034db86b
DL
131 if (p->family != PIM_AF)
132 SET_FLAG(c->flags, ZEBRA_IFA_SECONDARY);
133 else if (!CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY)) {
134 /* trying to add primary address? */
135 pim_addr primary_addr = pim_find_primary_addr(c->ifp);
136 pim_addr addr = pim_addr_from_prefix(p);
137
138 if (pim_addr_cmp(primary_addr, addr)) {
2dbe669b 139 if (PIM_DEBUG_ZEBRA)
d62a17ae 140 zlog_warn(
2dbe669b
DA
141 "%s: %s : forcing secondary flag on %pFX",
142 __func__, c->ifp->name, p);
d62a17ae 143 SET_FLAG(c->flags, ZEBRA_IFA_SECONDARY);
144 }
145 }
97feb13f
DL
146#else /* PIM_IPV != 4 */
147 if (p->family != PIM_AF)
148 return 0;
149#endif
12e41d03 150
d62a17ae 151 pim_if_addr_add(c);
26bb1fd5 152 if (pim_ifp) {
94120cb2
DL
153 struct pim_instance *pim;
154
26bb1fd5 155 pim = pim_get_pim_instance(vrf_id);
e2067d59 156 if (!pim) {
157 if (PIM_DEBUG_ZEBRA)
158 zlog_debug("%s: Unable to find pim instance",
159 __func__);
160 return 0;
161 }
162
26bb1fd5
DS
163 pim_ifp->pim = pim;
164
d62a17ae 165 pim_rp_check_on_if_add(pim_ifp);
26bb1fd5 166 }
12e41d03 167
d62a17ae 168 if (if_is_loopback(c->ifp)) {
4bb0e8f0 169 struct vrf *vrf = vrf_lookup_by_id(vrf_id);
d62a17ae 170 struct interface *ifp;
d8424057 171
451fda4f 172 FOR_ALL_INTERFACES (vrf, ifp) {
d62a17ae 173 if (!if_is_loopback(ifp) && if_is_operative(ifp))
174 pim_if_addr_add_all(ifp);
175 }
176 }
d62a17ae 177 return 0;
12e41d03
DL
178}
179
121f9dee 180static int pim_zebra_if_address_del(ZAPI_CALLBACK_ARGS)
12e41d03 181{
d62a17ae 182 struct connected *c;
183 struct prefix *p;
fec883d9 184 struct vrf *vrf = vrf_lookup_by_id(vrf_id);
819f099b
DS
185
186 if (!vrf)
187 return 0;
d62a17ae 188
189 /*
190 zebra api notifies address adds/dels events by using the same call
191 interface_add_read below, see comments in lib/zclient.c
192
193 zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_DELETE, ...)
194 will remove address from interface list by calling
195 connected_delete_by_prefix()
196 */
121f9dee 197 c = zebra_interface_address_read(cmd, zclient->ibuf, vrf_id);
d62a17ae 198 if (!c)
199 return 0;
200
201 p = c->address;
6233f087 202
94120cb2
DL
203 if (PIM_DEBUG_ZEBRA) {
204 zlog_debug(
205 "%s: %s(%u) disconnected IP address %pFX flags %u %s",
206 __func__, c->ifp->name, vrf_id, p, c->flags,
207 CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY)
208 ? "secondary"
209 : "primary");
12e41d03 210#ifdef PIM_DEBUG_IFADDR_DUMP
94120cb2 211 dump_if_address(c->ifp);
12e41d03 212#endif
94120cb2 213 }
12e41d03 214
97feb13f 215 if (p->family == PIM_AF) {
94120cb2 216 struct pim_instance *pim;
12e41d03 217
94120cb2 218 pim = vrf->info;
d62a17ae 219 pim_if_addr_del(c, 0);
fec883d9
DS
220 pim_rp_setup(pim);
221 pim_i_am_rp_re_evaluate(pim);
d62a17ae 222 }
6233f087 223
721c0857 224 connected_free(&c);
d62a17ae 225 return 0;
12e41d03
DL
226}
227
74389231
DS
228void pim_zebra_update_all_interfaces(struct pim_instance *pim)
229{
230 struct interface *ifp;
231
232 FOR_ALL_INTERFACES (pim->vrf, ifp) {
233 struct pim_interface *pim_ifp = ifp->info;
234 struct pim_iface_upstream_switch *us;
235 struct listnode *node;
236
237 if (!pim_ifp)
238 continue;
239
240 for (ALL_LIST_ELEMENTS_RO(pim_ifp->upstream_switch_list, node,
241 us)) {
242 struct pim_rpf rpf;
243
244 rpf.source_nexthop.interface = ifp;
144035b7 245 rpf.rpf_addr = us->address;
74389231
DS
246 pim_joinprune_send(&rpf, us->us);
247 pim_jp_agg_clear_group(us->us);
248 }
249 }
250}
251
cc67ccf9
DS
252void pim_zebra_upstream_rpf_changed(struct pim_instance *pim,
253 struct pim_upstream *up,
254 struct pim_rpf *old)
255{
1250cb5d
SP
256 if (old->source_nexthop.interface) {
257 struct pim_neighbor *nbr;
cc67ccf9 258
144035b7 259 nbr = pim_neighbor_find(old->source_nexthop.interface,
260 old->rpf_addr);
1250cb5d 261 if (nbr)
c5cdf069 262 pim_jp_agg_remove_group(nbr->upstream_jp_agg, up, nbr);
cc67ccf9 263
cc67ccf9 264 /*
1250cb5d
SP
265 * We have detected a case where we might need
266 * to rescan the inherited o_list so do it.
cc67ccf9 267 */
1250cb5d
SP
268 if (up->channel_oil->oil_inherited_rescan) {
269 pim_upstream_inherited_olist_decide(pim, up);
270 up->channel_oil->oil_inherited_rescan = 0;
271 }
cc67ccf9 272
1250cb5d
SP
273 if (up->join_state == PIM_UPSTREAM_JOINED) {
274 /*
275 * If we come up real fast we can be here
276 * where the mroute has not been installed
277 * so install it.
278 */
279 if (!up->channel_oil->installed)
69e3538c 280 pim_upstream_mroute_add(up->channel_oil,
15569c58 281 __func__);
1250cb5d
SP
282
283 /*
284 * RFC 4601: 4.5.7. Sending (S,G)
285 * Join/Prune Messages
286 *
287 * Transitions from Joined State
288 *
289 * RPF'(S,G) changes not due to an Assert
290 *
291 * The upstream (S,G) state machine remains
292 * in Joined state. Send Join(S,G) to the new
293 * upstream neighbor, which is the new value
294 * of RPF'(S,G). Send Prune(S,G) to the old
295 * upstream neighbor, which is the old value
296 * of RPF'(S,G). Set the Join Timer (JT) to
297 * expire after t_periodic seconds.
298 */
299 pim_jp_agg_switch_interface(old, &up->rpf, up);
300
301 pim_upstream_join_timer_restart(up, old);
302 } /* up->join_state == PIM_UPSTREAM_JOINED */
303 }
304
305 else {
cc67ccf9 306 /*
1250cb5d
SP
307 * We have detected a case where we might need
308 * to rescan the inherited o_list so do it.
cc67ccf9 309 */
1250cb5d
SP
310 if (up->channel_oil->oil_inherited_rescan) {
311 pim_upstream_inherited_olist_decide(pim, up);
312 up->channel_oil->oil_inherited_rescan = 0;
313 }
cc67ccf9 314
db431af2
AK
315 if (up->join_state == PIM_UPSTREAM_JOINED)
316 pim_jp_agg_switch_interface(old, &up->rpf, up);
317
1250cb5d 318 if (!up->channel_oil->installed)
15569c58 319 pim_upstream_mroute_add(up->channel_oil, __func__);
1250cb5d 320 }
cc67ccf9 321
1250cb5d
SP
322 /* FIXME can join_desired actually be changed by pim_rpf_update()
323 * returning PIM_RPF_CHANGED ?
324 */
cc67ccf9
DS
325 pim_upstream_update_join_desired(pim, up);
326}
327
94120cb2 328__attribute__((unused))
121f9dee 329static int pim_zebra_vxlan_sg_proc(ZAPI_CALLBACK_ARGS)
af7b561b
AK
330{
331 struct stream *s;
332 struct pim_instance *pim;
6fff2cc6
DL
333 pim_sgaddr sg;
334 size_t prefixlen;
af7b561b
AK
335
336 pim = pim_get_pim_instance(vrf_id);
337 if (!pim)
338 return 0;
339
340 s = zclient->ibuf;
341
6fff2cc6 342 prefixlen = stream_getl(s);
c631920c
DL
343 stream_get(&sg.src, s, prefixlen);
344 stream_get(&sg.grp, s, prefixlen);
af7b561b 345
9bace5c2
DL
346 if (PIM_DEBUG_ZEBRA)
347 zlog_debug("%u:recv SG %s %pSG", vrf_id,
348 (cmd == ZEBRA_VXLAN_SG_ADD) ? "add" : "del", &sg);
af7b561b 349
121f9dee 350 if (cmd == ZEBRA_VXLAN_SG_ADD)
af7b561b
AK
351 pim_vxlan_sg_add(pim, &sg);
352 else
353 pim_vxlan_sg_del(pim, &sg);
354
355 return 0;
356}
357
94120cb2 358__attribute__((unused))
ecbbc3a7
AK
359static void pim_zebra_vxlan_replay(void)
360{
361 struct stream *s = NULL;
362
363 /* Check socket. */
364 if (!zclient || zclient->sock < 0)
365 return;
366
367 s = zclient->obuf;
368 stream_reset(s);
369
370 zclient_create_header(s, ZEBRA_VXLAN_SG_REPLAY, VRF_DEFAULT);
371 stream_putw_at(s, 0, stream_get_endp(s));
372
373 zclient_send_message(zclient);
374}
375
da11e325 376void pim_scan_oil(struct pim_instance *pim)
8a67a996 377{
d62a17ae 378 struct channel_oil *c_oil;
d62a17ae 379
bfc92019
DS
380 pim->scan_oil_last = pim_time_monotonic_sec();
381 ++pim->scan_oil_events;
d62a17ae 382
7315ecda 383 frr_each (rb_pim_oil, &pim->channel_oil_head, c_oil)
7984af18 384 pim_upstream_mroute_iif_update(c_oil, __func__);
12e41d03
DL
385}
386
cc9f21da 387static void on_rpf_cache_refresh(struct thread *t)
12e41d03 388{
da11e325
DS
389 struct pim_instance *pim = THREAD_ARG(t);
390
d62a17ae 391 /* update kernel multicast forwarding cache (MFC) */
da11e325 392 pim_scan_oil(pim);
12e41d03 393
bfc92019
DS
394 pim->rpf_cache_refresh_last = pim_time_monotonic_sec();
395 ++pim->rpf_cache_refresh_events;
12e41d03 396
d62a17ae 397 // It is called as part of pim_neighbor_add
398 // pim_rp_setup ();
12e41d03
DL
399}
400
da11e325 401void sched_rpf_cache_refresh(struct pim_instance *pim)
12e41d03 402{
bfc92019 403 ++pim->rpf_cache_refresh_requests;
12e41d03 404
bfc92019 405 pim_rpf_set_refresh_time(pim);
e71bf8f7 406
da11e325 407 if (pim->rpf_cache_refresher) {
d62a17ae 408 /* Refresh timer is already running */
409 return;
410 }
12e41d03 411
d62a17ae 412 /* Start refresh timer */
12e41d03 413
d62a17ae 414 if (PIM_DEBUG_ZEBRA) {
15569c58 415 zlog_debug("%s: triggering %ld msec timer", __func__,
da03883e 416 router->rpf_cache_refresh_delay_msec);
d62a17ae 417 }
12e41d03 418
36417fcc 419 thread_add_timer_msec(router->master, on_rpf_cache_refresh, pim,
da03883e 420 router->rpf_cache_refresh_delay_msec,
da11e325 421 &pim->rpf_cache_refresher);
12e41d03
DL
422}
423
d62a17ae 424static void pim_zebra_connected(struct zclient *zclient)
48e8451b 425{
94120cb2 426#if PIM_IPV == 4
d62a17ae 427 /* Send the client registration */
0945d5ed 428 bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER, router->vrf_id);
94120cb2 429#endif
ba4eb1bc 430
4dfe9ad2 431 zclient_send_reg_requests(zclient, router->vrf_id);
ecbbc3a7 432
94120cb2 433#if PIM_IPV == 4
ecbbc3a7
AK
434 /* request for VxLAN BUM group addresses */
435 pim_zebra_vxlan_replay();
94120cb2 436#endif
48e8451b 437}
8711a53d 438
ac567a6f
DS
439static void pim_zebra_capabilities(struct zclient_capabilities *cap)
440{
05ca004b 441 router->mlag_role = cap->role;
75700af6 442 router->multipath = cap->ecmp;
ac567a6f
DS
443}
444
a243d1db 445static zclient_handler *const pim_handlers[] = {
a243d1db
DL
446 [ZEBRA_INTERFACE_ADDRESS_ADD] = pim_zebra_if_address_add,
447 [ZEBRA_INTERFACE_ADDRESS_DELETE] = pim_zebra_if_address_del,
0455229c
DL
448
449 [ZEBRA_NEXTHOP_UPDATE] = pim_parse_nexthop_update,
94120cb2 450 [ZEBRA_ROUTER_ID_UPDATE] = pim_router_id_update_zebra,
a243d1db 451 [ZEBRA_INTERFACE_VRF_UPDATE] = pim_zebra_interface_vrf_update,
a243d1db 452
97feb13f 453#if PIM_IPV == 4
a243d1db
DL
454 [ZEBRA_VXLAN_SG_ADD] = pim_zebra_vxlan_sg_proc,
455 [ZEBRA_VXLAN_SG_DEL] = pim_zebra_vxlan_sg_proc,
456
457 [ZEBRA_MLAG_PROCESS_UP] = pim_zebra_mlag_process_up,
458 [ZEBRA_MLAG_PROCESS_DOWN] = pim_zebra_mlag_process_down,
459 [ZEBRA_MLAG_FORWARD_MSG] = pim_zebra_mlag_handle_msg,
94120cb2 460#endif
a243d1db
DL
461};
462
eb05883f 463void pim_zebra_init(void)
12e41d03 464{
d62a17ae 465 /* Socket for receiving updates from Zebra daemon */
a243d1db
DL
466 zclient = zclient_new(router->master, &zclient_options_default,
467 pim_handlers, array_size(pim_handlers));
d62a17ae 468
ac567a6f 469 zclient->zebra_capabilities = pim_zebra_capabilities;
d62a17ae 470 zclient->zebra_connected = pim_zebra_connected;
d62a17ae 471
342213ea 472 zclient_init(zclient, ZEBRA_ROUTE_PIM, 0, &pimd_privs);
d62a17ae 473 if (PIM_DEBUG_PIM_TRACE) {
15569c58 474 zlog_notice("%s: zclient socket initialized", __func__);
d62a17ae 475 }
476
477 zclient_lookup_new();
12e41d03
DL
478}
479
12e41d03
DL
480void pim_forward_start(struct pim_ifchannel *ch)
481{
d62a17ae 482 struct pim_upstream *up = ch->upstream;
9443810e 483 uint32_t mask = 0;
d62a17ae 484
8e8be741 485 if (PIM_DEBUG_PIM_TRACE)
41490e0e 486 zlog_debug("%s: (S,G)=%pSG oif=%s (%pPA)", __func__, &ch->sg,
8e8be741 487 ch->interface->name, &up->upstream_addr);
d62a17ae 488
9443810e 489 if (PIM_IF_FLAG_TEST_PROTO_IGMP(ch->flags))
80a82b56 490 mask = PIM_OIF_FLAG_PROTO_GM;
d62a17ae 491
9443810e
SP
492 if (PIM_IF_FLAG_TEST_PROTO_PIM(ch->flags))
493 mask |= PIM_OIF_FLAG_PROTO_PIM;
494
1b249e70
AK
495 pim_channel_add_oif(up->channel_oil, ch->interface,
496 mask, __func__);
12e41d03
DL
497}
498
86696f7b 499void pim_forward_stop(struct pim_ifchannel *ch)
12e41d03 500{
d62a17ae 501 struct pim_upstream *up = ch->upstream;
12e41d03 502
d62a17ae 503 if (PIM_DEBUG_PIM_TRACE) {
86696f7b 504 zlog_debug("%s: (S,G)=%s oif=%s installed: %d",
15569c58 505 __func__, ch->sg_str, ch->interface->name,
86696f7b 506 up->channel_oil->installed);
d62a17ae 507 }
12e41d03 508
2164ed5d
DS
509 /*
510 * If a channel is being removed, check to see if we still need
511 * to inherit the interface. If so make sure it is added in
512 */
513 if (pim_upstream_evaluate_join_desired_interface(up, ch, ch->parent))
514 pim_channel_add_oif(up->channel_oil, ch->interface,
1b249e70 515 PIM_OIF_FLAG_PROTO_PIM, __func__);
2164ed5d
DS
516 else
517 pim_channel_del_oif(up->channel_oil, ch->interface,
1b249e70 518 PIM_OIF_FLAG_PROTO_PIM, __func__);
12e41d03 519}
8799b66b 520
d62a17ae 521void pim_zebra_zclient_update(struct vty *vty)
8799b66b 522{
d62a17ae 523 vty_out(vty, "Zclient update socket: ");
524
525 if (zclient) {
526 vty_out(vty, "%d failures=%d\n", zclient->sock, zclient->fail);
527 } else {
528 vty_out(vty, "<null zclient>\n");
529 }
8799b66b 530}
1bc98276 531
d62a17ae 532struct zclient *pim_zebra_zclient_get(void)
1bc98276 533{
d62a17ae 534 if (zclient)
535 return zclient;
536 else
537 return NULL;
1bc98276 538}
ddbf3e60
DS
539
540void pim_zebra_interface_set_master(struct interface *vrf,
541 struct interface *ifp)
542{
543 zclient_interface_set_master(zclient, vrf, ifp);
544}