Line data Source code
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 2 : static int pim_router_id_update_zebra(ZAPI_CALLBACK_ARGS)
59 : {
60 2 : struct prefix router_id;
61 :
62 2 : zebra_router_id_update_read(zclient->ibuf, &router_id);
63 :
64 2 : return 0;
65 : }
66 :
67 0 : static int pim_zebra_interface_vrf_update(ZAPI_CALLBACK_ARGS)
68 : {
69 0 : struct interface *ifp;
70 0 : vrf_id_t new_vrf_id;
71 :
72 0 : ifp = zebra_interface_vrf_update_read(zclient->ibuf, vrf_id,
73 : &new_vrf_id);
74 0 : if (!ifp)
75 : return 0;
76 :
77 0 : if (PIM_DEBUG_ZEBRA)
78 0 : zlog_debug("%s: %s updating from %u to %u", __func__, ifp->name,
79 : vrf_id, new_vrf_id);
80 :
81 0 : if_update_to_new_vrf(ifp, new_vrf_id);
82 :
83 0 : return 0;
84 : }
85 :
86 : #ifdef PIM_DEBUG_IFADDR_DUMP
87 0 : static void dump_if_address(struct interface *ifp)
88 : {
89 0 : struct connected *ifc;
90 0 : struct listnode *node;
91 :
92 0 : zlog_debug("%s %s: interface %s addresses:", __FILE__, __func__,
93 : ifp->name);
94 :
95 0 : for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) {
96 0 : struct prefix *p = ifc->address;
97 :
98 0 : if (p->family != AF_INET)
99 0 : continue;
100 :
101 0 : 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 0 : }
108 : #endif
109 :
110 27 : static int pim_zebra_if_address_add(ZAPI_CALLBACK_ARGS)
111 : {
112 27 : struct connected *c;
113 27 : struct prefix *p;
114 27 : 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 27 : c = zebra_interface_address_read(cmd, zclient->ibuf, vrf_id);
125 27 : if (!c)
126 : return 0;
127 :
128 27 : pim_ifp = c->ifp->info;
129 27 : p = c->address;
130 :
131 27 : if (PIM_DEBUG_ZEBRA) {
132 0 : 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 0 : 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 27 : if (p->family != PIM_AF)
161 : return 0;
162 : #endif
163 :
164 11 : pim_if_addr_add(c);
165 11 : if (pim_ifp) {
166 5 : struct pim_instance *pim;
167 :
168 5 : pim = pim_get_pim_instance(vrf_id);
169 5 : if (!pim) {
170 0 : if (PIM_DEBUG_ZEBRA)
171 0 : zlog_debug("%s: Unable to find pim instance",
172 : __func__);
173 0 : return 0;
174 : }
175 :
176 5 : pim_ifp->pim = pim;
177 :
178 5 : pim_rp_check_on_if_add(pim_ifp);
179 : }
180 :
181 11 : if (if_is_loopback(c->ifp)) {
182 4 : struct vrf *vrf = vrf_lookup_by_id(vrf_id);
183 4 : struct interface *ifp;
184 :
185 20 : FOR_ALL_INTERFACES (vrf, ifp) {
186 12 : if (!if_is_loopback(ifp) && if_is_operative(ifp))
187 1 : pim_if_addr_add_all(ifp);
188 : }
189 : }
190 : return 0;
191 : }
192 :
193 1 : static int pim_zebra_if_address_del(ZAPI_CALLBACK_ARGS)
194 : {
195 1 : struct connected *c;
196 1 : struct prefix *p;
197 1 : struct vrf *vrf = vrf_lookup_by_id(vrf_id);
198 :
199 1 : if (!vrf)
200 : return 0;
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 : */
210 1 : c = zebra_interface_address_read(cmd, zclient->ibuf, vrf_id);
211 1 : if (!c)
212 : return 0;
213 :
214 1 : p = c->address;
215 :
216 1 : if (PIM_DEBUG_ZEBRA) {
217 0 : 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");
223 : #ifdef PIM_DEBUG_IFADDR_DUMP
224 0 : dump_if_address(c->ifp);
225 : #endif
226 : }
227 :
228 1 : if (p->family == PIM_AF) {
229 0 : struct pim_instance *pim;
230 :
231 0 : pim = vrf->info;
232 0 : pim_if_addr_del(c, 0);
233 0 : pim_rp_setup(pim);
234 0 : pim_i_am_rp_re_evaluate(pim);
235 : }
236 :
237 1 : connected_free(&c);
238 1 : return 0;
239 : }
240 :
241 4 : void pim_zebra_update_all_interfaces(struct pim_instance *pim)
242 : {
243 4 : struct interface *ifp;
244 :
245 24 : FOR_ALL_INTERFACES (pim->vrf, ifp) {
246 16 : struct pim_interface *pim_ifp = ifp->info;
247 16 : struct pim_iface_upstream_switch *us;
248 16 : struct listnode *node;
249 :
250 16 : if (!pim_ifp)
251 0 : continue;
252 :
253 32 : for (ALL_LIST_ELEMENTS_RO(pim_ifp->upstream_switch_list, node,
254 : us)) {
255 0 : struct pim_rpf rpf;
256 :
257 0 : rpf.source_nexthop.interface = ifp;
258 0 : rpf.rpf_addr = us->address;
259 0 : pim_joinprune_send(&rpf, us->us);
260 0 : pim_jp_agg_clear_group(us->us);
261 : }
262 : }
263 4 : }
264 :
265 0 : void pim_zebra_upstream_rpf_changed(struct pim_instance *pim,
266 : struct pim_upstream *up,
267 : struct pim_rpf *old)
268 : {
269 0 : if (old->source_nexthop.interface) {
270 0 : struct pim_neighbor *nbr;
271 :
272 0 : nbr = pim_neighbor_find(old->source_nexthop.interface,
273 : old->rpf_addr);
274 0 : if (nbr)
275 0 : 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 0 : if (up->channel_oil->oil_inherited_rescan) {
282 0 : pim_upstream_inherited_olist_decide(pim, up);
283 0 : up->channel_oil->oil_inherited_rescan = 0;
284 : }
285 :
286 0 : 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 0 : if (!up->channel_oil->installed)
293 0 : 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 0 : pim_jp_agg_switch_interface(old, &up->rpf, up);
313 :
314 0 : 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 0 : if (up->channel_oil->oil_inherited_rescan) {
324 0 : pim_upstream_inherited_olist_decide(pim, up);
325 0 : up->channel_oil->oil_inherited_rescan = 0;
326 : }
327 :
328 0 : if (up->join_state == PIM_UPSTREAM_JOINED)
329 0 : pim_jp_agg_switch_interface(old, &up->rpf, up);
330 :
331 0 : if (!up->channel_oil->installed)
332 0 : 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 0 : pim_upstream_update_join_desired(pim, up);
339 0 : }
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 2 : void pim_scan_oil(struct pim_instance *pim)
390 : {
391 2 : struct channel_oil *c_oil;
392 :
393 2 : pim->scan_oil_last = pim_time_monotonic_sec();
394 2 : ++pim->scan_oil_events;
395 :
396 4 : frr_each (rb_pim_oil, &pim->channel_oil_head, c_oil)
397 0 : pim_upstream_mroute_iif_update(c_oil, __func__);
398 2 : }
399 :
400 2 : static void on_rpf_cache_refresh(struct thread *t)
401 : {
402 2 : struct pim_instance *pim = THREAD_ARG(t);
403 :
404 : /* update kernel multicast forwarding cache (MFC) */
405 2 : pim_scan_oil(pim);
406 :
407 2 : pim->rpf_cache_refresh_last = pim_time_monotonic_sec();
408 2 : ++pim->rpf_cache_refresh_events;
409 :
410 : // It is called as part of pim_neighbor_add
411 : // pim_rp_setup ();
412 2 : }
413 :
414 4 : void sched_rpf_cache_refresh(struct pim_instance *pim)
415 : {
416 4 : ++pim->rpf_cache_refresh_requests;
417 :
418 4 : pim_rpf_set_refresh_time(pim);
419 :
420 4 : if (pim->rpf_cache_refresher) {
421 : /* Refresh timer is already running */
422 : return;
423 : }
424 :
425 : /* Start refresh timer */
426 :
427 4 : if (PIM_DEBUG_ZEBRA) {
428 0 : zlog_debug("%s: triggering %ld msec timer", __func__,
429 : router->rpf_cache_refresh_delay_msec);
430 : }
431 :
432 4 : thread_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 2 : 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 2 : 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 2 : }
451 :
452 2 : static void pim_zebra_capabilities(struct zclient_capabilities *cap)
453 : {
454 2 : router->mlag_role = cap->role;
455 2 : router->multipath = cap->ecmp;
456 2 : }
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 2 : void pim_zebra_init(void)
477 : {
478 : /* Socket for receiving updates from Zebra daemon */
479 2 : zclient = zclient_new(router->master, &zclient_options_default,
480 : pim_handlers, array_size(pim_handlers));
481 :
482 2 : zclient->zebra_capabilities = pim_zebra_capabilities;
483 2 : zclient->zebra_connected = pim_zebra_connected;
484 :
485 2 : zclient_init(zclient, ZEBRA_ROUTE_PIM, 0, &pimd_privs);
486 2 : if (PIM_DEBUG_PIM_TRACE) {
487 0 : zlog_notice("%s: zclient socket initialized", __func__);
488 : }
489 :
490 2 : zclient_lookup_new();
491 2 : }
492 :
493 1 : void pim_forward_start(struct pim_ifchannel *ch)
494 : {
495 1 : struct pim_upstream *up = ch->upstream;
496 1 : uint32_t mask = 0;
497 :
498 1 : if (PIM_DEBUG_PIM_TRACE)
499 0 : zlog_debug("%s: (S,G)=%pSG oif=%s (%pPA)", __func__, &ch->sg,
500 : ch->interface->name, &up->upstream_addr);
501 :
502 1 : if (PIM_IF_FLAG_TEST_PROTO_IGMP(ch->flags))
503 0 : mask = PIM_OIF_FLAG_PROTO_GM;
504 :
505 1 : if (PIM_IF_FLAG_TEST_PROTO_PIM(ch->flags))
506 1 : mask |= PIM_OIF_FLAG_PROTO_PIM;
507 :
508 1 : pim_channel_add_oif(up->channel_oil, ch->interface,
509 : mask, __func__);
510 1 : }
511 :
512 0 : void pim_forward_stop(struct pim_ifchannel *ch)
513 : {
514 0 : struct pim_upstream *up = ch->upstream;
515 :
516 0 : if (PIM_DEBUG_PIM_TRACE) {
517 0 : 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 0 : if (pim_upstream_evaluate_join_desired_interface(up, ch, ch->parent))
527 0 : pim_channel_add_oif(up->channel_oil, ch->interface,
528 : PIM_OIF_FLAG_PROTO_PIM, __func__);
529 : else
530 0 : pim_channel_del_oif(up->channel_oil, ch->interface,
531 : PIM_OIF_FLAG_PROTO_PIM, __func__);
532 0 : }
533 :
534 0 : void pim_zebra_zclient_update(struct vty *vty)
535 : {
536 0 : vty_out(vty, "Zclient update socket: ");
537 :
538 0 : if (zclient) {
539 0 : vty_out(vty, "%d failures=%d\n", zclient->sock, zclient->fail);
540 : } else {
541 0 : vty_out(vty, "<null zclient>\n");
542 : }
543 0 : }
544 :
545 21 : struct zclient *pim_zebra_zclient_get(void)
546 : {
547 21 : if (zclient)
548 : return zclient;
549 : else
550 0 : return NULL;
551 : }
552 :
553 0 : void pim_zebra_interface_set_master(struct interface *vrf,
554 : struct interface *ifp)
555 : {
556 0 : zclient_interface_set_master(zclient, vrf, ifp);
557 0 : }
|