]> git.proxmox.com Git - mirror_frr.git/blob - isisd/isis_zebra.c
bgpd: fix dereference of null pointer in bgp_attr_aspath
[mirror_frr.git] / isisd / isis_zebra.c
1 /*
2 * IS-IS Rout(e)ing protocol - isis_zebra.c
3 *
4 * Copyright (C) 2001,2002 Sampo Saaristo
5 * Tampere University of Technology
6 * Institute of Communications Engineering
7 * Copyright (C) 2013-2015 Christian Franke <chris@opensourcerouting.org>
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public Licenseas published by the Free
11 * Software Foundation; either version 2 of the License, or (at your option)
12 * any later version.
13 *
14 * This program is distributed in the hope that it will be useful,but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; see the file COPYING; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24 #include <zebra.h>
25
26 #include "thread.h"
27 #include "command.h"
28 #include "memory.h"
29 #include "log.h"
30 #include "lib_errors.h"
31 #include "if.h"
32 #include "network.h"
33 #include "prefix.h"
34 #include "zclient.h"
35 #include "stream.h"
36 #include "linklist.h"
37 #include "nexthop.h"
38 #include "vrf.h"
39 #include "libfrr.h"
40 #include "bfd.h"
41 #include "link_state.h"
42
43 #include "isisd/isis_constants.h"
44 #include "isisd/isis_common.h"
45 #include "isisd/isis_flags.h"
46 #include "isisd/isis_misc.h"
47 #include "isisd/isis_circuit.h"
48 #include "isisd/isisd.h"
49 #include "isisd/isis_circuit.h"
50 #include "isisd/isis_csm.h"
51 #include "isisd/isis_lsp.h"
52 #include "isisd/isis_spf.h"
53 #include "isisd/isis_spf_private.h"
54 #include "isisd/isis_route.h"
55 #include "isisd/isis_zebra.h"
56 #include "isisd/isis_adjacency.h"
57 #include "isisd/isis_te.h"
58 #include "isisd/isis_sr.h"
59 #include "isisd/isis_ldp_sync.h"
60
61 struct zclient *zclient;
62 static struct zclient *zclient_sync;
63
64 /* Router-id update message from zebra. */
65 static int isis_router_id_update_zebra(ZAPI_CALLBACK_ARGS)
66 {
67 struct isis_area *area;
68 struct listnode *node;
69 struct prefix router_id;
70 struct isis *isis = NULL;
71
72 isis = isis_lookup_by_vrfid(vrf_id);
73
74 if (isis == NULL) {
75 return -1;
76 }
77
78 zebra_router_id_update_read(zclient->ibuf, &router_id);
79 if (isis->router_id == router_id.u.prefix4.s_addr)
80 return 0;
81
82 isis->router_id = router_id.u.prefix4.s_addr;
83 for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area))
84 if (listcount(area->area_addrs) > 0)
85 lsp_regenerate_schedule(area, area->is_type, 0);
86
87 return 0;
88 }
89
90 static int isis_zebra_if_address_add(ZAPI_CALLBACK_ARGS)
91 {
92 struct isis_circuit *circuit;
93 struct connected *c;
94
95 c = zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_ADD,
96 zclient->ibuf, vrf_id);
97
98 if (c == NULL)
99 return 0;
100
101 #ifdef EXTREME_DEBUG
102 if (c->address->family == AF_INET)
103 zlog_debug("connected IP address %pFX", c->address);
104 if (c->address->family == AF_INET6)
105 zlog_debug("connected IPv6 address %pFX", c->address);
106 #endif /* EXTREME_DEBUG */
107
108 if (if_is_operative(c->ifp)) {
109 circuit = circuit_scan_by_ifp(c->ifp);
110 if (circuit)
111 isis_circuit_add_addr(circuit, c);
112 }
113
114 return 0;
115 }
116
117 static int isis_zebra_if_address_del(ZAPI_CALLBACK_ARGS)
118 {
119 struct isis_circuit *circuit;
120 struct connected *c;
121
122 c = zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_DELETE,
123 zclient->ibuf, vrf_id);
124
125 if (c == NULL)
126 return 0;
127
128 #ifdef EXTREME_DEBUG
129 if (c->address->family == AF_INET)
130 zlog_debug("disconnected IP address %pFX", c->address);
131 if (c->address->family == AF_INET6)
132 zlog_debug("disconnected IPv6 address %pFX", c->address);
133 #endif /* EXTREME_DEBUG */
134
135 if (if_is_operative(c->ifp)) {
136 circuit = circuit_scan_by_ifp(c->ifp);
137 if (circuit)
138 isis_circuit_del_addr(circuit, c);
139 }
140
141 connected_free(&c);
142
143 return 0;
144 }
145
146 static int isis_zebra_link_params(ZAPI_CALLBACK_ARGS)
147 {
148 struct interface *ifp;
149 bool changed = false;
150
151 ifp = zebra_interface_link_params_read(zclient->ibuf, vrf_id, &changed);
152
153 if (ifp == NULL || !changed)
154 return 0;
155
156 /* Update TE TLV */
157 isis_mpls_te_update(ifp);
158
159 return 0;
160 }
161
162 enum isis_zebra_nexthop_type {
163 ISIS_NEXTHOP_MAIN = 0,
164 ISIS_NEXTHOP_BACKUP,
165 };
166
167 static int isis_zebra_add_nexthops(struct isis *isis, struct list *nexthops,
168 struct zapi_nexthop zapi_nexthops[],
169 enum isis_zebra_nexthop_type type,
170 bool mpls_lsp, uint8_t backup_nhs)
171 {
172 struct isis_nexthop *nexthop;
173 struct listnode *node;
174 int count = 0;
175
176 /* Nexthops */
177 for (ALL_LIST_ELEMENTS_RO(nexthops, node, nexthop)) {
178 struct zapi_nexthop *api_nh;
179
180 if (count >= MULTIPATH_NUM)
181 break;
182 api_nh = &zapi_nexthops[count];
183 if (fabricd)
184 SET_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_ONLINK);
185 api_nh->vrf_id = isis->vrf_id;
186
187 switch (nexthop->family) {
188 case AF_INET:
189 /* FIXME: can it be ? */
190 if (nexthop->ip.ipv4.s_addr != INADDR_ANY) {
191 api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX;
192 api_nh->gate.ipv4 = nexthop->ip.ipv4;
193 } else {
194 api_nh->type = NEXTHOP_TYPE_IFINDEX;
195 }
196 break;
197 case AF_INET6:
198 if (!IN6_IS_ADDR_LINKLOCAL(&nexthop->ip.ipv6)
199 && !IN6_IS_ADDR_UNSPECIFIED(&nexthop->ip.ipv6)) {
200 continue;
201 }
202 api_nh->gate.ipv6 = nexthop->ip.ipv6;
203 api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX;
204 break;
205 default:
206 flog_err(EC_LIB_DEVELOPMENT,
207 "%s: unknown address family [%d]", __func__,
208 nexthop->family);
209 exit(1);
210 }
211
212 api_nh->ifindex = nexthop->ifindex;
213
214 /* Add MPLS label(s). */
215 if (nexthop->label_stack) {
216 api_nh->label_num = nexthop->label_stack->num_labels;
217 memcpy(api_nh->labels, nexthop->label_stack->label,
218 sizeof(mpls_label_t) * api_nh->label_num);
219 } else if (nexthop->sr.present) {
220 api_nh->label_num = 1;
221 api_nh->labels[0] = nexthop->sr.label;
222 } else if (mpls_lsp) {
223 switch (type) {
224 case ISIS_NEXTHOP_MAIN:
225 /*
226 * Do not use non-SR enabled nexthops to prevent
227 * broken LSPs from being formed.
228 */
229 continue;
230 case ISIS_NEXTHOP_BACKUP:
231 /*
232 * This is necessary because zebra requires
233 * the nexthops of MPLS LSPs to be labeled.
234 */
235 api_nh->label_num = 1;
236 api_nh->labels[0] = MPLS_LABEL_IMPLICIT_NULL;
237 break;
238 }
239 }
240
241 /* Backup nexthop handling. */
242 if (backup_nhs) {
243 SET_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_HAS_BACKUP);
244 /*
245 * If the backup has multiple nexthops, all of them
246 * protect the same primary nexthop since ECMP routes
247 * have no backups.
248 */
249 api_nh->backup_num = backup_nhs;
250 for (int i = 0; i < backup_nhs; i++)
251 api_nh->backup_idx[i] = i;
252 }
253 count++;
254 }
255
256 return count;
257 }
258
259 void isis_zebra_route_add_route(struct isis *isis, struct prefix *prefix,
260 struct prefix_ipv6 *src_p,
261 struct isis_route_info *route_info)
262 {
263 struct zapi_route api;
264 int count = 0;
265
266 if (zclient->sock < 0)
267 return;
268
269 /* Uninstall the route if it doesn't have any valid nexthop. */
270 if (list_isempty(route_info->nexthops)) {
271 isis_zebra_route_del_route(isis, prefix, src_p, route_info);
272 return;
273 }
274
275 memset(&api, 0, sizeof(api));
276 api.vrf_id = isis->vrf_id;
277 api.type = PROTO_TYPE;
278 api.safi = SAFI_UNICAST;
279 api.prefix = *prefix;
280 if (src_p && src_p->prefixlen) {
281 api.src_prefix = *src_p;
282 SET_FLAG(api.message, ZAPI_MESSAGE_SRCPFX);
283 }
284 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
285 SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
286 api.metric = route_info->cost;
287
288 /* Add backup nexthops first. */
289 if (route_info->backup) {
290 count = isis_zebra_add_nexthops(
291 isis, route_info->backup->nexthops, api.backup_nexthops,
292 ISIS_NEXTHOP_BACKUP, false, 0);
293 if (count > 0) {
294 SET_FLAG(api.message, ZAPI_MESSAGE_BACKUP_NEXTHOPS);
295 api.backup_nexthop_num = count;
296 }
297 }
298
299 /* Add primary nexthops. */
300 count = isis_zebra_add_nexthops(isis, route_info->nexthops,
301 api.nexthops, ISIS_NEXTHOP_MAIN, false,
302 count);
303 if (!count)
304 return;
305 api.nexthop_num = count;
306
307 zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api);
308 }
309
310 void isis_zebra_route_del_route(struct isis *isis,
311 struct prefix *prefix,
312 struct prefix_ipv6 *src_p,
313 struct isis_route_info *route_info)
314 {
315 struct zapi_route api;
316
317 if (zclient->sock < 0)
318 return;
319
320 memset(&api, 0, sizeof(api));
321 api.vrf_id = isis->vrf_id;
322 api.type = PROTO_TYPE;
323 api.safi = SAFI_UNICAST;
324 api.prefix = *prefix;
325 if (src_p && src_p->prefixlen) {
326 api.src_prefix = *src_p;
327 SET_FLAG(api.message, ZAPI_MESSAGE_SRCPFX);
328 }
329
330 zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api);
331 }
332
333 /**
334 * Install Prefix-SID label entry in the forwarding plane through Zebra.
335 *
336 * @param area IS-IS area
337 * @param prefix Route prefix
338 * @param rinfo Route information
339 * @param psid Prefix-SID information
340 */
341 void isis_zebra_prefix_sid_install(struct isis_area *area,
342 struct prefix *prefix,
343 struct isis_route_info *rinfo,
344 struct isis_sr_psid_info *psid)
345 {
346 struct zapi_labels zl;
347 int count = 0;
348
349 sr_debug("ISIS-Sr (%s): update label %u for prefix %pFX",
350 area->area_tag, psid->label, prefix);
351
352 /* Prepare message. */
353 memset(&zl, 0, sizeof(zl));
354 zl.type = ZEBRA_LSP_ISIS_SR;
355 zl.local_label = psid->label;
356
357 /* Local routes don't have any nexthop and require special handling. */
358 if (list_isempty(rinfo->nexthops)) {
359 struct zapi_nexthop *znh;
360 struct interface *ifp;
361
362 ifp = if_lookup_by_name("lo", VRF_DEFAULT);
363 if (!ifp) {
364 zlog_warn(
365 "%s: couldn't install Prefix-SID %pFX: loopback interface not found",
366 __func__, prefix);
367 return;
368 }
369
370 znh = &zl.nexthops[zl.nexthop_num++];
371 znh->type = NEXTHOP_TYPE_IFINDEX;
372 znh->ifindex = ifp->ifindex;
373 znh->label_num = 1;
374 znh->labels[0] = MPLS_LABEL_IMPLICIT_NULL;
375 } else {
376 /* Add backup nexthops first. */
377 if (rinfo->backup) {
378 count = isis_zebra_add_nexthops(
379 area->isis, rinfo->backup->nexthops,
380 zl.backup_nexthops, ISIS_NEXTHOP_BACKUP, true,
381 0);
382 if (count > 0) {
383 SET_FLAG(zl.message, ZAPI_LABELS_HAS_BACKUPS);
384 zl.backup_nexthop_num = count;
385 }
386 }
387
388 /* Add primary nexthops. */
389 count = isis_zebra_add_nexthops(area->isis, rinfo->nexthops,
390 zl.nexthops, ISIS_NEXTHOP_MAIN,
391 true, count);
392 if (!count)
393 return;
394 zl.nexthop_num = count;
395 }
396
397 /* Send message to zebra. */
398 (void)zebra_send_mpls_labels(zclient, ZEBRA_MPLS_LABELS_REPLACE, &zl);
399 }
400
401 /**
402 * Uninstall Prefix-SID label entry from the forwarding plane through Zebra.
403 *
404 * @param area IS-IS area
405 * @param prefix Route prefix
406 * @param rinfo Route information
407 * @param psid Prefix-SID information
408 */
409 void isis_zebra_prefix_sid_uninstall(struct isis_area *area,
410 struct prefix *prefix,
411 struct isis_route_info *rinfo,
412 struct isis_sr_psid_info *psid)
413 {
414 struct zapi_labels zl;
415
416 sr_debug("ISIS-Sr (%s): delete label %u for prefix %pFX",
417 area->area_tag, psid->label, prefix);
418
419 /* Prepare message. */
420 memset(&zl, 0, sizeof(zl));
421 zl.type = ZEBRA_LSP_ISIS_SR;
422 zl.local_label = psid->label;
423
424 /* Send message to zebra. */
425 (void)zebra_send_mpls_labels(zclient, ZEBRA_MPLS_LABELS_DELETE, &zl);
426 }
427
428 /**
429 * Send (LAN)-Adjacency-SID to ZEBRA for installation or deletion.
430 *
431 * @param cmd ZEBRA_MPLS_LABELS_ADD or ZEBRA_ROUTE_DELETE
432 * @param sra Segment Routing Adjacency-SID
433 */
434 void isis_zebra_send_adjacency_sid(int cmd, const struct sr_adjacency *sra)
435 {
436 struct isis *isis = sra->adj->circuit->area->isis;
437 struct zapi_labels zl;
438 struct zapi_nexthop *znh;
439
440 if (cmd != ZEBRA_MPLS_LABELS_ADD && cmd != ZEBRA_MPLS_LABELS_DELETE) {
441 flog_warn(EC_LIB_DEVELOPMENT, "%s: wrong ZEBRA command",
442 __func__);
443 return;
444 }
445
446 sr_debug(" |- %s label %u for interface %s",
447 cmd == ZEBRA_MPLS_LABELS_ADD ? "Add" : "Delete",
448 sra->input_label, sra->adj->circuit->interface->name);
449
450 memset(&zl, 0, sizeof(zl));
451 zl.type = ZEBRA_LSP_ISIS_SR;
452 zl.local_label = sra->input_label;
453 zl.nexthop_num = 1;
454 znh = &zl.nexthops[0];
455 znh->gate = sra->nexthop.address;
456 znh->type = (sra->nexthop.family == AF_INET)
457 ? NEXTHOP_TYPE_IPV4_IFINDEX
458 : NEXTHOP_TYPE_IPV6_IFINDEX;
459 znh->ifindex = sra->adj->circuit->interface->ifindex;
460 znh->label_num = 1;
461 znh->labels[0] = MPLS_LABEL_IMPLICIT_NULL;
462
463 /* Set backup nexthops. */
464 if (sra->type == ISIS_SR_LAN_BACKUP) {
465 int count;
466
467 count = isis_zebra_add_nexthops(isis, sra->backup_nexthops,
468 zl.backup_nexthops,
469 ISIS_NEXTHOP_BACKUP, true, 0);
470 if (count > 0) {
471 SET_FLAG(zl.message, ZAPI_LABELS_HAS_BACKUPS);
472 zl.backup_nexthop_num = count;
473
474 SET_FLAG(znh->flags, ZAPI_NEXTHOP_FLAG_HAS_BACKUP);
475 znh->backup_num = count;
476 for (int i = 0; i < count; i++)
477 znh->backup_idx[i] = i;
478 }
479 }
480
481 (void)zebra_send_mpls_labels(zclient, cmd, &zl);
482 }
483
484 static int isis_zebra_read(ZAPI_CALLBACK_ARGS)
485 {
486 struct zapi_route api;
487 struct isis *isis = NULL;
488
489 isis = isis_lookup_by_vrfid(vrf_id);
490
491 if (isis == NULL)
492 return -1;
493
494 if (zapi_route_decode(zclient->ibuf, &api) < 0)
495 return -1;
496
497 if (api.prefix.family == AF_INET6
498 && IN6_IS_ADDR_LINKLOCAL(&api.prefix.u.prefix6))
499 return 0;
500
501 /*
502 * Avoid advertising a false default reachability. (A default
503 * route installed by IS-IS gets redistributed from zebra back
504 * into IS-IS causing us to start advertising default reachabity
505 * without this check)
506 */
507 if (api.prefix.prefixlen == 0
508 && api.src_prefix.prefixlen == 0
509 && api.type == PROTO_TYPE) {
510 cmd = ZEBRA_REDISTRIBUTE_ROUTE_DEL;
511 }
512
513 if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_ADD)
514 isis_redist_add(isis, api.type, &api.prefix, &api.src_prefix,
515 api.distance, api.metric, api.tag);
516 else
517 isis_redist_delete(isis, api.type, &api.prefix,
518 &api.src_prefix);
519
520 return 0;
521 }
522
523 int isis_distribute_list_update(int routetype)
524 {
525 return 0;
526 }
527
528 void isis_zebra_redistribute_set(afi_t afi, int type, vrf_id_t vrf_id)
529 {
530 if (type == DEFAULT_ROUTE)
531 zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_ADD,
532 zclient, afi, vrf_id);
533 else
534 zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, afi, type,
535 0, vrf_id);
536 }
537
538 void isis_zebra_redistribute_unset(afi_t afi, int type, vrf_id_t vrf_id)
539 {
540 if (type == DEFAULT_ROUTE)
541 zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_DELETE,
542 zclient, afi, vrf_id);
543 else
544 zclient_redistribute(ZEBRA_REDISTRIBUTE_DELETE, zclient, afi,
545 type, 0, vrf_id);
546 }
547
548 /**
549 * Register RLFA with LDP.
550 */
551 int isis_zebra_rlfa_register(struct isis_spftree *spftree, struct rlfa *rlfa)
552 {
553 struct isis_area *area = spftree->area;
554 struct zapi_rlfa_request zr = {};
555 int ret;
556
557 if (!zclient)
558 return 0;
559
560 zr.igp.vrf_id = area->isis->vrf_id;
561 zr.igp.protocol = ZEBRA_ROUTE_ISIS;
562 strlcpy(zr.igp.isis.area_tag, area->area_tag,
563 sizeof(zr.igp.isis.area_tag));
564 zr.igp.isis.spf.tree_id = spftree->tree_id;
565 zr.igp.isis.spf.level = spftree->level;
566 zr.igp.isis.spf.run_id = spftree->runcount;
567 zr.destination = rlfa->prefix;
568 zr.pq_address = rlfa->pq_address;
569
570 zlog_debug("ISIS-LFA: registering RLFA %pFX@%pI4 with LDP",
571 &rlfa->prefix, &rlfa->pq_address);
572
573 ret = zclient_send_opaque_unicast(zclient, LDP_RLFA_REGISTER,
574 ZEBRA_ROUTE_LDP, 0, 0,
575 (const uint8_t *)&zr, sizeof(zr));
576 if (ret == ZCLIENT_SEND_FAILURE) {
577 zlog_warn("ISIS-LFA: failed to register RLFA with LDP");
578 return -1;
579 }
580
581 return 0;
582 }
583
584 /**
585 * Unregister all RLFAs from the given SPF tree with LDP.
586 */
587 void isis_zebra_rlfa_unregister_all(struct isis_spftree *spftree)
588 {
589 struct isis_area *area = spftree->area;
590 struct zapi_rlfa_igp igp = {};
591 int ret;
592
593 if (!zclient || spftree->type != SPF_TYPE_FORWARD
594 || CHECK_FLAG(spftree->flags, F_SPFTREE_NO_ADJACENCIES))
595 return;
596
597 if (IS_DEBUG_LFA)
598 zlog_debug("ISIS-LFA: unregistering all RLFAs with LDP");
599
600 igp.vrf_id = area->isis->vrf_id;
601 igp.protocol = ZEBRA_ROUTE_ISIS;
602 strlcpy(igp.isis.area_tag, area->area_tag, sizeof(igp.isis.area_tag));
603 igp.isis.spf.tree_id = spftree->tree_id;
604 igp.isis.spf.level = spftree->level;
605 igp.isis.spf.run_id = spftree->runcount;
606
607 ret = zclient_send_opaque_unicast(zclient, LDP_RLFA_UNREGISTER_ALL,
608 ZEBRA_ROUTE_LDP, 0, 0,
609 (const uint8_t *)&igp, sizeof(igp));
610 if (ret == ZCLIENT_SEND_FAILURE)
611 zlog_warn("ISIS-LFA: failed to unregister RLFA with LDP");
612 }
613
614 /* Label Manager Functions */
615
616 /**
617 * Check if Label Manager is Ready or not.
618 *
619 * @return True if Label Manager is ready, False otherwise
620 */
621 bool isis_zebra_label_manager_ready(void)
622 {
623 return (zclient_sync->sock > 0);
624 }
625
626 /**
627 * Request Label Range to the Label Manager.
628 *
629 * @param base base label of the label range to request
630 * @param chunk_size size of the label range to request
631 *
632 * @return 0 on success, -1 on failure
633 */
634 int isis_zebra_request_label_range(uint32_t base, uint32_t chunk_size)
635 {
636 int ret;
637 uint32_t start, end;
638
639 if (zclient_sync->sock < 0)
640 return -1;
641
642 ret = lm_get_label_chunk(zclient_sync, 0, base, chunk_size, &start,
643 &end);
644 if (ret < 0) {
645 zlog_warn("%s: error getting label range!", __func__);
646 return -1;
647 }
648
649 return 0;
650 }
651
652 /**
653 * Release Label Range to the Label Manager.
654 *
655 * @param start start of label range to release
656 * @param end end of label range to release
657 *
658 * @return 0 on success, -1 otherwise
659 */
660 int isis_zebra_release_label_range(uint32_t start, uint32_t end)
661 {
662 int ret;
663
664 if (zclient_sync->sock < 0)
665 return -1;
666
667 ret = lm_release_label_chunk(zclient_sync, start, end);
668 if (ret < 0) {
669 zlog_warn("%s: error releasing label range!", __func__);
670 return -1;
671 }
672
673 return 0;
674 }
675
676 /**
677 * Connect to the Label Manager.
678 *
679 * @return 0 on success, -1 otherwise
680 */
681 int isis_zebra_label_manager_connect(void)
682 {
683 /* Connect to label manager. */
684 if (zclient_socket_connect(zclient_sync) < 0) {
685 zlog_warn("%s: failed connecting synchronous zclient!",
686 __func__);
687 return -1;
688 }
689 /* make socket non-blocking */
690 set_nonblocking(zclient_sync->sock);
691
692 /* Send hello to notify zebra this is a synchronous client */
693 if (zclient_send_hello(zclient_sync) == ZCLIENT_SEND_FAILURE) {
694 zlog_warn("%s: failed sending hello for synchronous zclient!",
695 __func__);
696 close(zclient_sync->sock);
697 zclient_sync->sock = -1;
698 return -1;
699 }
700
701 /* Connect to label manager */
702 if (lm_label_manager_connect(zclient_sync, 0) != 0) {
703 zlog_warn("%s: failed connecting to label manager!", __func__);
704 if (zclient_sync->sock > 0) {
705 close(zclient_sync->sock);
706 zclient_sync->sock = -1;
707 }
708 return -1;
709 }
710
711 sr_debug("ISIS-Sr: Successfully connected to the Label Manager");
712
713 return 0;
714 }
715
716 void isis_zebra_vrf_register(struct isis *isis)
717 {
718 if (!zclient || zclient->sock < 0 || !isis)
719 return;
720
721 if (isis->vrf_id != VRF_UNKNOWN) {
722 if (IS_DEBUG_EVENTS)
723 zlog_debug("%s: Register VRF %s id %u", __func__,
724 isis->name, isis->vrf_id);
725 zclient_send_reg_requests(zclient, isis->vrf_id);
726 }
727 }
728
729 void isis_zebra_vrf_deregister(struct isis *isis)
730 {
731 if (!zclient || zclient->sock < 0 || !isis)
732 return;
733
734 if (isis->vrf_id != VRF_UNKNOWN) {
735 if (IS_DEBUG_EVENTS)
736 zlog_debug("%s: Deregister VRF %s id %u", __func__,
737 isis->name, isis->vrf_id);
738 zclient_send_dereg_requests(zclient, isis->vrf_id);
739 }
740 }
741
742 static void isis_zebra_connected(struct zclient *zclient)
743 {
744 zclient_send_reg_requests(zclient, VRF_DEFAULT);
745 zclient_register_opaque(zclient, LDP_RLFA_LABELS);
746 zclient_register_opaque(zclient, LDP_IGP_SYNC_IF_STATE_UPDATE);
747 zclient_register_opaque(zclient, LDP_IGP_SYNC_ANNOUNCE_UPDATE);
748 bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER, VRF_DEFAULT);
749 }
750
751 /**
752 * Register / unregister Link State ZAPI Opaque Message
753 *
754 * @param up True to register, false to unregister
755 *
756 * @return 0 if success, -1 otherwise
757 */
758 int isis_zebra_ls_register(bool up)
759 {
760 int rc;
761
762 if (up)
763 rc = ls_register(zclient, true);
764 else
765 rc = ls_unregister(zclient, true);
766
767 return rc;
768 }
769
770 /*
771 * opaque messages between processes
772 */
773 static int isis_opaque_msg_handler(ZAPI_CALLBACK_ARGS)
774 {
775 struct stream *s;
776 struct zapi_opaque_msg info;
777 struct zapi_opaque_reg_info dst;
778 struct ldp_igp_sync_if_state state;
779 struct ldp_igp_sync_announce announce;
780 struct zapi_rlfa_response rlfa;
781 int ret = 0;
782
783 s = zclient->ibuf;
784 if (zclient_opaque_decode(s, &info) != 0)
785 return -1;
786
787 switch (info.type) {
788 case LINK_STATE_SYNC:
789 STREAM_GETC(s, dst.proto);
790 STREAM_GETW(s, dst.instance);
791 STREAM_GETL(s, dst.session_id);
792 dst.type = LINK_STATE_SYNC;
793 ret = isis_te_sync_ted(dst);
794 break;
795 case LDP_IGP_SYNC_IF_STATE_UPDATE:
796 STREAM_GET(&state, s, sizeof(state));
797 ret = isis_ldp_sync_state_update(state);
798 break;
799 case LDP_IGP_SYNC_ANNOUNCE_UPDATE:
800 STREAM_GET(&announce, s, sizeof(announce));
801 ret = isis_ldp_sync_announce_update(announce);
802 break;
803 case LDP_RLFA_LABELS:
804 STREAM_GET(&rlfa, s, sizeof(rlfa));
805 isis_rlfa_process_ldp_response(&rlfa);
806 break;
807 default:
808 break;
809 }
810
811 stream_failure:
812
813 return ret;
814 }
815
816 static int isis_zebra_client_close_notify(ZAPI_CALLBACK_ARGS)
817 {
818 int ret = 0;
819
820 struct zapi_client_close_info info;
821
822 if (zapi_client_close_notify_decode(zclient->ibuf, &info) < 0)
823 return -1;
824
825 isis_ldp_sync_handle_client_close(&info);
826 isis_ldp_rlfa_handle_client_close(&info);
827
828 return ret;
829 }
830
831 static zclient_handler *const isis_handlers[] = {
832 [ZEBRA_ROUTER_ID_UPDATE] = isis_router_id_update_zebra,
833 [ZEBRA_INTERFACE_ADDRESS_ADD] = isis_zebra_if_address_add,
834 [ZEBRA_INTERFACE_ADDRESS_DELETE] = isis_zebra_if_address_del,
835 [ZEBRA_INTERFACE_LINK_PARAMS] = isis_zebra_link_params,
836 [ZEBRA_REDISTRIBUTE_ROUTE_ADD] = isis_zebra_read,
837 [ZEBRA_REDISTRIBUTE_ROUTE_DEL] = isis_zebra_read,
838
839 [ZEBRA_OPAQUE_MESSAGE] = isis_opaque_msg_handler,
840
841 [ZEBRA_CLIENT_CLOSE_NOTIFY] = isis_zebra_client_close_notify,
842 };
843
844 void isis_zebra_init(struct thread_master *master, int instance)
845 {
846 /* Initialize asynchronous zclient. */
847 zclient = zclient_new(master, &zclient_options_default, isis_handlers,
848 array_size(isis_handlers));
849 zclient_init(zclient, PROTO_TYPE, 0, &isisd_privs);
850 zclient->zebra_connected = isis_zebra_connected;
851
852 /* Initialize special zclient for synchronous message exchanges. */
853 struct zclient_options options = zclient_options_default;
854 options.synchronous = true;
855 zclient_sync = zclient_new(master, &options, NULL, 0);
856 zclient_sync->sock = -1;
857 zclient_sync->redist_default = ZEBRA_ROUTE_ISIS;
858 zclient_sync->instance = instance;
859 /*
860 * session_id must be different from default value (0) to distinguish
861 * the asynchronous socket from the synchronous one
862 */
863 zclient_sync->session_id = 1;
864 zclient_sync->privs = &isisd_privs;
865 }
866
867 void isis_zebra_stop(void)
868 {
869 zclient_unregister_opaque(zclient, LDP_RLFA_LABELS);
870 zclient_unregister_opaque(zclient, LDP_IGP_SYNC_IF_STATE_UPDATE);
871 zclient_unregister_opaque(zclient, LDP_IGP_SYNC_ANNOUNCE_UPDATE);
872 zclient_stop(zclient_sync);
873 zclient_free(zclient_sync);
874 zclient_stop(zclient);
875 zclient_free(zclient);
876 frr_fini();
877 }