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