]> git.proxmox.com Git - mirror_frr.git/blame - isisd/isis_zebra.c
Merge pull request #7443 from opensourcerouting/gcc-10-plugin-ice
[mirror_frr.git] / isisd / isis_zebra.c
CommitLineData
eb5d44eb 1/*
d62a17ae 2 * IS-IS Rout(e)ing protocol - isis_zebra.c
eb5d44eb 3 *
4 * Copyright (C) 2001,2002 Sampo Saaristo
d62a17ae 5 * Tampere University of Technology
eb5d44eb 6 * Institute of Communications Engineering
f3ccedaa 7 * Copyright (C) 2013-2015 Christian Franke <chris@opensourcerouting.org>
eb5d44eb 8 *
d62a17ae 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)
eb5d44eb 12 * any later version.
13 *
d62a17ae 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
eb5d44eb 17 * more details.
896014f4
DL
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
eb5d44eb 22 */
23
24#include <zebra.h>
eb5d44eb 25
26#include "thread.h"
27#include "command.h"
28#include "memory.h"
29#include "log.h"
363be4dd 30#include "lib_errors.h"
eb5d44eb 31#include "if.h"
32#include "network.h"
33#include "prefix.h"
34#include "zclient.h"
35#include "stream.h"
36#include "linklist.h"
f3ccedaa 37#include "nexthop.h"
7076bb2f 38#include "vrf.h"
8879bd22 39#include "libfrr.h"
eb5d44eb 40
41#include "isisd/isis_constants.h"
42#include "isisd/isis_common.h"
3f045a08
JB
43#include "isisd/isis_flags.h"
44#include "isisd/isis_misc.h"
45#include "isisd/isis_circuit.h"
c89c05dd 46#include "isisd/isisd.h"
eb5d44eb 47#include "isisd/isis_circuit.h"
48#include "isisd/isis_csm.h"
3f045a08 49#include "isisd/isis_lsp.h"
eb5d44eb 50#include "isisd/isis_route.h"
51#include "isisd/isis_zebra.h"
c3f7b406 52#include "isisd/isis_adjacency.h"
f8c06e2c 53#include "isisd/isis_te.h"
26f6acaf 54#include "isisd/isis_sr.h"
1cbf96a8 55#include "isisd/isis_ldp_sync.h"
eb5d44eb 56
26f6acaf
RW
57struct zclient *zclient;
58static struct zclient *zclient_sync;
59
18a6dce6 60/* Router-id update message from zebra. */
121f9dee 61static int isis_router_id_update_zebra(ZAPI_CALLBACK_ARGS)
18a6dce6 62{
d62a17ae 63 struct isis_area *area;
64 struct listnode *node;
65 struct prefix router_id;
eab88f36
K
66 struct isis *isis = NULL;
67
68 isis = isis_lookup_by_vrfid(vrf_id);
69
70 if (isis == NULL) {
71 return -1;
72 }
d62a17ae 73
d62a17ae 74 zebra_router_id_update_read(zclient->ibuf, &router_id);
75 if (isis->router_id == router_id.u.prefix4.s_addr)
76 return 0;
77
78 isis->router_id = router_id.u.prefix4.s_addr;
79 for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area))
80 if (listcount(area->area_addrs) > 0)
81 lsp_regenerate_schedule(area, area->is_type, 0);
82
83 return 0;
18a6dce6 84}
eb5d44eb 85
121f9dee 86static int isis_zebra_if_address_add(ZAPI_CALLBACK_ARGS)
eb5d44eb 87{
115f8f56 88 struct isis_circuit *circuit;
d62a17ae 89 struct connected *c;
eb5d44eb 90
d62a17ae 91 c = zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_ADD,
92 zclient->ibuf, vrf_id);
f390d2c7 93
d62a17ae 94 if (c == NULL)
95 return 0;
f390d2c7 96
62f30dcc 97#ifdef EXTREME_DEBUG
d62a17ae 98 if (p->family == AF_INET)
2dbe669b 99 zlog_debug("connected IP address %pFX", c->address);
d62a17ae 100 if (p->family == AF_INET6)
2dbe669b 101 zlog_debug("connected IPv6 address %pFX", c->address);
eb5d44eb 102#endif /* EXTREME_DEBUG */
115f8f56
IR
103
104 if (if_is_operative(c->ifp)) {
105 circuit = circuit_scan_by_ifp(c->ifp);
106 if (circuit)
107 isis_circuit_add_addr(circuit, c);
108 }
eb5d44eb 109
d62a17ae 110 return 0;
eb5d44eb 111}
112
121f9dee 113static int isis_zebra_if_address_del(ZAPI_CALLBACK_ARGS)
eb5d44eb 114{
115f8f56 115 struct isis_circuit *circuit;
d62a17ae 116 struct connected *c;
eb5d44eb 117
d62a17ae 118 c = zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_DELETE,
119 zclient->ibuf, vrf_id);
f390d2c7 120
d62a17ae 121 if (c == NULL)
122 return 0;
f390d2c7 123
f891f443 124#ifdef EXTREME_DEBUG
d62a17ae 125 if (p->family == AF_INET)
2dbe669b 126 zlog_debug("disconnected IP address %pFX", c->address);
d62a17ae 127 if (p->family == AF_INET6)
2dbe669b 128 zlog_debug("disconnected IPv6 address %pFX", c->address);
f891f443 129#endif /* EXTREME_DEBUG */
f390d2c7 130
115f8f56
IR
131 if (if_is_operative(c->ifp)) {
132 circuit = circuit_scan_by_ifp(c->ifp);
133 if (circuit)
134 isis_circuit_del_addr(circuit, c);
135 }
136
721c0857 137 connected_free(&c);
f390d2c7 138
d62a17ae 139 return 0;
eb5d44eb 140}
141
121f9dee 142static int isis_zebra_link_params(ZAPI_CALLBACK_ARGS)
f8c06e2c 143{
d62a17ae 144 struct interface *ifp;
f8c06e2c 145
edc12762 146 ifp = zebra_interface_link_params_read(zclient->ibuf, vrf_id);
f8c06e2c 147
d62a17ae 148 if (ifp == NULL)
149 return 0;
f8c06e2c 150
d62a17ae 151 /* Update TE TLV */
152 isis_mpls_te_update(ifp);
f8c06e2c 153
d62a17ae 154 return 0;
f8c06e2c
OD
155}
156
c951ee6e 157enum isis_zebra_nexthop_type {
d47d6089
RW
158 ISIS_NEXTHOP_MAIN = 0,
159 ISIS_NEXTHOP_BACKUP,
c951ee6e
RW
160};
161
162static int isis_zebra_add_nexthops(struct isis *isis, struct list *nexthops,
163 struct zapi_nexthop zapi_nexthops[],
164 enum isis_zebra_nexthop_type type,
d47d6089 165 bool mpls_lsp, uint8_t backup_nhs)
eb5d44eb 166{
d62a17ae 167 struct isis_nexthop *nexthop;
168 struct listnode *node;
c0721de4 169 int count = 0;
d62a17ae 170
f80dd32b 171 /* Nexthops */
c951ee6e
RW
172 for (ALL_LIST_ELEMENTS_RO(nexthops, node, nexthop)) {
173 struct zapi_nexthop *api_nh;
174
363be4dd
RW
175 if (count >= MULTIPATH_NUM)
176 break;
c951ee6e 177 api_nh = &zapi_nexthops[count];
363be4dd 178 if (fabricd)
68a02e06 179 SET_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_ONLINK);
dc18b3b0 180 api_nh->vrf_id = isis->vrf_id;
363be4dd
RW
181
182 switch (nexthop->family) {
183 case AF_INET:
f80dd32b 184 /* FIXME: can it be ? */
363be4dd 185 if (nexthop->ip.ipv4.s_addr != INADDR_ANY) {
f80dd32b 186 api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX;
363be4dd 187 api_nh->gate.ipv4 = nexthop->ip.ipv4;
f80dd32b
RW
188 } else {
189 api_nh->type = NEXTHOP_TYPE_IFINDEX;
190 }
363be4dd
RW
191 break;
192 case AF_INET6:
193 if (!IN6_IS_ADDR_LINKLOCAL(&nexthop->ip.ipv6)
194 && !IN6_IS_ADDR_UNSPECIFIED(&nexthop->ip.ipv6)) {
f80dd32b
RW
195 continue;
196 }
363be4dd 197 api_nh->gate.ipv6 = nexthop->ip.ipv6;
f80dd32b 198 api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX;
363be4dd
RW
199 break;
200 default:
201 flog_err(EC_LIB_DEVELOPMENT,
202 "%s: unknown address family [%d]", __func__,
203 nexthop->family);
204 exit(1);
d62a17ae 205 }
363be4dd
RW
206
207 api_nh->ifindex = nexthop->ifindex;
c951ee6e
RW
208
209 /* Add MPLS label(s). */
210 switch (type) {
d47d6089
RW
211 case ISIS_NEXTHOP_MAIN:
212 if (nexthop->sr.present) {
c951ee6e
RW
213 api_nh->label_num = 1;
214 api_nh->labels[0] = nexthop->sr.label;
d47d6089
RW
215 } else if (mpls_lsp)
216 /*
217 * Do not use non-SR enabled nexthops to prevent
218 * broken LSPs from being formed.
219 */
220 continue;
c951ee6e 221 break;
d47d6089 222 case ISIS_NEXTHOP_BACKUP:
c951ee6e
RW
223 if (nexthop->label_stack) {
224 api_nh->label_num =
225 nexthop->label_stack->num_labels;
226 memcpy(api_nh->labels,
227 nexthop->label_stack->label,
228 sizeof(mpls_label_t)
229 * api_nh->label_num);
d47d6089
RW
230 } else if (mpls_lsp) {
231 /*
232 * This is necessary because zebra requires
233 * the nexthops of MPLS LSPs to be labeled.
234 */
c951ee6e
RW
235 api_nh->label_num = 1;
236 api_nh->labels[0] = MPLS_LABEL_IMPLICIT_NULL;
237 }
238 break;
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 }
363be4dd 253 count++;
d62a17ae 254 }
c951ee6e
RW
255
256 return count;
257}
258
259void 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
d47d6089 266 if (zclient->sock < 0 || list_isempty(route_info->nexthops))
c0721de4 267 return;
f390d2c7 268
c951ee6e
RW
269 memset(&api, 0, sizeof(api));
270 api.vrf_id = isis->vrf_id;
271 api.type = PROTO_TYPE;
272 api.safi = SAFI_UNICAST;
273 api.prefix = *prefix;
274 if (src_p && src_p->prefixlen) {
275 api.src_prefix = *src_p;
276 SET_FLAG(api.message, ZAPI_MESSAGE_SRCPFX);
277 }
278 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
279 SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
280 api.metric = route_info->cost;
281
282 /* Add backup nexthops first. */
283 if (route_info->backup) {
284 count = isis_zebra_add_nexthops(
285 isis, route_info->backup->nexthops, api.backup_nexthops,
d47d6089 286 ISIS_NEXTHOP_BACKUP, false, 0);
c951ee6e
RW
287 if (count > 0) {
288 SET_FLAG(api.message, ZAPI_MESSAGE_BACKUP_NEXTHOPS);
289 api.backup_nexthop_num = count;
290 }
291 }
292
293 /* Add primary nexthops. */
294 count = isis_zebra_add_nexthops(isis, route_info->nexthops,
d47d6089 295 api.nexthops, ISIS_NEXTHOP_MAIN, false,
c951ee6e
RW
296 count);
297 if (!count)
298 return;
c0721de4 299 api.nexthop_num = count;
f390d2c7 300
c0721de4 301 zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api);
eb5d44eb 302}
303
dc18b3b0
K
304void isis_zebra_route_del_route(struct isis *isis,
305 struct prefix *prefix,
0a5f3f4f
RW
306 struct prefix_ipv6 *src_p,
307 struct isis_route_info *route_info)
eb5d44eb 308{
c0721de4 309 struct zapi_route api;
d62a17ae 310
0a5f3f4f 311 if (zclient->sock < 0)
d62a17ae 312 return;
313
c0721de4 314 memset(&api, 0, sizeof(api));
dc18b3b0 315 api.vrf_id = isis->vrf_id;
7c0cbd0e 316 api.type = PROTO_TYPE;
d62a17ae 317 api.safi = SAFI_UNICAST;
c0721de4 318 api.prefix = *prefix;
321c1bbb
CF
319 if (src_p && src_p->prefixlen) {
320 api.src_prefix = *src_p;
321 SET_FLAG(api.message, ZAPI_MESSAGE_SRCPFX);
322 }
f390d2c7 323
c0721de4 324 zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api);
eb5d44eb 325}
326
f2333421 327/**
d47d6089 328 * Install Prefix-SID label entry in the forwarding plane through Zebra.
f2333421 329 *
d47d6089
RW
330 * @param area IS-IS area
331 * @param prefix Route prefix
332 * @param rinfo Route information
333 * @param psid Prefix-SID information
f2333421 334 */
d47d6089
RW
335void isis_zebra_prefix_sid_install(struct isis_area *area,
336 struct prefix *prefix,
337 struct isis_route_info *rinfo,
338 struct isis_sr_psid_info *psid)
26f6acaf
RW
339{
340 struct zapi_labels zl;
c951ee6e 341 int count = 0;
26f6acaf 342
d47d6089
RW
343 sr_debug("ISIS-Sr (%s): update label %u for prefix %pFX",
344 area->area_tag, psid->label, prefix);
345
26f6acaf
RW
346 /* Prepare message. */
347 memset(&zl, 0, sizeof(zl));
348 zl.type = ZEBRA_LSP_ISIS_SR;
d47d6089
RW
349 zl.local_label = psid->label;
350
351 /* Local routes don't have any nexthop and require special handling. */
352 if (list_isempty(rinfo->nexthops)) {
353 struct zapi_nexthop *znh;
354 struct interface *ifp;
26f6acaf 355
26f6acaf
RW
356 ifp = if_lookup_by_name("lo", VRF_DEFAULT);
357 if (!ifp) {
358 zlog_warn(
359 "%s: couldn't install Prefix-SID %pFX: loopback interface not found",
d47d6089 360 __func__, prefix);
26f6acaf
RW
361 return;
362 }
363
364 znh = &zl.nexthops[zl.nexthop_num++];
365 znh->type = NEXTHOP_TYPE_IFINDEX;
366 znh->ifindex = ifp->ifindex;
e0e8a84f
OD
367 znh->label_num = 1;
368 znh->labels[0] = MPLS_LABEL_IMPLICIT_NULL;
d47d6089 369 } else {
c951ee6e
RW
370 /* Add backup nexthops first. */
371 if (rinfo->backup) {
372 count = isis_zebra_add_nexthops(
d47d6089
RW
373 area->isis, rinfo->backup->nexthops,
374 zl.backup_nexthops, ISIS_NEXTHOP_BACKUP, true,
c951ee6e
RW
375 0);
376 if (count > 0) {
377 SET_FLAG(zl.message, ZAPI_LABELS_HAS_BACKUPS);
378 zl.backup_nexthop_num = count;
379 }
26f6acaf 380 }
c951ee6e
RW
381
382 /* Add primary nexthops. */
d47d6089
RW
383 count = isis_zebra_add_nexthops(area->isis, rinfo->nexthops,
384 zl.nexthops, ISIS_NEXTHOP_MAIN,
385 true, count);
c951ee6e
RW
386 if (!count)
387 return;
388 zl.nexthop_num = count;
26f6acaf
RW
389 }
390
391 /* Send message to zebra. */
392 (void)zebra_send_mpls_labels(zclient, ZEBRA_MPLS_LABELS_REPLACE, &zl);
393}
394
f2333421 395/**
d47d6089 396 * Uninstall Prefix-SID label entry from the forwarding plane through Zebra.
f2333421 397 *
d47d6089
RW
398 * @param area IS-IS area
399 * @param prefix Route prefix
400 * @param rinfo Route information
401 * @param psid Prefix-SID information
f2333421 402 */
d47d6089
RW
403void isis_zebra_prefix_sid_uninstall(struct isis_area *area,
404 struct prefix *prefix,
405 struct isis_route_info *rinfo,
406 struct isis_sr_psid_info *psid)
26f6acaf
RW
407{
408 struct zapi_labels zl;
409
d47d6089
RW
410 sr_debug("ISIS-Sr (%s): delete label %u for prefix %pFX",
411 area->area_tag, psid->label, prefix);
412
26f6acaf
RW
413 /* Prepare message. */
414 memset(&zl, 0, sizeof(zl));
415 zl.type = ZEBRA_LSP_ISIS_SR;
d47d6089 416 zl.local_label = psid->label;
26f6acaf
RW
417
418 /* Send message to zebra. */
419 (void)zebra_send_mpls_labels(zclient, ZEBRA_MPLS_LABELS_DELETE, &zl);
420}
421
f2333421
OD
422/**
423 * Send (LAN)-Adjacency-SID to ZEBRA for installation or deletion.
424 *
425 * @param cmd ZEBRA_MPLS_LABELS_ADD or ZEBRA_ROUTE_DELETE
426 * @param sra Segment Routing Adjacency-SID
427 */
c3f7b406
OD
428void isis_zebra_send_adjacency_sid(int cmd, const struct sr_adjacency *sra)
429{
054fda12 430 struct isis *isis = sra->adj->circuit->area->isis;
c3f7b406
OD
431 struct zapi_labels zl;
432 struct zapi_nexthop *znh;
433
434 if (cmd != ZEBRA_MPLS_LABELS_ADD && cmd != ZEBRA_MPLS_LABELS_DELETE) {
435 flog_warn(EC_LIB_DEVELOPMENT, "%s: wrong ZEBRA command",
436 __func__);
437 return;
438 }
439
440 sr_debug(" |- %s label %u for interface %s",
441 cmd == ZEBRA_MPLS_LABELS_ADD ? "Add" : "Delete",
054fda12 442 sra->input_label, sra->adj->circuit->interface->name);
c3f7b406
OD
443
444 memset(&zl, 0, sizeof(zl));
445 zl.type = ZEBRA_LSP_ISIS_SR;
054fda12 446 zl.local_label = sra->input_label;
c3f7b406
OD
447 zl.nexthop_num = 1;
448 znh = &zl.nexthops[0];
449 znh->gate = sra->nexthop.address;
450 znh->type = (sra->nexthop.family == AF_INET)
451 ? NEXTHOP_TYPE_IPV4_IFINDEX
452 : NEXTHOP_TYPE_IPV6_IFINDEX;
453 znh->ifindex = sra->adj->circuit->interface->ifindex;
454 znh->label_num = 1;
455 znh->labels[0] = MPLS_LABEL_IMPLICIT_NULL;
456
054fda12
RW
457 /* Set backup nexthops. */
458 if (sra->type == ISIS_SR_LAN_BACKUP) {
459 int count;
460
461 count = isis_zebra_add_nexthops(isis, sra->backup_nexthops,
462 zl.backup_nexthops,
d47d6089 463 ISIS_NEXTHOP_BACKUP, true, 0);
054fda12
RW
464 if (count > 0) {
465 SET_FLAG(zl.message, ZAPI_LABELS_HAS_BACKUPS);
466 zl.backup_nexthop_num = count;
467
468 SET_FLAG(znh->flags, ZAPI_NEXTHOP_FLAG_HAS_BACKUP);
469 znh->backup_num = count;
470 for (int i = 0; i < count; i++)
471 znh->backup_idx[i] = i;
472 }
473 }
474
c3f7b406
OD
475 (void)zebra_send_mpls_labels(zclient, cmd, &zl);
476}
477
121f9dee 478static int isis_zebra_read(ZAPI_CALLBACK_ARGS)
eb5d44eb 479{
74489921 480 struct zapi_route api;
eab88f36
K
481 struct isis *isis = NULL;
482
483 isis = isis_lookup_by_vrfid(vrf_id);
484
485 if (isis == NULL)
486 return -1;
d62a17ae 487
74489921
RW
488 if (zapi_route_decode(zclient->ibuf, &api) < 0)
489 return -1;
d62a17ae 490
9fb2b879
DS
491 if (api.prefix.family == AF_INET6
492 && IN6_IS_ADDR_LINKLOCAL(&api.prefix.u.prefix6))
493 return 0;
494
d62a17ae 495 /*
496 * Avoid advertising a false default reachability. (A default
497 * route installed by IS-IS gets redistributed from zebra back
498 * into IS-IS causing us to start advertising default reachabity
499 * without this check)
500 */
d43d2df5
CF
501 if (api.prefix.prefixlen == 0
502 && api.src_prefix.prefixlen == 0
7c0cbd0e 503 && api.type == PROTO_TYPE) {
121f9dee 504 cmd = ZEBRA_REDISTRIBUTE_ROUTE_DEL;
d43d2df5 505 }
d62a17ae 506
121f9dee 507 if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_ADD)
eab88f36 508 isis_redist_add(isis, api.type, &api.prefix, &api.src_prefix,
d43d2df5 509 api.distance, api.metric);
d62a17ae 510 else
eab88f36
K
511 isis_redist_delete(isis, api.type, &api.prefix,
512 &api.src_prefix);
d62a17ae 513
514 return 0;
eb5d44eb 515}
eb5d44eb 516
d62a17ae 517int isis_distribute_list_update(int routetype)
eb5d44eb 518{
d62a17ae 519 return 0;
eb5d44eb 520}
521
d62a17ae 522void isis_zebra_redistribute_set(afi_t afi, int type)
eb5d44eb 523{
d62a17ae 524 if (type == DEFAULT_ROUTE)
525 zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_ADD,
49db7a7b 526 zclient, afi, VRF_DEFAULT);
d62a17ae 527 else
528 zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, afi, type,
529 0, VRF_DEFAULT);
f3ccedaa
CF
530}
531
d62a17ae 532void isis_zebra_redistribute_unset(afi_t afi, int type)
f3ccedaa 533{
d62a17ae 534 if (type == DEFAULT_ROUTE)
535 zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_DELETE,
49db7a7b 536 zclient, afi, VRF_DEFAULT);
d62a17ae 537 else
538 zclient_redistribute(ZEBRA_REDISTRIBUTE_DELETE, zclient, afi,
539 type, 0, VRF_DEFAULT);
eb5d44eb 540}
541
774e3570
OD
542/* Label Manager Functions */
543
58fbcdf2
OD
544/**
545 * Check if Label Manager is Ready or not.
546 *
547 * @return True if Label Manager is ready, False otherwise
548 */
549bool isis_zebra_label_manager_ready(void)
550{
551 return (zclient_sync->sock > 0);
552}
553
774e3570
OD
554/**
555 * Request Label Range to the Label Manager.
556 *
557 * @param base base label of the label range to request
558 * @param chunk_size size of the label range to request
559 *
560 * @return 0 on success, -1 on failure
561 */
26f6acaf
RW
562int isis_zebra_request_label_range(uint32_t base, uint32_t chunk_size)
563{
564 int ret;
565 uint32_t start, end;
566
58fbcdf2
OD
567 if (zclient_sync->sock < 0)
568 return -1;
26f6acaf
RW
569
570 ret = lm_get_label_chunk(zclient_sync, 0, base, chunk_size, &start,
571 &end);
572 if (ret < 0) {
573 zlog_warn("%s: error getting label range!", __func__);
574 return -1;
575 }
576
577 return 0;
578}
579
774e3570
OD
580/**
581 * Release Label Range to the Label Manager.
582 *
583 * @param start start of label range to release
584 * @param end end of label range to release
774e3570 585 *
58fbcdf2 586 * @return 0 on success, -1 otherwise
774e3570 587 */
58fbcdf2 588int isis_zebra_release_label_range(uint32_t start, uint32_t end)
26f6acaf
RW
589{
590 int ret;
26f6acaf 591
58fbcdf2 592 if (zclient_sync->sock < 0)
26f6acaf 593 return -1;
26f6acaf
RW
594
595 ret = lm_release_label_chunk(zclient_sync, start, end);
596 if (ret < 0) {
26f6acaf 597 zlog_warn("%s: error releasing label range!", __func__);
26f6acaf
RW
598 return -1;
599 }
600
601 return 0;
602}
603
774e3570
OD
604/**
605 * Connect to the Label Manager.
58fbcdf2
OD
606 *
607 * @return 0 on success, -1 otherwise
774e3570 608 */
58fbcdf2 609int isis_zebra_label_manager_connect(void)
26f6acaf
RW
610{
611 /* Connect to label manager. */
58fbcdf2
OD
612 if (zclient_socket_connect(zclient_sync) < 0) {
613 zlog_warn("%s: failed connecting synchronous zclient!",
26f6acaf 614 __func__);
58fbcdf2 615 return -1;
26f6acaf 616 }
774e3570 617 /* make socket non-blocking */
26f6acaf 618 set_nonblocking(zclient_sync->sock);
774e3570
OD
619
620 /* Send hello to notify zebra this is a synchronous client */
58fbcdf2
OD
621 if (zclient_send_hello(zclient_sync) < 0) {
622 zlog_warn("%s: failed sending hello for synchronous zclient!",
623 __func__);
624 close(zclient_sync->sock);
625 zclient_sync->sock = -1;
626 return -1;
774e3570
OD
627 }
628
629 /* Connect to label manager */
58fbcdf2
OD
630 if (lm_label_manager_connect(zclient_sync, 0) != 0) {
631 zlog_warn("%s: failed connecting to label manager!", __func__);
632 if (zclient_sync->sock > 0) {
633 close(zclient_sync->sock);
634 zclient_sync->sock = -1;
635 }
636 return -1;
26f6acaf
RW
637 }
638
58fbcdf2
OD
639 sr_debug("ISIS-Sr: Successfully connected to the Label Manager");
640
641 return 0;
26f6acaf
RW
642}
643
65251ce8 644void isis_zebra_vrf_register(struct isis *isis)
645{
646 if (!zclient || zclient->sock < 0 || !isis)
647 return;
648
649 if (isis->vrf_id != VRF_UNKNOWN) {
650 if (IS_DEBUG_EVENTS)
651 zlog_debug("%s: Register VRF %s id %u", __func__,
652 isis->name, isis->vrf_id);
653 zclient_send_reg_requests(zclient, isis->vrf_id);
654 }
655}
656
657
d62a17ae 658static void isis_zebra_connected(struct zclient *zclient)
7076bb2f 659{
d62a17ae 660 zclient_send_reg_requests(zclient, VRF_DEFAULT);
7076bb2f
FL
661}
662
1cbf96a8 663/*
664 * opaque messages between processes
665 */
666static int isis_opaque_msg_handler(ZAPI_CALLBACK_ARGS)
667{
668 struct stream *s;
669 struct zapi_opaque_msg info;
670 struct ldp_igp_sync_if_state state;
671 struct ldp_igp_sync_announce announce;
672 struct ldp_igp_sync_hello hello;
673 int ret = 0;
674
675 s = zclient->ibuf;
676 if (zclient_opaque_decode(s, &info) != 0)
677 return -1;
678
679 switch (info.type) {
680 case LDP_IGP_SYNC_IF_STATE_UPDATE:
681 STREAM_GET(&state, s, sizeof(state));
682 ret = isis_ldp_sync_state_update(state);
683 break;
684 case LDP_IGP_SYNC_ANNOUNCE_UPDATE:
685 STREAM_GET(&announce, s, sizeof(announce));
686 ret = isis_ldp_sync_announce_update(announce);
687 break;
688 case LDP_IGP_SYNC_HELLO_UPDATE:
689 STREAM_GET(&hello, s, sizeof(hello));
690 ret = isis_ldp_sync_hello_update(hello);
691 break;
692 default:
693 break;
694 }
695
696stream_failure:
697
698 return ret;
699}
700
26f6acaf 701void isis_zebra_init(struct thread_master *master, int instance)
eb5d44eb 702{
26f6acaf 703 /* Initialize asynchronous zclient. */
26f63a1e 704 zclient = zclient_new(master, &zclient_options_default);
7c0cbd0e 705 zclient_init(zclient, PROTO_TYPE, 0, &isisd_privs);
d62a17ae 706 zclient->zebra_connected = isis_zebra_connected;
707 zclient->router_id_update = isis_router_id_update_zebra;
d62a17ae 708 zclient->interface_address_add = isis_zebra_if_address_add;
709 zclient->interface_address_delete = isis_zebra_if_address_del;
710 zclient->interface_link_params = isis_zebra_link_params;
74489921
RW
711 zclient->redistribute_route_add = isis_zebra_read;
712 zclient->redistribute_route_del = isis_zebra_read;
d62a17ae 713
26f6acaf 714 /* Initialize special zclient for synchronous message exchanges. */
774e3570
OD
715 struct zclient_options options = zclient_options_default;
716 options.synchronous = true;
717 zclient_sync = zclient_new(master, &options);
26f6acaf
RW
718 zclient_sync->sock = -1;
719 zclient_sync->redist_default = ZEBRA_ROUTE_ISIS;
720 zclient_sync->instance = instance;
774e3570
OD
721 /*
722 * session_id must be different from default value (0) to distinguish
723 * the asynchronous socket from the synchronous one
724 */
725 zclient_sync->session_id = 1;
26f6acaf 726 zclient_sync->privs = &isisd_privs;
1cbf96a8 727
728 zclient->opaque_msg_handler = isis_opaque_msg_handler;
eb5d44eb 729}
8d429559 730
d62a17ae 731void isis_zebra_stop(void)
8d429559 732{
58fbcdf2
OD
733 zclient_stop(zclient_sync);
734 zclient_free(zclient_sync);
d62a17ae 735 zclient_stop(zclient);
736 zclient_free(zclient);
8879bd22 737 frr_fini();
8d429559 738}