]> git.proxmox.com Git - mirror_frr.git/blob - pimd/pim_zebra.c
97b68c0a327a353a8ded004e1290cc23884c5cc8
[mirror_frr.git] / pimd / pim_zebra.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * PIM for Quagga
4 * Copyright (C) 2008 Everton da Silva Marques
5 */
6
7 #include <zebra.h>
8
9 #include "if.h"
10 #include "log.h"
11 #include "prefix.h"
12 #include "zclient.h"
13 #include "stream.h"
14 #include "network.h"
15 #include "vty.h"
16 #include "plist.h"
17 #include "lib/bfd.h"
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"
30 #include "pim_rp.h"
31 #include "pim_igmpv3.h"
32 #include "pim_jp_agg.h"
33 #include "pim_nht.h"
34 #include "pim_ssm.h"
35 #include "pim_vxlan.h"
36 #include "pim_mlag.h"
37
38 #undef PIM_DEBUG_IFADDR_DUMP
39 #define PIM_DEBUG_IFADDR_DUMP
40
41 struct zclient *zclient;
42
43
44 /* Router-id update message from zebra. */
45 static int pim_router_id_update_zebra(ZAPI_CALLBACK_ARGS)
46 {
47 struct prefix router_id;
48
49 zebra_router_id_update_read(zclient->ibuf, &router_id);
50
51 return 0;
52 }
53
54 static int pim_zebra_interface_vrf_update(ZAPI_CALLBACK_ARGS)
55 {
56 struct interface *ifp;
57 vrf_id_t new_vrf_id;
58 struct pim_instance *pim;
59 struct pim_interface *pim_ifp;
60
61 ifp = zebra_interface_vrf_update_read(zclient->ibuf, vrf_id,
62 &new_vrf_id);
63 if (!ifp)
64 return 0;
65
66 if (PIM_DEBUG_ZEBRA)
67 zlog_debug("%s: %s updating from %u to %u", __func__, ifp->name,
68 vrf_id, new_vrf_id);
69
70 pim = pim_get_pim_instance(new_vrf_id);
71
72 if_update_to_new_vrf(ifp, new_vrf_id);
73
74 pim_ifp = ifp->info;
75 if (!pim_ifp)
76 return 0;
77
78 pim_ifp->pim->mcast_if_count--;
79 pim_ifp->pim = pim;
80 pim_ifp->pim->mcast_if_count++;
81
82 return 0;
83 }
84
85 #ifdef PIM_DEBUG_IFADDR_DUMP
86 static void dump_if_address(struct interface *ifp)
87 {
88 struct connected *ifc;
89 struct listnode *node;
90
91 zlog_debug("%s %s: interface %s addresses:", __FILE__, __func__,
92 ifp->name);
93
94 for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) {
95 struct prefix *p = ifc->address;
96
97 if (p->family != AF_INET)
98 continue;
99
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)
103 ? "secondary"
104 : "primary");
105 }
106 }
107 #endif
108
109 static int pim_zebra_if_address_add(ZAPI_CALLBACK_ARGS)
110 {
111 struct connected *c;
112 struct prefix *p;
113 struct pim_interface *pim_ifp;
114
115 /*
116 zebra api notifies address adds/dels events by using the same call
117 interface_add_read below, see comments in lib/zclient.c
118
119 zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_ADD, ...)
120 will add address to interface list by calling
121 connected_add_by_prefix()
122 */
123 c = zebra_interface_address_read(cmd, zclient->ibuf, vrf_id);
124 if (!c)
125 return 0;
126
127 pim_ifp = c->ifp->info;
128 p = c->address;
129
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)
134 ? "secondary"
135 : "primary");
136
137 #ifdef PIM_DEBUG_IFADDR_DUMP
138 dump_if_address(c->ifp);
139 #endif
140 }
141
142 #if PIM_IPV == 4
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);
149
150 if (pim_addr_cmp(primary_addr, addr)) {
151 if (PIM_DEBUG_ZEBRA)
152 zlog_warn(
153 "%s: %s : forcing secondary flag on %pFX",
154 __func__, c->ifp->name, p);
155 SET_FLAG(c->flags, ZEBRA_IFA_SECONDARY);
156 }
157 }
158 #else /* PIM_IPV != 4 */
159 if (p->family != PIM_AF)
160 return 0;
161 #endif
162
163 pim_if_addr_add(c);
164 if (pim_ifp) {
165 struct pim_instance *pim;
166
167 pim = pim_get_pim_instance(vrf_id);
168 if (!pim) {
169 if (PIM_DEBUG_ZEBRA)
170 zlog_debug("%s: Unable to find pim instance",
171 __func__);
172 return 0;
173 }
174
175 pim_ifp->pim = pim;
176
177 pim_rp_check_on_if_add(pim_ifp);
178 }
179
180 if (if_is_loopback(c->ifp)) {
181 struct vrf *vrf = vrf_lookup_by_id(vrf_id);
182 struct interface *ifp;
183
184 FOR_ALL_INTERFACES (vrf, ifp) {
185 if (!if_is_loopback(ifp) && if_is_operative(ifp))
186 pim_if_addr_add_all(ifp);
187 }
188 }
189 return 0;
190 }
191
192 static int pim_zebra_if_address_del(ZAPI_CALLBACK_ARGS)
193 {
194 struct connected *c;
195 struct prefix *p;
196 struct vrf *vrf = vrf_lookup_by_id(vrf_id);
197
198 if (!vrf)
199 return 0;
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 */
209 c = zebra_interface_address_read(cmd, zclient->ibuf, vrf_id);
210 if (!c)
211 return 0;
212
213 p = c->address;
214
215 if (PIM_DEBUG_ZEBRA) {
216 zlog_debug(
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)
220 ? "secondary"
221 : "primary");
222 #ifdef PIM_DEBUG_IFADDR_DUMP
223 dump_if_address(c->ifp);
224 #endif
225 }
226
227 if (p->family == PIM_AF) {
228 struct pim_instance *pim;
229
230 pim = vrf->info;
231 pim_if_addr_del(c, 0);
232 pim_rp_setup(pim);
233 pim_i_am_rp_re_evaluate(pim);
234 }
235
236 connected_free(&c);
237 return 0;
238 }
239
240 void 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 = us->address;
258 pim_joinprune_send(&rpf, us->us);
259 pim_jp_agg_clear_group(us->us);
260 }
261 }
262 }
263
264 void pim_zebra_upstream_rpf_changed(struct pim_instance *pim,
265 struct pim_upstream *up,
266 struct pim_rpf *old)
267 {
268 if (old->source_nexthop.interface) {
269 struct pim_neighbor *nbr;
270
271 nbr = pim_neighbor_find(old->source_nexthop.interface,
272 old->rpf_addr, true);
273
274 if (nbr)
275 pim_jp_agg_remove_group(nbr->upstream_jp_agg, up, nbr);
276
277 /*
278 * We have detected a case where we might need
279 * to rescan the inherited o_list so do it.
280 */
281 if (up->channel_oil->oil_inherited_rescan) {
282 pim_upstream_inherited_olist_decide(pim, up);
283 up->channel_oil->oil_inherited_rescan = 0;
284 }
285
286 if (up->join_state == PIM_UPSTREAM_JOINED) {
287 /*
288 * If we come up real fast we can be here
289 * where the mroute has not been installed
290 * so install it.
291 */
292 if (!up->channel_oil->installed)
293 pim_upstream_mroute_add(up->channel_oil,
294 __func__);
295
296 /*
297 * RFC 4601: 4.5.7. Sending (S,G)
298 * Join/Prune Messages
299 *
300 * Transitions from Joined State
301 *
302 * RPF'(S,G) changes not due to an Assert
303 *
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.
311 */
312 pim_jp_agg_switch_interface(old, &up->rpf, up);
313
314 pim_upstream_join_timer_restart(up, old);
315 } /* up->join_state == PIM_UPSTREAM_JOINED */
316 }
317
318 else {
319 /*
320 * We have detected a case where we might need
321 * to rescan the inherited o_list so do it.
322 */
323 if (up->channel_oil->oil_inherited_rescan) {
324 pim_upstream_inherited_olist_decide(pim, up);
325 up->channel_oil->oil_inherited_rescan = 0;
326 }
327
328 if (up->join_state == PIM_UPSTREAM_JOINED)
329 pim_jp_agg_switch_interface(old, &up->rpf, up);
330
331 if (!up->channel_oil->installed)
332 pim_upstream_mroute_add(up->channel_oil, __func__);
333 }
334
335 /* FIXME can join_desired actually be changed by pim_rpf_update()
336 * returning PIM_RPF_CHANGED ?
337 */
338 pim_upstream_update_join_desired(pim, up);
339 }
340
341 __attribute__((unused))
342 static int pim_zebra_vxlan_sg_proc(ZAPI_CALLBACK_ARGS)
343 {
344 struct stream *s;
345 struct pim_instance *pim;
346 pim_sgaddr sg;
347 size_t prefixlen;
348
349 pim = pim_get_pim_instance(vrf_id);
350 if (!pim)
351 return 0;
352
353 s = zclient->ibuf;
354
355 prefixlen = stream_getl(s);
356 stream_get(&sg.src, s, prefixlen);
357 stream_get(&sg.grp, s, prefixlen);
358
359 if (PIM_DEBUG_ZEBRA)
360 zlog_debug("%u:recv SG %s %pSG", vrf_id,
361 (cmd == ZEBRA_VXLAN_SG_ADD) ? "add" : "del", &sg);
362
363 if (cmd == ZEBRA_VXLAN_SG_ADD)
364 pim_vxlan_sg_add(pim, &sg);
365 else
366 pim_vxlan_sg_del(pim, &sg);
367
368 return 0;
369 }
370
371 __attribute__((unused))
372 static void pim_zebra_vxlan_replay(void)
373 {
374 struct stream *s = NULL;
375
376 /* Check socket. */
377 if (!zclient || zclient->sock < 0)
378 return;
379
380 s = zclient->obuf;
381 stream_reset(s);
382
383 zclient_create_header(s, ZEBRA_VXLAN_SG_REPLAY, VRF_DEFAULT);
384 stream_putw_at(s, 0, stream_get_endp(s));
385
386 zclient_send_message(zclient);
387 }
388
389 void pim_scan_oil(struct pim_instance *pim)
390 {
391 struct channel_oil *c_oil;
392
393 pim->scan_oil_last = pim_time_monotonic_sec();
394 ++pim->scan_oil_events;
395
396 frr_each (rb_pim_oil, &pim->channel_oil_head, c_oil)
397 pim_upstream_mroute_iif_update(c_oil, __func__);
398 }
399
400 static void on_rpf_cache_refresh(struct event *t)
401 {
402 struct pim_instance *pim = EVENT_ARG(t);
403
404 /* update kernel multicast forwarding cache (MFC) */
405 pim_scan_oil(pim);
406
407 pim->rpf_cache_refresh_last = pim_time_monotonic_sec();
408 ++pim->rpf_cache_refresh_events;
409
410 // It is called as part of pim_neighbor_add
411 // pim_rp_setup ();
412 }
413
414 void sched_rpf_cache_refresh(struct pim_instance *pim)
415 {
416 ++pim->rpf_cache_refresh_requests;
417
418 pim_rpf_set_refresh_time(pim);
419
420 if (pim->rpf_cache_refresher) {
421 /* Refresh timer is already running */
422 return;
423 }
424
425 /* Start refresh timer */
426
427 if (PIM_DEBUG_ZEBRA) {
428 zlog_debug("%s: triggering %ld msec timer", __func__,
429 router->rpf_cache_refresh_delay_msec);
430 }
431
432 event_add_timer_msec(router->master, on_rpf_cache_refresh, pim,
433 router->rpf_cache_refresh_delay_msec,
434 &pim->rpf_cache_refresher);
435 }
436
437 static void pim_zebra_connected(struct zclient *zclient)
438 {
439 #if PIM_IPV == 4
440 /* Send the client registration */
441 bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER, router->vrf_id);
442 #endif
443
444 zclient_send_reg_requests(zclient, router->vrf_id);
445
446 #if PIM_IPV == 4
447 /* request for VxLAN BUM group addresses */
448 pim_zebra_vxlan_replay();
449 #endif
450 }
451
452 static void pim_zebra_capabilities(struct zclient_capabilities *cap)
453 {
454 router->mlag_role = cap->role;
455 router->multipath = cap->ecmp;
456 }
457
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,
461
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,
465
466 #if PIM_IPV == 4
467 [ZEBRA_VXLAN_SG_ADD] = pim_zebra_vxlan_sg_proc,
468 [ZEBRA_VXLAN_SG_DEL] = pim_zebra_vxlan_sg_proc,
469
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,
473 #endif
474 };
475
476 void pim_zebra_init(void)
477 {
478 /* Socket for receiving updates from Zebra daemon */
479 zclient = zclient_new(router->master, &zclient_options_default,
480 pim_handlers, array_size(pim_handlers));
481
482 zclient->zebra_capabilities = pim_zebra_capabilities;
483 zclient->zebra_connected = pim_zebra_connected;
484
485 zclient_init(zclient, ZEBRA_ROUTE_PIM, 0, &pimd_privs);
486 if (PIM_DEBUG_PIM_TRACE) {
487 zlog_notice("%s: zclient socket initialized", __func__);
488 }
489
490 zclient_lookup_new();
491 }
492
493 void pim_forward_start(struct pim_ifchannel *ch)
494 {
495 struct pim_upstream *up = ch->upstream;
496 uint32_t mask = 0;
497
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);
501
502 if (PIM_IF_FLAG_TEST_PROTO_IGMP(ch->flags))
503 mask = PIM_OIF_FLAG_PROTO_GM;
504
505 if (PIM_IF_FLAG_TEST_PROTO_PIM(ch->flags))
506 mask |= PIM_OIF_FLAG_PROTO_PIM;
507
508 pim_channel_add_oif(up->channel_oil, ch->interface,
509 mask, __func__);
510 }
511
512 void pim_forward_stop(struct pim_ifchannel *ch)
513 {
514 struct pim_upstream *up = ch->upstream;
515
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);
520 }
521
522 /*
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
525 */
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__);
529 else
530 pim_channel_del_oif(up->channel_oil, ch->interface,
531 PIM_OIF_FLAG_PROTO_PIM, __func__);
532 }
533
534 void pim_zebra_zclient_update(struct vty *vty)
535 {
536 vty_out(vty, "Zclient update socket: ");
537
538 if (zclient) {
539 vty_out(vty, "%d failures=%d\n", zclient->sock, zclient->fail);
540 } else {
541 vty_out(vty, "<null zclient>\n");
542 }
543 }
544
545 struct zclient *pim_zebra_zclient_get(void)
546 {
547 if (zclient)
548 return zclient;
549 else
550 return NULL;
551 }
552
553 void pim_zebra_interface_set_master(struct interface *vrf,
554 struct interface *ifp)
555 {
556 zclient_interface_set_master(zclient, vrf, ifp);
557 }