2 * IS-IS Rout(e)ing protocol - isis_zebra.c
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>
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)
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
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
30 #include "lib_errors.h"
42 #include "isisd/isis_constants.h"
43 #include "isisd/isis_common.h"
44 #include "isisd/isis_flags.h"
45 #include "isisd/isis_misc.h"
46 #include "isisd/isis_circuit.h"
47 #include "isisd/isisd.h"
48 #include "isisd/isis_circuit.h"
49 #include "isisd/isis_csm.h"
50 #include "isisd/isis_lsp.h"
51 #include "isisd/isis_spf.h"
52 #include "isisd/isis_spf_private.h"
53 #include "isisd/isis_route.h"
54 #include "isisd/isis_zebra.h"
55 #include "isisd/isis_adjacency.h"
56 #include "isisd/isis_te.h"
57 #include "isisd/isis_sr.h"
58 #include "isisd/isis_ldp_sync.h"
60 struct zclient
*zclient
;
61 static struct zclient
*zclient_sync
;
63 /* Router-id update message from zebra. */
64 static int isis_router_id_update_zebra(ZAPI_CALLBACK_ARGS
)
66 struct isis_area
*area
;
67 struct listnode
*node
;
68 struct prefix router_id
;
69 struct isis
*isis
= NULL
;
71 isis
= isis_lookup_by_vrfid(vrf_id
);
77 zebra_router_id_update_read(zclient
->ibuf
, &router_id
);
78 if (isis
->router_id
== router_id
.u
.prefix4
.s_addr
)
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);
89 static int isis_zebra_if_address_add(ZAPI_CALLBACK_ARGS
)
91 struct isis_circuit
*circuit
;
94 c
= zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_ADD
,
95 zclient
->ibuf
, vrf_id
);
101 if (c
->address
->family
== AF_INET
)
102 zlog_debug("connected IP address %pFX", c
->address
);
103 if (c
->address
->family
== AF_INET6
)
104 zlog_debug("connected IPv6 address %pFX", c
->address
);
105 #endif /* EXTREME_DEBUG */
107 if (if_is_operative(c
->ifp
)) {
108 circuit
= circuit_scan_by_ifp(c
->ifp
);
110 isis_circuit_add_addr(circuit
, c
);
116 static int isis_zebra_if_address_del(ZAPI_CALLBACK_ARGS
)
118 struct isis_circuit
*circuit
;
121 c
= zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_DELETE
,
122 zclient
->ibuf
, vrf_id
);
128 if (c
->address
->family
== AF_INET
)
129 zlog_debug("disconnected IP address %pFX", c
->address
);
130 if (c
->address
->family
== AF_INET6
)
131 zlog_debug("disconnected IPv6 address %pFX", c
->address
);
132 #endif /* EXTREME_DEBUG */
134 if (if_is_operative(c
->ifp
)) {
135 circuit
= circuit_scan_by_ifp(c
->ifp
);
137 isis_circuit_del_addr(circuit
, c
);
145 static int isis_zebra_link_params(ZAPI_CALLBACK_ARGS
)
147 struct interface
*ifp
;
148 bool changed
= false;
150 ifp
= zebra_interface_link_params_read(zclient
->ibuf
, vrf_id
, &changed
);
152 if (ifp
== NULL
|| !changed
)
156 isis_mpls_te_update(ifp
);
161 enum isis_zebra_nexthop_type
{
162 ISIS_NEXTHOP_MAIN
= 0,
166 static int isis_zebra_add_nexthops(struct isis
*isis
, struct list
*nexthops
,
167 struct zapi_nexthop zapi_nexthops
[],
168 enum isis_zebra_nexthop_type type
,
169 bool mpls_lsp
, uint8_t backup_nhs
)
171 struct isis_nexthop
*nexthop
;
172 struct listnode
*node
;
176 for (ALL_LIST_ELEMENTS_RO(nexthops
, node
, nexthop
)) {
177 struct zapi_nexthop
*api_nh
;
179 if (count
>= MULTIPATH_NUM
)
181 api_nh
= &zapi_nexthops
[count
];
183 SET_FLAG(api_nh
->flags
, ZAPI_NEXTHOP_FLAG_ONLINK
);
184 api_nh
->vrf_id
= isis
->vrf_id
;
186 switch (nexthop
->family
) {
188 /* FIXME: can it be ? */
189 if (nexthop
->ip
.ipv4
.s_addr
!= INADDR_ANY
) {
190 api_nh
->type
= NEXTHOP_TYPE_IPV4_IFINDEX
;
191 api_nh
->gate
.ipv4
= nexthop
->ip
.ipv4
;
193 api_nh
->type
= NEXTHOP_TYPE_IFINDEX
;
197 if (!IN6_IS_ADDR_LINKLOCAL(&nexthop
->ip
.ipv6
)
198 && !IN6_IS_ADDR_UNSPECIFIED(&nexthop
->ip
.ipv6
)) {
201 api_nh
->gate
.ipv6
= nexthop
->ip
.ipv6
;
202 api_nh
->type
= NEXTHOP_TYPE_IPV6_IFINDEX
;
205 flog_err(EC_LIB_DEVELOPMENT
,
206 "%s: unknown address family [%d]", __func__
,
211 api_nh
->ifindex
= nexthop
->ifindex
;
213 /* Add MPLS label(s). */
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
) {
223 case ISIS_NEXTHOP_MAIN
:
225 * Do not use non-SR enabled nexthops to prevent
226 * broken LSPs from being formed.
229 case ISIS_NEXTHOP_BACKUP
:
231 * This is necessary because zebra requires
232 * the nexthops of MPLS LSPs to be labeled.
234 api_nh
->label_num
= 1;
235 api_nh
->labels
[0] = MPLS_LABEL_IMPLICIT_NULL
;
240 /* Backup nexthop handling. */
242 SET_FLAG(api_nh
->flags
, ZAPI_NEXTHOP_FLAG_HAS_BACKUP
);
244 * If the backup has multiple nexthops, all of them
245 * protect the same primary nexthop since ECMP routes
248 api_nh
->backup_num
= backup_nhs
;
249 for (int i
= 0; i
< backup_nhs
; i
++)
250 api_nh
->backup_idx
[i
] = i
;
258 void isis_zebra_route_add_route(struct isis
*isis
, struct prefix
*prefix
,
259 struct prefix_ipv6
*src_p
,
260 struct isis_route_info
*route_info
)
262 struct zapi_route api
;
265 if (zclient
->sock
< 0)
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
);
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
);
283 SET_FLAG(api
.message
, ZAPI_MESSAGE_NEXTHOP
);
284 SET_FLAG(api
.message
, ZAPI_MESSAGE_METRIC
);
285 api
.metric
= route_info
->cost
;
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
,
291 ISIS_NEXTHOP_BACKUP
, false, 0);
293 SET_FLAG(api
.message
, ZAPI_MESSAGE_BACKUP_NEXTHOPS
);
294 api
.backup_nexthop_num
= count
;
298 /* Add primary nexthops. */
299 count
= isis_zebra_add_nexthops(isis
, route_info
->nexthops
,
300 api
.nexthops
, ISIS_NEXTHOP_MAIN
, false,
304 api
.nexthop_num
= count
;
306 zclient_route_send(ZEBRA_ROUTE_ADD
, zclient
, &api
);
309 void isis_zebra_route_del_route(struct isis
*isis
,
310 struct prefix
*prefix
,
311 struct prefix_ipv6
*src_p
,
312 struct isis_route_info
*route_info
)
314 struct zapi_route api
;
316 if (zclient
->sock
< 0)
319 memset(&api
, 0, sizeof(api
));
320 api
.vrf_id
= isis
->vrf_id
;
321 api
.type
= PROTO_TYPE
;
322 api
.safi
= SAFI_UNICAST
;
323 api
.prefix
= *prefix
;
324 if (src_p
&& src_p
->prefixlen
) {
325 api
.src_prefix
= *src_p
;
326 SET_FLAG(api
.message
, ZAPI_MESSAGE_SRCPFX
);
329 zclient_route_send(ZEBRA_ROUTE_DELETE
, zclient
, &api
);
333 * Install Prefix-SID label entry in the forwarding plane through Zebra.
335 * @param area IS-IS area
336 * @param prefix Route prefix
337 * @param rinfo Route information
338 * @param psid Prefix-SID information
340 void 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
)
345 struct zapi_labels zl
;
348 sr_debug("ISIS-Sr (%s): update label %u for prefix %pFX",
349 area
->area_tag
, psid
->label
, prefix
);
351 /* Prepare message. */
352 memset(&zl
, 0, sizeof(zl
));
353 zl
.type
= ZEBRA_LSP_ISIS_SR
;
354 zl
.local_label
= psid
->label
;
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
;
361 ifp
= if_lookup_by_name("lo", VRF_DEFAULT
);
364 "%s: couldn't install Prefix-SID %pFX: loopback interface not found",
369 znh
= &zl
.nexthops
[zl
.nexthop_num
++];
370 znh
->type
= NEXTHOP_TYPE_IFINDEX
;
371 znh
->ifindex
= ifp
->ifindex
;
373 znh
->labels
[0] = MPLS_LABEL_IMPLICIT_NULL
;
375 /* Add backup nexthops first. */
377 count
= isis_zebra_add_nexthops(
378 area
->isis
, rinfo
->backup
->nexthops
,
379 zl
.backup_nexthops
, ISIS_NEXTHOP_BACKUP
, true,
382 SET_FLAG(zl
.message
, ZAPI_LABELS_HAS_BACKUPS
);
383 zl
.backup_nexthop_num
= count
;
387 /* Add primary nexthops. */
388 count
= isis_zebra_add_nexthops(area
->isis
, rinfo
->nexthops
,
389 zl
.nexthops
, ISIS_NEXTHOP_MAIN
,
393 zl
.nexthop_num
= count
;
396 /* Send message to zebra. */
397 (void)zebra_send_mpls_labels(zclient
, ZEBRA_MPLS_LABELS_REPLACE
, &zl
);
401 * Uninstall Prefix-SID label entry from the forwarding plane through Zebra.
403 * @param area IS-IS area
404 * @param prefix Route prefix
405 * @param rinfo Route information
406 * @param psid Prefix-SID information
408 void 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
)
413 struct zapi_labels zl
;
415 sr_debug("ISIS-Sr (%s): delete label %u for prefix %pFX",
416 area
->area_tag
, psid
->label
, prefix
);
418 /* Prepare message. */
419 memset(&zl
, 0, sizeof(zl
));
420 zl
.type
= ZEBRA_LSP_ISIS_SR
;
421 zl
.local_label
= psid
->label
;
423 /* Send message to zebra. */
424 (void)zebra_send_mpls_labels(zclient
, ZEBRA_MPLS_LABELS_DELETE
, &zl
);
428 * Send (LAN)-Adjacency-SID to ZEBRA for installation or deletion.
430 * @param cmd ZEBRA_MPLS_LABELS_ADD or ZEBRA_ROUTE_DELETE
431 * @param sra Segment Routing Adjacency-SID
433 void isis_zebra_send_adjacency_sid(int cmd
, const struct sr_adjacency
*sra
)
435 struct isis
*isis
= sra
->adj
->circuit
->area
->isis
;
436 struct zapi_labels zl
;
437 struct zapi_nexthop
*znh
;
439 if (cmd
!= ZEBRA_MPLS_LABELS_ADD
&& cmd
!= ZEBRA_MPLS_LABELS_DELETE
) {
440 flog_warn(EC_LIB_DEVELOPMENT
, "%s: wrong ZEBRA command",
445 sr_debug(" |- %s label %u for interface %s",
446 cmd
== ZEBRA_MPLS_LABELS_ADD
? "Add" : "Delete",
447 sra
->input_label
, sra
->adj
->circuit
->interface
->name
);
449 memset(&zl
, 0, sizeof(zl
));
450 zl
.type
= ZEBRA_LSP_ISIS_SR
;
451 zl
.local_label
= sra
->input_label
;
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
;
460 znh
->labels
[0] = MPLS_LABEL_IMPLICIT_NULL
;
462 /* Set backup nexthops. */
463 if (sra
->type
== ISIS_SR_LAN_BACKUP
) {
466 count
= isis_zebra_add_nexthops(isis
, sra
->backup_nexthops
,
468 ISIS_NEXTHOP_BACKUP
, true, 0);
470 SET_FLAG(zl
.message
, ZAPI_LABELS_HAS_BACKUPS
);
471 zl
.backup_nexthop_num
= count
;
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
;
480 (void)zebra_send_mpls_labels(zclient
, cmd
, &zl
);
483 static int isis_zebra_read(ZAPI_CALLBACK_ARGS
)
485 struct zapi_route api
;
486 struct isis
*isis
= NULL
;
488 isis
= isis_lookup_by_vrfid(vrf_id
);
493 if (zapi_route_decode(zclient
->ibuf
, &api
) < 0)
496 if (api
.prefix
.family
== AF_INET6
497 && IN6_IS_ADDR_LINKLOCAL(&api
.prefix
.u
.prefix6
))
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)
506 if (api
.prefix
.prefixlen
== 0
507 && api
.src_prefix
.prefixlen
== 0
508 && api
.type
== PROTO_TYPE
) {
509 cmd
= ZEBRA_REDISTRIBUTE_ROUTE_DEL
;
512 if (cmd
== ZEBRA_REDISTRIBUTE_ROUTE_ADD
)
513 isis_redist_add(isis
, api
.type
, &api
.prefix
, &api
.src_prefix
,
514 api
.distance
, api
.metric
, api
.tag
);
516 isis_redist_delete(isis
, api
.type
, &api
.prefix
,
522 int isis_distribute_list_update(int routetype
)
527 void isis_zebra_redistribute_set(afi_t afi
, int type
, vrf_id_t vrf_id
)
529 if (type
== DEFAULT_ROUTE
)
530 zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_ADD
,
531 zclient
, afi
, vrf_id
);
533 zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD
, zclient
, afi
, type
,
537 void isis_zebra_redistribute_unset(afi_t afi
, int type
, vrf_id_t vrf_id
)
539 if (type
== DEFAULT_ROUTE
)
540 zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_DELETE
,
541 zclient
, afi
, vrf_id
);
543 zclient_redistribute(ZEBRA_REDISTRIBUTE_DELETE
, zclient
, afi
,
548 * Register RLFA with LDP.
550 int isis_zebra_rlfa_register(struct isis_spftree
*spftree
, struct rlfa
*rlfa
)
552 struct isis_area
*area
= spftree
->area
;
553 struct zapi_rlfa_request zr
= {};
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
;
569 zlog_debug("ISIS-LFA: registering RLFA %pFX@%pI4 with LDP",
570 &rlfa
->prefix
, &rlfa
->pq_address
);
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");
584 * Unregister all RLFAs from the given SPF tree with LDP.
586 void isis_zebra_rlfa_unregister_all(struct isis_spftree
*spftree
)
588 struct isis_area
*area
= spftree
->area
;
589 struct zapi_rlfa_igp igp
= {};
592 if (!zclient
|| spftree
->type
!= SPF_TYPE_FORWARD
593 || CHECK_FLAG(spftree
->flags
, F_SPFTREE_NO_ADJACENCIES
))
597 zlog_debug("ISIS-LFA: unregistering all RLFAs with LDP");
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
;
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");
613 /* Label Manager Functions */
616 * Check if Label Manager is Ready or not.
618 * @return True if Label Manager is ready, False otherwise
620 bool isis_zebra_label_manager_ready(void)
622 return (zclient_sync
->sock
> 0);
626 * Request Label Range to the Label Manager.
628 * @param base base label of the label range to request
629 * @param chunk_size size of the label range to request
631 * @return 0 on success, -1 on failure
633 int isis_zebra_request_label_range(uint32_t base
, uint32_t chunk_size
)
638 if (zclient_sync
->sock
< 0)
641 ret
= lm_get_label_chunk(zclient_sync
, 0, base
, chunk_size
, &start
,
644 zlog_warn("%s: error getting label range!", __func__
);
652 * Release Label Range to the Label Manager.
654 * @param start start of label range to release
655 * @param end end of label range to release
657 * @return 0 on success, -1 otherwise
659 int isis_zebra_release_label_range(uint32_t start
, uint32_t end
)
663 if (zclient_sync
->sock
< 0)
666 ret
= lm_release_label_chunk(zclient_sync
, start
, end
);
668 zlog_warn("%s: error releasing label range!", __func__
);
676 * Connect to the Label Manager.
678 * @return 0 on success, -1 otherwise
680 int isis_zebra_label_manager_connect(void)
682 /* Connect to label manager. */
683 if (zclient_socket_connect(zclient_sync
) < 0) {
684 zlog_warn("%s: failed connecting synchronous zclient!",
688 /* make socket non-blocking */
689 set_nonblocking(zclient_sync
->sock
);
691 /* Send hello to notify zebra this is a synchronous client */
692 if (zclient_send_hello(zclient_sync
) == ZCLIENT_SEND_FAILURE
) {
693 zlog_warn("%s: failed sending hello for synchronous zclient!",
695 close(zclient_sync
->sock
);
696 zclient_sync
->sock
= -1;
700 /* Connect to label manager */
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;
710 sr_debug("ISIS-Sr: Successfully connected to the Label Manager");
715 void isis_zebra_vrf_register(struct isis
*isis
)
717 if (!zclient
|| zclient
->sock
< 0 || !isis
)
720 if (isis
->vrf_id
!= VRF_UNKNOWN
) {
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
);
728 void isis_zebra_vrf_deregister(struct isis
*isis
)
730 if (!zclient
|| zclient
->sock
< 0 || !isis
)
733 if (isis
->vrf_id
!= VRF_UNKNOWN
) {
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
);
741 static void isis_zebra_connected(struct zclient
*zclient
)
743 zclient_send_reg_requests(zclient
, VRF_DEFAULT
);
744 zclient_register_opaque(zclient
, LDP_RLFA_LABELS
);
745 zclient_register_opaque(zclient
, LDP_IGP_SYNC_IF_STATE_UPDATE
);
746 zclient_register_opaque(zclient
, LDP_IGP_SYNC_ANNOUNCE_UPDATE
);
747 bfd_client_sendmsg(zclient
, ZEBRA_BFD_CLIENT_REGISTER
, VRF_DEFAULT
);
751 * opaque messages between processes
753 static int isis_opaque_msg_handler(ZAPI_CALLBACK_ARGS
)
756 struct zapi_opaque_msg info
;
757 struct ldp_igp_sync_if_state state
;
758 struct ldp_igp_sync_announce announce
;
759 struct zapi_rlfa_response rlfa
;
763 if (zclient_opaque_decode(s
, &info
) != 0)
767 case LDP_IGP_SYNC_IF_STATE_UPDATE
:
768 STREAM_GET(&state
, s
, sizeof(state
));
769 ret
= isis_ldp_sync_state_update(state
);
771 case LDP_IGP_SYNC_ANNOUNCE_UPDATE
:
772 STREAM_GET(&announce
, s
, sizeof(announce
));
773 ret
= isis_ldp_sync_announce_update(announce
);
775 case LDP_RLFA_LABELS
:
776 STREAM_GET(&rlfa
, s
, sizeof(rlfa
));
777 isis_rlfa_process_ldp_response(&rlfa
);
788 static int isis_zebra_client_close_notify(ZAPI_CALLBACK_ARGS
)
792 struct zapi_client_close_info info
;
794 if (zapi_client_close_notify_decode(zclient
->ibuf
, &info
) < 0)
797 isis_ldp_sync_handle_client_close(&info
);
798 isis_ldp_rlfa_handle_client_close(&info
);
803 void isis_zebra_init(struct thread_master
*master
, int instance
)
805 /* Initialize asynchronous zclient. */
806 zclient
= zclient_new(master
, &zclient_options_default
);
807 zclient_init(zclient
, PROTO_TYPE
, 0, &isisd_privs
);
808 zclient
->zebra_connected
= isis_zebra_connected
;
809 zclient
->router_id_update
= isis_router_id_update_zebra
;
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
;
813 zclient
->redistribute_route_add
= isis_zebra_read
;
814 zclient
->redistribute_route_del
= isis_zebra_read
;
816 /* Initialize special zclient for synchronous message exchanges. */
817 struct zclient_options options
= zclient_options_default
;
818 options
.synchronous
= true;
819 zclient_sync
= zclient_new(master
, &options
);
820 zclient_sync
->sock
= -1;
821 zclient_sync
->redist_default
= ZEBRA_ROUTE_ISIS
;
822 zclient_sync
->instance
= instance
;
824 * session_id must be different from default value (0) to distinguish
825 * the asynchronous socket from the synchronous one
827 zclient_sync
->session_id
= 1;
828 zclient_sync
->privs
= &isisd_privs
;
830 zclient
->opaque_msg_handler
= isis_opaque_msg_handler
;
832 zclient
->zebra_client_close_notify
= isis_zebra_client_close_notify
;
835 void isis_zebra_stop(void)
837 zclient_unregister_opaque(zclient
, LDP_RLFA_LABELS
);
838 zclient_unregister_opaque(zclient
, LDP_IGP_SYNC_IF_STATE_UPDATE
);
839 zclient_unregister_opaque(zclient
, LDP_IGP_SYNC_ANNOUNCE_UPDATE
);
840 zclient_stop(zclient_sync
);
841 zclient_free(zclient_sync
);
842 zclient_stop(zclient
);
843 zclient_free(zclient
);