]> git.proxmox.com Git - mirror_frr.git/blame - pimd/pim_zebra.c
bgpd: Cleanup pointer assignment so compiler doesn't get confused
[mirror_frr.git] / pimd / pim_zebra.c
CommitLineData
12e41d03 1/*
896014f4
DL
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 */
12e41d03
DL
19
20#include <zebra.h>
21
12e41d03
DL
22#include "if.h"
23#include "log.h"
24#include "prefix.h"
25#include "zclient.h"
26#include "stream.h"
27#include "network.h"
dfe43e25
DW
28#include "vty.h"
29#include "plist.h"
ba4eb1bc 30#include "lib/bfd.h"
12e41d03
DL
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"
8f5f5e91 43#include "pim_rp.h"
2560106c 44#include "pim_igmpv3.h"
982bff89 45#include "pim_jp_agg.h"
1bc98276 46#include "pim_nht.h"
15a5dafe 47#include "pim_ssm.h"
af7b561b 48#include "pim_vxlan.h"
46c2687c 49#include "pim_mlag.h"
12e41d03
DL
50
51#undef PIM_DEBUG_IFADDR_DUMP
52#define PIM_DEBUG_IFADDR_DUMP
53
36b5b98f 54struct zclient *zclient;
38f4935a 55
12e41d03 56
12e41d03 57/* Router-id update message from zebra. */
121f9dee 58static int pim_router_id_update_zebra(ZAPI_CALLBACK_ARGS)
12e41d03 59{
d62a17ae 60 struct prefix router_id;
12e41d03 61
d62a17ae 62 zebra_router_id_update_read(zclient->ibuf, &router_id);
12e41d03 63
d62a17ae 64 return 0;
12e41d03
DL
65}
66
121f9dee 67static int pim_zebra_interface_vrf_update(ZAPI_CALLBACK_ARGS)
ee568318
DS
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)
15569c58
DA
78 zlog_debug("%s: %s updating from %u to %u", __func__, ifp->name,
79 vrf_id, new_vrf_id);
ee568318 80
a36898e7 81 if_update_to_new_vrf(ifp, new_vrf_id);
ee568318
DS
82
83 return 0;
84}
85
12e41d03
DL
86#ifdef PIM_DEBUG_IFADDR_DUMP
87static void dump_if_address(struct interface *ifp)
88{
d62a17ae 89 struct connected *ifc;
90 struct listnode *node;
91
5e81f5dd
DS
92 zlog_debug("%s %s: interface %s addresses:", __FILE__, __func__,
93 ifp->name);
d62a17ae 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
ee2bbf7c
MS
101 zlog_debug("%s %s: interface %s address %pI4 %s", __FILE__,
102 __func__, ifp->name, &p->u.prefix4,
d62a17ae 103 CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY)
104 ? "secondary"
105 : "primary");
106 }
12e41d03
DL
107}
108#endif
109
121f9dee 110static int pim_zebra_if_address_add(ZAPI_CALLBACK_ARGS)
12e41d03 111{
d62a17ae 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 */
121f9dee 124 c = zebra_interface_address_read(cmd, zclient->ibuf, vrf_id);
d62a17ae 125 if (!c)
126 return 0;
127
128 pim_ifp = c->ifp->info;
129 p = c->address;
130
131 if (PIM_DEBUG_ZEBRA) {
2dbe669b
DA
132 zlog_debug("%s: %s(%u) connected IP address %pFX flags %u %s",
133 __func__, c->ifp->name, vrf_id, p, c->flags,
996c9314
LB
134 CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY)
135 ? "secondary"
136 : "primary");
d62a17ae 137
12e41d03 138#ifdef PIM_DEBUG_IFADDR_DUMP
d62a17ae 139 dump_if_address(c->ifp);
12e41d03 140#endif
d62a17ae 141 }
12e41d03 142
94120cb2 143#if PIM_IPV == 4
034db86b
DL
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)) {
2dbe669b 152 if (PIM_DEBUG_ZEBRA)
d62a17ae 153 zlog_warn(
2dbe669b
DA
154 "%s: %s : forcing secondary flag on %pFX",
155 __func__, c->ifp->name, p);
d62a17ae 156 SET_FLAG(c->flags, ZEBRA_IFA_SECONDARY);
157 }
158 }
97feb13f
DL
159#else /* PIM_IPV != 4 */
160 if (p->family != PIM_AF)
161 return 0;
162#endif
12e41d03 163
d62a17ae 164 pim_if_addr_add(c);
26bb1fd5 165 if (pim_ifp) {
94120cb2
DL
166 struct pim_instance *pim;
167
26bb1fd5 168 pim = pim_get_pim_instance(vrf_id);
e2067d59 169 if (!pim) {
170 if (PIM_DEBUG_ZEBRA)
171 zlog_debug("%s: Unable to find pim instance",
172 __func__);
173 return 0;
174 }
175
26bb1fd5
DS
176 pim_ifp->pim = pim;
177
d62a17ae 178 pim_rp_check_on_if_add(pim_ifp);
26bb1fd5 179 }
12e41d03 180
d62a17ae 181 if (if_is_loopback(c->ifp)) {
4bb0e8f0 182 struct vrf *vrf = vrf_lookup_by_id(vrf_id);
d62a17ae 183 struct interface *ifp;
d8424057 184
451fda4f 185 FOR_ALL_INTERFACES (vrf, ifp) {
d62a17ae 186 if (!if_is_loopback(ifp) && if_is_operative(ifp))
187 pim_if_addr_add_all(ifp);
188 }
189 }
d62a17ae 190 return 0;
12e41d03
DL
191}
192
121f9dee 193static int pim_zebra_if_address_del(ZAPI_CALLBACK_ARGS)
12e41d03 194{
d62a17ae 195 struct connected *c;
196 struct prefix *p;
fec883d9 197 struct vrf *vrf = vrf_lookup_by_id(vrf_id);
819f099b
DS
198
199 if (!vrf)
200 return 0;
d62a17ae 201
202 /*
203 zebra api notifies address adds/dels events by using the same call
204 interface_add_read below, see comments in lib/zclient.c
205
206 zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_DELETE, ...)
207 will remove address from interface list by calling
208 connected_delete_by_prefix()
209 */
121f9dee 210 c = zebra_interface_address_read(cmd, zclient->ibuf, vrf_id);
d62a17ae 211 if (!c)
212 return 0;
213
214 p = c->address;
6233f087 215
94120cb2
DL
216 if (PIM_DEBUG_ZEBRA) {
217 zlog_debug(
218 "%s: %s(%u) disconnected IP address %pFX flags %u %s",
219 __func__, c->ifp->name, vrf_id, p, c->flags,
220 CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY)
221 ? "secondary"
222 : "primary");
12e41d03 223#ifdef PIM_DEBUG_IFADDR_DUMP
94120cb2 224 dump_if_address(c->ifp);
12e41d03 225#endif
94120cb2 226 }
12e41d03 227
97feb13f 228 if (p->family == PIM_AF) {
94120cb2 229 struct pim_instance *pim;
12e41d03 230
94120cb2 231 pim = vrf->info;
d62a17ae 232 pim_if_addr_del(c, 0);
fec883d9
DS
233 pim_rp_setup(pim);
234 pim_i_am_rp_re_evaluate(pim);
d62a17ae 235 }
6233f087 236
721c0857 237 connected_free(&c);
d62a17ae 238 return 0;
12e41d03
DL
239}
240
74389231
DS
241void pim_zebra_update_all_interfaces(struct pim_instance *pim)
242{
243 struct interface *ifp;
244
245 FOR_ALL_INTERFACES (pim->vrf, ifp) {
246 struct pim_interface *pim_ifp = ifp->info;
247 struct pim_iface_upstream_switch *us;
248 struct listnode *node;
249
250 if (!pim_ifp)
251 continue;
252
253 for (ALL_LIST_ELEMENTS_RO(pim_ifp->upstream_switch_list, node,
254 us)) {
255 struct pim_rpf rpf;
256
257 rpf.source_nexthop.interface = ifp;
00b1f412 258 pim_addr_to_prefix(&rpf.rpf_addr, us->address);
74389231
DS
259 pim_joinprune_send(&rpf, us->us);
260 pim_jp_agg_clear_group(us->us);
261 }
262 }
263}
264
cc67ccf9
DS
265void pim_zebra_upstream_rpf_changed(struct pim_instance *pim,
266 struct pim_upstream *up,
267 struct pim_rpf *old)
268{
1250cb5d
SP
269 if (old->source_nexthop.interface) {
270 struct pim_neighbor *nbr;
cc67ccf9 271
9bb93fa0
DL
272 nbr = pim_neighbor_find_prefix(old->source_nexthop.interface,
273 &old->rpf_addr);
1250cb5d 274 if (nbr)
c5cdf069 275 pim_jp_agg_remove_group(nbr->upstream_jp_agg, up, nbr);
cc67ccf9 276
cc67ccf9 277 /*
1250cb5d
SP
278 * We have detected a case where we might need
279 * to rescan the inherited o_list so do it.
cc67ccf9 280 */
1250cb5d
SP
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 }
cc67ccf9 285
1250cb5d
SP
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)
69e3538c 293 pim_upstream_mroute_add(up->channel_oil,
15569c58 294 __func__);
1250cb5d
SP
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 {
cc67ccf9 319 /*
1250cb5d
SP
320 * We have detected a case where we might need
321 * to rescan the inherited o_list so do it.
cc67ccf9 322 */
1250cb5d
SP
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 }
cc67ccf9 327
db431af2
AK
328 if (up->join_state == PIM_UPSTREAM_JOINED)
329 pim_jp_agg_switch_interface(old, &up->rpf, up);
330
1250cb5d 331 if (!up->channel_oil->installed)
15569c58 332 pim_upstream_mroute_add(up->channel_oil, __func__);
1250cb5d 333 }
cc67ccf9 334
1250cb5d
SP
335 /* FIXME can join_desired actually be changed by pim_rpf_update()
336 * returning PIM_RPF_CHANGED ?
337 */
cc67ccf9
DS
338 pim_upstream_update_join_desired(pim, up);
339}
340
94120cb2 341__attribute__((unused))
121f9dee 342static int pim_zebra_vxlan_sg_proc(ZAPI_CALLBACK_ARGS)
af7b561b
AK
343{
344 struct stream *s;
345 struct pim_instance *pim;
6fff2cc6
DL
346 pim_sgaddr sg;
347 size_t prefixlen;
af7b561b
AK
348
349 pim = pim_get_pim_instance(vrf_id);
350 if (!pim)
351 return 0;
352
353 s = zclient->ibuf;
354
6fff2cc6 355 prefixlen = stream_getl(s);
c631920c
DL
356 stream_get(&sg.src, s, prefixlen);
357 stream_get(&sg.grp, s, prefixlen);
af7b561b 358
9bace5c2
DL
359 if (PIM_DEBUG_ZEBRA)
360 zlog_debug("%u:recv SG %s %pSG", vrf_id,
361 (cmd == ZEBRA_VXLAN_SG_ADD) ? "add" : "del", &sg);
af7b561b 362
121f9dee 363 if (cmd == ZEBRA_VXLAN_SG_ADD)
af7b561b
AK
364 pim_vxlan_sg_add(pim, &sg);
365 else
366 pim_vxlan_sg_del(pim, &sg);
367
368 return 0;
369}
370
94120cb2 371__attribute__((unused))
ecbbc3a7
AK
372static 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
da11e325 389void pim_scan_oil(struct pim_instance *pim)
8a67a996 390{
d62a17ae 391 struct channel_oil *c_oil;
d62a17ae 392
bfc92019
DS
393 pim->scan_oil_last = pim_time_monotonic_sec();
394 ++pim->scan_oil_events;
d62a17ae 395
7315ecda 396 frr_each (rb_pim_oil, &pim->channel_oil_head, c_oil)
7984af18 397 pim_upstream_mroute_iif_update(c_oil, __func__);
12e41d03
DL
398}
399
cc9f21da 400static void on_rpf_cache_refresh(struct thread *t)
12e41d03 401{
da11e325
DS
402 struct pim_instance *pim = THREAD_ARG(t);
403
d62a17ae 404 /* update kernel multicast forwarding cache (MFC) */
da11e325 405 pim_scan_oil(pim);
12e41d03 406
bfc92019
DS
407 pim->rpf_cache_refresh_last = pim_time_monotonic_sec();
408 ++pim->rpf_cache_refresh_events;
12e41d03 409
d62a17ae 410 // It is called as part of pim_neighbor_add
411 // pim_rp_setup ();
12e41d03
DL
412}
413
da11e325 414void sched_rpf_cache_refresh(struct pim_instance *pim)
12e41d03 415{
bfc92019 416 ++pim->rpf_cache_refresh_requests;
12e41d03 417
bfc92019 418 pim_rpf_set_refresh_time(pim);
e71bf8f7 419
da11e325 420 if (pim->rpf_cache_refresher) {
d62a17ae 421 /* Refresh timer is already running */
422 return;
423 }
12e41d03 424
d62a17ae 425 /* Start refresh timer */
12e41d03 426
d62a17ae 427 if (PIM_DEBUG_ZEBRA) {
15569c58 428 zlog_debug("%s: triggering %ld msec timer", __func__,
da03883e 429 router->rpf_cache_refresh_delay_msec);
d62a17ae 430 }
12e41d03 431
36417fcc 432 thread_add_timer_msec(router->master, on_rpf_cache_refresh, pim,
da03883e 433 router->rpf_cache_refresh_delay_msec,
da11e325 434 &pim->rpf_cache_refresher);
12e41d03
DL
435}
436
d62a17ae 437static void pim_zebra_connected(struct zclient *zclient)
48e8451b 438{
94120cb2 439#if PIM_IPV == 4
d62a17ae 440 /* Send the client registration */
0945d5ed 441 bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER, router->vrf_id);
94120cb2 442#endif
ba4eb1bc 443
4dfe9ad2 444 zclient_send_reg_requests(zclient, router->vrf_id);
ecbbc3a7 445
94120cb2 446#if PIM_IPV == 4
ecbbc3a7
AK
447 /* request for VxLAN BUM group addresses */
448 pim_zebra_vxlan_replay();
94120cb2 449#endif
48e8451b 450}
8711a53d 451
ac567a6f
DS
452static void pim_zebra_capabilities(struct zclient_capabilities *cap)
453{
05ca004b 454 router->mlag_role = cap->role;
ac567a6f
DS
455}
456
a243d1db 457static zclient_handler *const pim_handlers[] = {
a243d1db
DL
458 [ZEBRA_INTERFACE_ADDRESS_ADD] = pim_zebra_if_address_add,
459 [ZEBRA_INTERFACE_ADDRESS_DELETE] = pim_zebra_if_address_del,
0455229c
DL
460
461 [ZEBRA_NEXTHOP_UPDATE] = pim_parse_nexthop_update,
94120cb2 462 [ZEBRA_ROUTER_ID_UPDATE] = pim_router_id_update_zebra,
a243d1db 463 [ZEBRA_INTERFACE_VRF_UPDATE] = pim_zebra_interface_vrf_update,
a243d1db 464
97feb13f 465#if PIM_IPV == 4
a243d1db
DL
466 [ZEBRA_VXLAN_SG_ADD] = pim_zebra_vxlan_sg_proc,
467 [ZEBRA_VXLAN_SG_DEL] = pim_zebra_vxlan_sg_proc,
468
469 [ZEBRA_MLAG_PROCESS_UP] = pim_zebra_mlag_process_up,
470 [ZEBRA_MLAG_PROCESS_DOWN] = pim_zebra_mlag_process_down,
471 [ZEBRA_MLAG_FORWARD_MSG] = pim_zebra_mlag_handle_msg,
94120cb2 472#endif
a243d1db
DL
473};
474
eb05883f 475void pim_zebra_init(void)
12e41d03 476{
d62a17ae 477 /* Socket for receiving updates from Zebra daemon */
a243d1db
DL
478 zclient = zclient_new(router->master, &zclient_options_default,
479 pim_handlers, array_size(pim_handlers));
d62a17ae 480
ac567a6f 481 zclient->zebra_capabilities = pim_zebra_capabilities;
d62a17ae 482 zclient->zebra_connected = pim_zebra_connected;
d62a17ae 483
342213ea 484 zclient_init(zclient, ZEBRA_ROUTE_PIM, 0, &pimd_privs);
d62a17ae 485 if (PIM_DEBUG_PIM_TRACE) {
15569c58 486 zlog_notice("%s: zclient socket initialized", __func__);
d62a17ae 487 }
488
489 zclient_lookup_new();
12e41d03
DL
490}
491
12e41d03
DL
492void pim_forward_start(struct pim_ifchannel *ch)
493{
d62a17ae 494 struct pim_upstream *up = ch->upstream;
9443810e 495 uint32_t mask = 0;
d62a17ae 496
8e8be741 497 if (PIM_DEBUG_PIM_TRACE)
41490e0e 498 zlog_debug("%s: (S,G)=%pSG oif=%s (%pPA)", __func__, &ch->sg,
8e8be741 499 ch->interface->name, &up->upstream_addr);
d62a17ae 500
9443810e 501 if (PIM_IF_FLAG_TEST_PROTO_IGMP(ch->flags))
80a82b56 502 mask = PIM_OIF_FLAG_PROTO_GM;
d62a17ae 503
9443810e
SP
504 if (PIM_IF_FLAG_TEST_PROTO_PIM(ch->flags))
505 mask |= PIM_OIF_FLAG_PROTO_PIM;
506
1b249e70
AK
507 pim_channel_add_oif(up->channel_oil, ch->interface,
508 mask, __func__);
12e41d03
DL
509}
510
86696f7b 511void pim_forward_stop(struct pim_ifchannel *ch)
12e41d03 512{
d62a17ae 513 struct pim_upstream *up = ch->upstream;
12e41d03 514
d62a17ae 515 if (PIM_DEBUG_PIM_TRACE) {
86696f7b 516 zlog_debug("%s: (S,G)=%s oif=%s installed: %d",
15569c58 517 __func__, ch->sg_str, ch->interface->name,
86696f7b 518 up->channel_oil->installed);
d62a17ae 519 }
12e41d03 520
2164ed5d
DS
521 /*
522 * If a channel is being removed, check to see if we still need
523 * to inherit the interface. If so make sure it is added in
524 */
525 if (pim_upstream_evaluate_join_desired_interface(up, ch, ch->parent))
526 pim_channel_add_oif(up->channel_oil, ch->interface,
1b249e70 527 PIM_OIF_FLAG_PROTO_PIM, __func__);
2164ed5d
DS
528 else
529 pim_channel_del_oif(up->channel_oil, ch->interface,
1b249e70 530 PIM_OIF_FLAG_PROTO_PIM, __func__);
12e41d03 531}
8799b66b 532
d62a17ae 533void pim_zebra_zclient_update(struct vty *vty)
8799b66b 534{
d62a17ae 535 vty_out(vty, "Zclient update socket: ");
536
537 if (zclient) {
538 vty_out(vty, "%d failures=%d\n", zclient->sock, zclient->fail);
539 } else {
540 vty_out(vty, "<null zclient>\n");
541 }
8799b66b 542}
1bc98276 543
d62a17ae 544struct zclient *pim_zebra_zclient_get(void)
1bc98276 545{
d62a17ae 546 if (zclient)
547 return zclient;
548 else
549 return NULL;
1bc98276 550}
ddbf3e60
DS
551
552void pim_zebra_interface_set_master(struct interface *vrf,
553 struct interface *ifp)
554{
555 zclient_interface_set_master(zclient, vrf, ifp);
556}