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