1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * IS-IS Rout(e)ing protocol - isis_zebra.c
5 * Copyright (C) 2001,2002 Sampo Saaristo
6 * Tampere University of Technology
7 * Institute of Communications Engineering
8 * Copyright (C) 2013-2015 Christian Franke <chris@opensourcerouting.org>
17 #include "lib_errors.h"
28 #include "link_state.h"
30 #include "isisd/isis_constants.h"
31 #include "isisd/isis_common.h"
32 #include "isisd/isis_flags.h"
33 #include "isisd/isis_misc.h"
34 #include "isisd/isis_circuit.h"
35 #include "isisd/isisd.h"
36 #include "isisd/isis_circuit.h"
37 #include "isisd/isis_csm.h"
38 #include "isisd/isis_lsp.h"
39 #include "isisd/isis_spf.h"
40 #include "isisd/isis_spf_private.h"
41 #include "isisd/isis_route.h"
42 #include "isisd/isis_zebra.h"
43 #include "isisd/isis_adjacency.h"
44 #include "isisd/isis_te.h"
45 #include "isisd/isis_sr.h"
46 #include "isisd/isis_ldp_sync.h"
48 struct zclient
*zclient
;
49 static struct zclient
*zclient_sync
;
51 /* Router-id update message from zebra. */
52 static int isis_router_id_update_zebra(ZAPI_CALLBACK_ARGS
)
54 struct isis_area
*area
;
55 struct listnode
*node
;
56 struct prefix router_id
;
57 struct isis
*isis
= NULL
;
59 isis
= isis_lookup_by_vrfid(vrf_id
);
65 zebra_router_id_update_read(zclient
->ibuf
, &router_id
);
66 if (isis
->router_id
== router_id
.u
.prefix4
.s_addr
)
69 isis
->router_id
= router_id
.u
.prefix4
.s_addr
;
70 for (ALL_LIST_ELEMENTS_RO(isis
->area_list
, node
, area
))
71 if (listcount(area
->area_addrs
) > 0)
72 lsp_regenerate_schedule(area
, area
->is_type
, 0);
77 static int isis_zebra_if_address_add(ZAPI_CALLBACK_ARGS
)
79 struct isis_circuit
*circuit
;
82 c
= zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_ADD
,
83 zclient
->ibuf
, vrf_id
);
89 if (c
->address
->family
== AF_INET
)
90 zlog_debug("connected IP address %pFX", c
->address
);
91 if (c
->address
->family
== AF_INET6
)
92 zlog_debug("connected IPv6 address %pFX", c
->address
);
93 #endif /* EXTREME_DEBUG */
95 if (if_is_operative(c
->ifp
)) {
96 circuit
= circuit_scan_by_ifp(c
->ifp
);
98 isis_circuit_add_addr(circuit
, c
);
104 static int isis_zebra_if_address_del(ZAPI_CALLBACK_ARGS
)
106 struct isis_circuit
*circuit
;
109 c
= zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_DELETE
,
110 zclient
->ibuf
, vrf_id
);
116 if (c
->address
->family
== AF_INET
)
117 zlog_debug("disconnected IP address %pFX", c
->address
);
118 if (c
->address
->family
== AF_INET6
)
119 zlog_debug("disconnected IPv6 address %pFX", c
->address
);
120 #endif /* EXTREME_DEBUG */
122 if (if_is_operative(c
->ifp
)) {
123 circuit
= circuit_scan_by_ifp(c
->ifp
);
125 isis_circuit_del_addr(circuit
, c
);
133 static int isis_zebra_link_params(ZAPI_CALLBACK_ARGS
)
135 struct interface
*ifp
;
136 bool changed
= false;
138 ifp
= zebra_interface_link_params_read(zclient
->ibuf
, vrf_id
, &changed
);
140 if (ifp
== NULL
|| !changed
)
144 isis_mpls_te_update(ifp
);
149 enum isis_zebra_nexthop_type
{
150 ISIS_NEXTHOP_MAIN
= 0,
154 static int isis_zebra_add_nexthops(struct isis
*isis
, struct list
*nexthops
,
155 struct zapi_nexthop zapi_nexthops
[],
156 enum isis_zebra_nexthop_type type
,
157 bool mpls_lsp
, uint8_t backup_nhs
)
159 struct isis_nexthop
*nexthop
;
160 struct listnode
*node
;
164 for (ALL_LIST_ELEMENTS_RO(nexthops
, node
, nexthop
)) {
165 struct zapi_nexthop
*api_nh
;
167 if (count
>= MULTIPATH_NUM
)
169 api_nh
= &zapi_nexthops
[count
];
171 SET_FLAG(api_nh
->flags
, ZAPI_NEXTHOP_FLAG_ONLINK
);
172 api_nh
->vrf_id
= isis
->vrf_id
;
174 switch (nexthop
->family
) {
176 /* FIXME: can it be ? */
177 if (nexthop
->ip
.ipv4
.s_addr
!= INADDR_ANY
) {
178 api_nh
->type
= NEXTHOP_TYPE_IPV4_IFINDEX
;
179 api_nh
->gate
.ipv4
= nexthop
->ip
.ipv4
;
181 api_nh
->type
= NEXTHOP_TYPE_IFINDEX
;
185 if (!IN6_IS_ADDR_LINKLOCAL(&nexthop
->ip
.ipv6
)
186 && !IN6_IS_ADDR_UNSPECIFIED(&nexthop
->ip
.ipv6
)) {
189 api_nh
->gate
.ipv6
= nexthop
->ip
.ipv6
;
190 api_nh
->type
= NEXTHOP_TYPE_IPV6_IFINDEX
;
193 flog_err(EC_LIB_DEVELOPMENT
,
194 "%s: unknown address family [%d]", __func__
,
199 api_nh
->ifindex
= nexthop
->ifindex
;
201 /* Add MPLS label(s). */
202 if (nexthop
->label_stack
) {
203 api_nh
->label_num
= nexthop
->label_stack
->num_labels
;
204 memcpy(api_nh
->labels
, nexthop
->label_stack
->label
,
205 sizeof(mpls_label_t
) * api_nh
->label_num
);
206 } else if (nexthop
->sr
.present
) {
207 api_nh
->label_num
= 1;
208 api_nh
->labels
[0] = nexthop
->sr
.label
;
209 } else if (mpls_lsp
) {
211 case ISIS_NEXTHOP_MAIN
:
213 * Do not use non-SR enabled nexthops to prevent
214 * broken LSPs from being formed.
217 case ISIS_NEXTHOP_BACKUP
:
219 * This is necessary because zebra requires
220 * the nexthops of MPLS LSPs to be labeled.
222 api_nh
->label_num
= 1;
223 api_nh
->labels
[0] = MPLS_LABEL_IMPLICIT_NULL
;
228 /* Backup nexthop handling. */
230 SET_FLAG(api_nh
->flags
, ZAPI_NEXTHOP_FLAG_HAS_BACKUP
);
232 * If the backup has multiple nexthops, all of them
233 * protect the same primary nexthop since ECMP routes
236 api_nh
->backup_num
= backup_nhs
;
237 for (int i
= 0; i
< backup_nhs
; i
++)
238 api_nh
->backup_idx
[i
] = i
;
246 void isis_zebra_route_add_route(struct isis
*isis
, struct prefix
*prefix
,
247 struct prefix_ipv6
*src_p
,
248 struct isis_route_info
*route_info
)
250 struct zapi_route api
;
253 if (zclient
->sock
< 0)
256 /* Uninstall the route if it doesn't have any valid nexthop. */
257 if (list_isempty(route_info
->nexthops
)) {
258 isis_zebra_route_del_route(isis
, prefix
, src_p
, route_info
);
262 memset(&api
, 0, sizeof(api
));
263 api
.vrf_id
= isis
->vrf_id
;
264 api
.type
= PROTO_TYPE
;
265 api
.safi
= SAFI_UNICAST
;
266 api
.prefix
= *prefix
;
267 if (src_p
&& src_p
->prefixlen
) {
268 api
.src_prefix
= *src_p
;
269 SET_FLAG(api
.message
, ZAPI_MESSAGE_SRCPFX
);
271 SET_FLAG(api
.message
, ZAPI_MESSAGE_NEXTHOP
);
272 SET_FLAG(api
.message
, ZAPI_MESSAGE_METRIC
);
273 api
.metric
= route_info
->cost
;
275 /* Add backup nexthops first. */
276 if (route_info
->backup
) {
277 count
= isis_zebra_add_nexthops(
278 isis
, route_info
->backup
->nexthops
, api
.backup_nexthops
,
279 ISIS_NEXTHOP_BACKUP
, false, 0);
281 SET_FLAG(api
.message
, ZAPI_MESSAGE_BACKUP_NEXTHOPS
);
282 api
.backup_nexthop_num
= count
;
286 /* Add primary nexthops. */
287 count
= isis_zebra_add_nexthops(isis
, route_info
->nexthops
,
288 api
.nexthops
, ISIS_NEXTHOP_MAIN
, false,
292 api
.nexthop_num
= count
;
294 zclient_route_send(ZEBRA_ROUTE_ADD
, zclient
, &api
);
297 void isis_zebra_route_del_route(struct isis
*isis
,
298 struct prefix
*prefix
,
299 struct prefix_ipv6
*src_p
,
300 struct isis_route_info
*route_info
)
302 struct zapi_route api
;
304 if (zclient
->sock
< 0)
307 memset(&api
, 0, sizeof(api
));
308 api
.vrf_id
= isis
->vrf_id
;
309 api
.type
= PROTO_TYPE
;
310 api
.safi
= SAFI_UNICAST
;
311 api
.prefix
= *prefix
;
312 if (src_p
&& src_p
->prefixlen
) {
313 api
.src_prefix
= *src_p
;
314 SET_FLAG(api
.message
, ZAPI_MESSAGE_SRCPFX
);
317 zclient_route_send(ZEBRA_ROUTE_DELETE
, zclient
, &api
);
321 * Install Prefix-SID label entry in the forwarding plane through Zebra.
323 * @param area IS-IS area
324 * @param prefix Route prefix
325 * @param rinfo Route information
326 * @param psid Prefix-SID information
328 void isis_zebra_prefix_sid_install(struct isis_area
*area
,
329 struct prefix
*prefix
,
330 struct isis_route_info
*rinfo
,
331 struct isis_sr_psid_info
*psid
)
333 struct zapi_labels zl
;
336 sr_debug("ISIS-Sr (%s): update label %u for prefix %pFX",
337 area
->area_tag
, psid
->label
, prefix
);
339 /* Prepare message. */
340 memset(&zl
, 0, sizeof(zl
));
341 zl
.type
= ZEBRA_LSP_ISIS_SR
;
342 zl
.local_label
= psid
->label
;
344 /* Local routes don't have any nexthop and require special handling. */
345 if (list_isempty(rinfo
->nexthops
)) {
346 struct zapi_nexthop
*znh
;
347 struct interface
*ifp
;
349 ifp
= if_lookup_by_name("lo", VRF_DEFAULT
);
352 "%s: couldn't install Prefix-SID %pFX: loopback interface not found",
357 znh
= &zl
.nexthops
[zl
.nexthop_num
++];
358 znh
->type
= NEXTHOP_TYPE_IFINDEX
;
359 znh
->ifindex
= ifp
->ifindex
;
361 znh
->labels
[0] = MPLS_LABEL_IMPLICIT_NULL
;
363 /* Add backup nexthops first. */
365 count
= isis_zebra_add_nexthops(
366 area
->isis
, rinfo
->backup
->nexthops
,
367 zl
.backup_nexthops
, ISIS_NEXTHOP_BACKUP
, true,
370 SET_FLAG(zl
.message
, ZAPI_LABELS_HAS_BACKUPS
);
371 zl
.backup_nexthop_num
= count
;
375 /* Add primary nexthops. */
376 count
= isis_zebra_add_nexthops(area
->isis
, rinfo
->nexthops
,
377 zl
.nexthops
, ISIS_NEXTHOP_MAIN
,
381 zl
.nexthop_num
= count
;
384 /* Send message to zebra. */
385 (void)zebra_send_mpls_labels(zclient
, ZEBRA_MPLS_LABELS_REPLACE
, &zl
);
389 * Uninstall Prefix-SID label entry from the forwarding plane through Zebra.
391 * @param area IS-IS area
392 * @param prefix Route prefix
393 * @param rinfo Route information
394 * @param psid Prefix-SID information
396 void isis_zebra_prefix_sid_uninstall(struct isis_area
*area
,
397 struct prefix
*prefix
,
398 struct isis_route_info
*rinfo
,
399 struct isis_sr_psid_info
*psid
)
401 struct zapi_labels zl
;
403 sr_debug("ISIS-Sr (%s): delete label %u for prefix %pFX",
404 area
->area_tag
, psid
->label
, prefix
);
406 /* Prepare message. */
407 memset(&zl
, 0, sizeof(zl
));
408 zl
.type
= ZEBRA_LSP_ISIS_SR
;
409 zl
.local_label
= psid
->label
;
411 /* Send message to zebra. */
412 (void)zebra_send_mpls_labels(zclient
, ZEBRA_MPLS_LABELS_DELETE
, &zl
);
416 * Send (LAN)-Adjacency-SID to ZEBRA for installation or deletion.
418 * @param cmd ZEBRA_MPLS_LABELS_ADD or ZEBRA_ROUTE_DELETE
419 * @param sra Segment Routing Adjacency-SID
421 void isis_zebra_send_adjacency_sid(int cmd
, const struct sr_adjacency
*sra
)
423 struct isis
*isis
= sra
->adj
->circuit
->area
->isis
;
424 struct zapi_labels zl
;
425 struct zapi_nexthop
*znh
;
427 if (cmd
!= ZEBRA_MPLS_LABELS_ADD
&& cmd
!= ZEBRA_MPLS_LABELS_DELETE
) {
428 flog_warn(EC_LIB_DEVELOPMENT
, "%s: wrong ZEBRA command",
433 sr_debug(" |- %s label %u for interface %s",
434 cmd
== ZEBRA_MPLS_LABELS_ADD
? "Add" : "Delete",
435 sra
->input_label
, sra
->adj
->circuit
->interface
->name
);
437 memset(&zl
, 0, sizeof(zl
));
438 zl
.type
= ZEBRA_LSP_ISIS_SR
;
439 zl
.local_label
= sra
->input_label
;
441 znh
= &zl
.nexthops
[0];
442 znh
->gate
= sra
->nexthop
.address
;
443 znh
->type
= (sra
->nexthop
.family
== AF_INET
)
444 ? NEXTHOP_TYPE_IPV4_IFINDEX
445 : NEXTHOP_TYPE_IPV6_IFINDEX
;
446 znh
->ifindex
= sra
->adj
->circuit
->interface
->ifindex
;
448 znh
->labels
[0] = MPLS_LABEL_IMPLICIT_NULL
;
450 /* Set backup nexthops. */
451 if (sra
->type
== ISIS_SR_LAN_BACKUP
) {
454 count
= isis_zebra_add_nexthops(isis
, sra
->backup_nexthops
,
456 ISIS_NEXTHOP_BACKUP
, true, 0);
458 SET_FLAG(zl
.message
, ZAPI_LABELS_HAS_BACKUPS
);
459 zl
.backup_nexthop_num
= count
;
461 SET_FLAG(znh
->flags
, ZAPI_NEXTHOP_FLAG_HAS_BACKUP
);
462 znh
->backup_num
= count
;
463 for (int i
= 0; i
< count
; i
++)
464 znh
->backup_idx
[i
] = i
;
468 (void)zebra_send_mpls_labels(zclient
, cmd
, &zl
);
471 static int isis_zebra_read(ZAPI_CALLBACK_ARGS
)
473 struct zapi_route api
;
474 struct isis
*isis
= NULL
;
476 isis
= isis_lookup_by_vrfid(vrf_id
);
481 if (zapi_route_decode(zclient
->ibuf
, &api
) < 0)
484 if (api
.prefix
.family
== AF_INET6
485 && IN6_IS_ADDR_LINKLOCAL(&api
.prefix
.u
.prefix6
))
489 * Avoid advertising a false default reachability. (A default
490 * route installed by IS-IS gets redistributed from zebra back
491 * into IS-IS causing us to start advertising default reachabity
492 * without this check)
494 if (api
.prefix
.prefixlen
== 0
495 && api
.src_prefix
.prefixlen
== 0
496 && api
.type
== PROTO_TYPE
) {
497 cmd
= ZEBRA_REDISTRIBUTE_ROUTE_DEL
;
500 if (cmd
== ZEBRA_REDISTRIBUTE_ROUTE_ADD
)
501 isis_redist_add(isis
, api
.type
, &api
.prefix
, &api
.src_prefix
,
502 api
.distance
, api
.metric
, api
.tag
);
504 isis_redist_delete(isis
, api
.type
, &api
.prefix
,
510 int isis_distribute_list_update(int routetype
)
515 void isis_zebra_redistribute_set(afi_t afi
, int type
, vrf_id_t vrf_id
)
517 if (type
== DEFAULT_ROUTE
)
518 zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_ADD
,
519 zclient
, afi
, vrf_id
);
521 zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD
, zclient
, afi
, type
,
525 void isis_zebra_redistribute_unset(afi_t afi
, int type
, vrf_id_t vrf_id
)
527 if (type
== DEFAULT_ROUTE
)
528 zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_DELETE
,
529 zclient
, afi
, vrf_id
);
531 zclient_redistribute(ZEBRA_REDISTRIBUTE_DELETE
, zclient
, afi
,
536 * Register RLFA with LDP.
538 int isis_zebra_rlfa_register(struct isis_spftree
*spftree
, struct rlfa
*rlfa
)
540 struct isis_area
*area
= spftree
->area
;
541 struct zapi_rlfa_request zr
= {};
547 zr
.igp
.vrf_id
= area
->isis
->vrf_id
;
548 zr
.igp
.protocol
= ZEBRA_ROUTE_ISIS
;
549 strlcpy(zr
.igp
.isis
.area_tag
, area
->area_tag
,
550 sizeof(zr
.igp
.isis
.area_tag
));
551 zr
.igp
.isis
.spf
.tree_id
= spftree
->tree_id
;
552 zr
.igp
.isis
.spf
.level
= spftree
->level
;
553 zr
.igp
.isis
.spf
.run_id
= spftree
->runcount
;
554 zr
.destination
= rlfa
->prefix
;
555 zr
.pq_address
= rlfa
->pq_address
;
557 zlog_debug("ISIS-LFA: registering RLFA %pFX@%pI4 with LDP",
558 &rlfa
->prefix
, &rlfa
->pq_address
);
560 ret
= zclient_send_opaque_unicast(zclient
, LDP_RLFA_REGISTER
,
561 ZEBRA_ROUTE_LDP
, 0, 0,
562 (const uint8_t *)&zr
, sizeof(zr
));
563 if (ret
== ZCLIENT_SEND_FAILURE
) {
564 zlog_warn("ISIS-LFA: failed to register RLFA with LDP");
572 * Unregister all RLFAs from the given SPF tree with LDP.
574 void isis_zebra_rlfa_unregister_all(struct isis_spftree
*spftree
)
576 struct isis_area
*area
= spftree
->area
;
577 struct zapi_rlfa_igp igp
= {};
580 if (!zclient
|| spftree
->type
!= SPF_TYPE_FORWARD
581 || CHECK_FLAG(spftree
->flags
, F_SPFTREE_NO_ADJACENCIES
))
585 zlog_debug("ISIS-LFA: unregistering all RLFAs with LDP");
587 igp
.vrf_id
= area
->isis
->vrf_id
;
588 igp
.protocol
= ZEBRA_ROUTE_ISIS
;
589 strlcpy(igp
.isis
.area_tag
, area
->area_tag
, sizeof(igp
.isis
.area_tag
));
590 igp
.isis
.spf
.tree_id
= spftree
->tree_id
;
591 igp
.isis
.spf
.level
= spftree
->level
;
592 igp
.isis
.spf
.run_id
= spftree
->runcount
;
594 ret
= zclient_send_opaque_unicast(zclient
, LDP_RLFA_UNREGISTER_ALL
,
595 ZEBRA_ROUTE_LDP
, 0, 0,
596 (const uint8_t *)&igp
, sizeof(igp
));
597 if (ret
== ZCLIENT_SEND_FAILURE
)
598 zlog_warn("ISIS-LFA: failed to unregister RLFA with LDP");
601 /* Label Manager Functions */
604 * Check if Label Manager is Ready or not.
606 * @return True if Label Manager is ready, False otherwise
608 bool isis_zebra_label_manager_ready(void)
610 return (zclient_sync
->sock
> 0);
614 * Request Label Range to the Label Manager.
616 * @param base base label of the label range to request
617 * @param chunk_size size of the label range to request
619 * @return 0 on success, -1 on failure
621 int isis_zebra_request_label_range(uint32_t base
, uint32_t chunk_size
)
626 if (zclient_sync
->sock
< 0)
629 ret
= lm_get_label_chunk(zclient_sync
, 0, base
, chunk_size
, &start
,
632 zlog_warn("%s: error getting label range!", __func__
);
640 * Release Label Range to the Label Manager.
642 * @param start start of label range to release
643 * @param end end of label range to release
645 * @return 0 on success, -1 otherwise
647 int isis_zebra_release_label_range(uint32_t start
, uint32_t end
)
651 if (zclient_sync
->sock
< 0)
654 ret
= lm_release_label_chunk(zclient_sync
, start
, end
);
656 zlog_warn("%s: error releasing label range!", __func__
);
664 * Connect to the Label Manager.
666 * @return 0 on success, -1 otherwise
668 int isis_zebra_label_manager_connect(void)
670 /* Connect to label manager. */
671 if (zclient_socket_connect(zclient_sync
) < 0) {
672 zlog_warn("%s: failed connecting synchronous zclient!",
676 /* make socket non-blocking */
677 set_nonblocking(zclient_sync
->sock
);
679 /* Send hello to notify zebra this is a synchronous client */
680 if (zclient_send_hello(zclient_sync
) == ZCLIENT_SEND_FAILURE
) {
681 zlog_warn("%s: failed sending hello for synchronous zclient!",
683 close(zclient_sync
->sock
);
684 zclient_sync
->sock
= -1;
688 /* Connect to label manager */
689 if (lm_label_manager_connect(zclient_sync
, 0) != 0) {
690 zlog_warn("%s: failed connecting to label manager!", __func__
);
691 if (zclient_sync
->sock
> 0) {
692 close(zclient_sync
->sock
);
693 zclient_sync
->sock
= -1;
698 sr_debug("ISIS-Sr: Successfully connected to the Label Manager");
703 void isis_zebra_vrf_register(struct isis
*isis
)
705 if (!zclient
|| zclient
->sock
< 0 || !isis
)
708 if (isis
->vrf_id
!= VRF_UNKNOWN
) {
710 zlog_debug("%s: Register VRF %s id %u", __func__
,
711 isis
->name
, isis
->vrf_id
);
712 zclient_send_reg_requests(zclient
, isis
->vrf_id
);
716 void isis_zebra_vrf_deregister(struct isis
*isis
)
718 if (!zclient
|| zclient
->sock
< 0 || !isis
)
721 if (isis
->vrf_id
!= VRF_UNKNOWN
) {
723 zlog_debug("%s: Deregister VRF %s id %u", __func__
,
724 isis
->name
, isis
->vrf_id
);
725 zclient_send_dereg_requests(zclient
, isis
->vrf_id
);
729 static void isis_zebra_connected(struct zclient
*zclient
)
731 zclient_send_reg_requests(zclient
, VRF_DEFAULT
);
732 zclient_register_opaque(zclient
, LDP_RLFA_LABELS
);
733 zclient_register_opaque(zclient
, LDP_IGP_SYNC_IF_STATE_UPDATE
);
734 zclient_register_opaque(zclient
, LDP_IGP_SYNC_ANNOUNCE_UPDATE
);
735 bfd_client_sendmsg(zclient
, ZEBRA_BFD_CLIENT_REGISTER
, VRF_DEFAULT
);
739 * Register / unregister Link State ZAPI Opaque Message
741 * @param up True to register, false to unregister
743 * @return 0 if success, -1 otherwise
745 int isis_zebra_ls_register(bool up
)
750 rc
= ls_register(zclient
, true);
752 rc
= ls_unregister(zclient
, true);
758 * opaque messages between processes
760 static int isis_opaque_msg_handler(ZAPI_CALLBACK_ARGS
)
763 struct zapi_opaque_msg info
;
764 struct zapi_opaque_reg_info dst
;
765 struct ldp_igp_sync_if_state state
;
766 struct ldp_igp_sync_announce announce
;
767 struct zapi_rlfa_response rlfa
;
771 if (zclient_opaque_decode(s
, &info
) != 0)
775 case LINK_STATE_SYNC
:
776 STREAM_GETC(s
, dst
.proto
);
777 STREAM_GETW(s
, dst
.instance
);
778 STREAM_GETL(s
, dst
.session_id
);
779 dst
.type
= LINK_STATE_SYNC
;
780 ret
= isis_te_sync_ted(dst
);
782 case LDP_IGP_SYNC_IF_STATE_UPDATE
:
783 STREAM_GET(&state
, s
, sizeof(state
));
784 ret
= isis_ldp_sync_state_update(state
);
786 case LDP_IGP_SYNC_ANNOUNCE_UPDATE
:
787 STREAM_GET(&announce
, s
, sizeof(announce
));
788 ret
= isis_ldp_sync_announce_update(announce
);
790 case LDP_RLFA_LABELS
:
791 STREAM_GET(&rlfa
, s
, sizeof(rlfa
));
792 isis_rlfa_process_ldp_response(&rlfa
);
803 static int isis_zebra_client_close_notify(ZAPI_CALLBACK_ARGS
)
807 struct zapi_client_close_info info
;
809 if (zapi_client_close_notify_decode(zclient
->ibuf
, &info
) < 0)
812 isis_ldp_sync_handle_client_close(&info
);
813 isis_ldp_rlfa_handle_client_close(&info
);
818 static zclient_handler
*const isis_handlers
[] = {
819 [ZEBRA_ROUTER_ID_UPDATE
] = isis_router_id_update_zebra
,
820 [ZEBRA_INTERFACE_ADDRESS_ADD
] = isis_zebra_if_address_add
,
821 [ZEBRA_INTERFACE_ADDRESS_DELETE
] = isis_zebra_if_address_del
,
822 [ZEBRA_INTERFACE_LINK_PARAMS
] = isis_zebra_link_params
,
823 [ZEBRA_REDISTRIBUTE_ROUTE_ADD
] = isis_zebra_read
,
824 [ZEBRA_REDISTRIBUTE_ROUTE_DEL
] = isis_zebra_read
,
826 [ZEBRA_OPAQUE_MESSAGE
] = isis_opaque_msg_handler
,
828 [ZEBRA_CLIENT_CLOSE_NOTIFY
] = isis_zebra_client_close_notify
,
831 void isis_zebra_init(struct event_loop
*master
, int instance
)
833 /* Initialize asynchronous zclient. */
834 zclient
= zclient_new(master
, &zclient_options_default
, isis_handlers
,
835 array_size(isis_handlers
));
836 zclient_init(zclient
, PROTO_TYPE
, 0, &isisd_privs
);
837 zclient
->zebra_connected
= isis_zebra_connected
;
839 /* Initialize special zclient for synchronous message exchanges. */
840 struct zclient_options options
= zclient_options_default
;
841 options
.synchronous
= true;
842 zclient_sync
= zclient_new(master
, &options
, NULL
, 0);
843 zclient_sync
->sock
= -1;
844 zclient_sync
->redist_default
= ZEBRA_ROUTE_ISIS
;
845 zclient_sync
->instance
= instance
;
847 * session_id must be different from default value (0) to distinguish
848 * the asynchronous socket from the synchronous one
850 zclient_sync
->session_id
= 1;
851 zclient_sync
->privs
= &isisd_privs
;
854 void isis_zebra_stop(void)
856 zclient_unregister_opaque(zclient
, LDP_RLFA_LABELS
);
857 zclient_unregister_opaque(zclient
, LDP_IGP_SYNC_IF_STATE_UPDATE
);
858 zclient_unregister_opaque(zclient
, LDP_IGP_SYNC_ANNOUNCE_UPDATE
);
859 zclient_stop(zclient_sync
);
860 zclient_free(zclient_sync
);
861 zclient_stop(zclient
);
862 zclient_free(zclient
);