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"
41 #include "link_state.h"
43 #include "isisd/isis_constants.h"
44 #include "isisd/isis_common.h"
45 #include "isisd/isis_flags.h"
46 #include "isisd/isis_misc.h"
47 #include "isisd/isis_circuit.h"
48 #include "isisd/isisd.h"
49 #include "isisd/isis_circuit.h"
50 #include "isisd/isis_csm.h"
51 #include "isisd/isis_lsp.h"
52 #include "isisd/isis_spf.h"
53 #include "isisd/isis_spf_private.h"
54 #include "isisd/isis_route.h"
55 #include "isisd/isis_zebra.h"
56 #include "isisd/isis_adjacency.h"
57 #include "isisd/isis_te.h"
58 #include "isisd/isis_sr.h"
59 #include "isisd/isis_ldp_sync.h"
61 struct zclient
*zclient
;
62 static struct zclient
*zclient_sync
;
64 /* Router-id update message from zebra. */
65 static int isis_router_id_update_zebra(ZAPI_CALLBACK_ARGS
)
67 struct isis_area
*area
;
68 struct listnode
*node
;
69 struct prefix router_id
;
70 struct isis
*isis
= NULL
;
72 isis
= isis_lookup_by_vrfid(vrf_id
);
78 zebra_router_id_update_read(zclient
->ibuf
, &router_id
);
79 if (isis
->router_id
== router_id
.u
.prefix4
.s_addr
)
82 isis
->router_id
= router_id
.u
.prefix4
.s_addr
;
83 for (ALL_LIST_ELEMENTS_RO(isis
->area_list
, node
, area
))
84 if (listcount(area
->area_addrs
) > 0)
85 lsp_regenerate_schedule(area
, area
->is_type
, 0);
90 static int isis_zebra_if_address_add(ZAPI_CALLBACK_ARGS
)
92 struct isis_circuit
*circuit
;
95 c
= zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_ADD
,
96 zclient
->ibuf
, vrf_id
);
102 if (c
->address
->family
== AF_INET
)
103 zlog_debug("connected IP address %pFX", c
->address
);
104 if (c
->address
->family
== AF_INET6
)
105 zlog_debug("connected IPv6 address %pFX", c
->address
);
106 #endif /* EXTREME_DEBUG */
108 if (if_is_operative(c
->ifp
)) {
109 circuit
= circuit_scan_by_ifp(c
->ifp
);
111 isis_circuit_add_addr(circuit
, c
);
117 static int isis_zebra_if_address_del(ZAPI_CALLBACK_ARGS
)
119 struct isis_circuit
*circuit
;
122 c
= zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_DELETE
,
123 zclient
->ibuf
, vrf_id
);
129 if (c
->address
->family
== AF_INET
)
130 zlog_debug("disconnected IP address %pFX", c
->address
);
131 if (c
->address
->family
== AF_INET6
)
132 zlog_debug("disconnected IPv6 address %pFX", c
->address
);
133 #endif /* EXTREME_DEBUG */
135 if (if_is_operative(c
->ifp
)) {
136 circuit
= circuit_scan_by_ifp(c
->ifp
);
138 isis_circuit_del_addr(circuit
, c
);
146 static int isis_zebra_link_params(ZAPI_CALLBACK_ARGS
)
148 struct interface
*ifp
;
149 bool changed
= false;
151 ifp
= zebra_interface_link_params_read(zclient
->ibuf
, vrf_id
, &changed
);
153 if (ifp
== NULL
|| !changed
)
157 isis_mpls_te_update(ifp
);
162 enum isis_zebra_nexthop_type
{
163 ISIS_NEXTHOP_MAIN
= 0,
167 static int isis_zebra_add_nexthops(struct isis
*isis
, struct list
*nexthops
,
168 struct zapi_nexthop zapi_nexthops
[],
169 enum isis_zebra_nexthop_type type
,
170 bool mpls_lsp
, uint8_t backup_nhs
)
172 struct isis_nexthop
*nexthop
;
173 struct listnode
*node
;
177 for (ALL_LIST_ELEMENTS_RO(nexthops
, node
, nexthop
)) {
178 struct zapi_nexthop
*api_nh
;
180 if (count
>= MULTIPATH_NUM
)
182 api_nh
= &zapi_nexthops
[count
];
184 SET_FLAG(api_nh
->flags
, ZAPI_NEXTHOP_FLAG_ONLINK
);
185 api_nh
->vrf_id
= isis
->vrf_id
;
187 switch (nexthop
->family
) {
189 /* FIXME: can it be ? */
190 if (nexthop
->ip
.ipv4
.s_addr
!= INADDR_ANY
) {
191 api_nh
->type
= NEXTHOP_TYPE_IPV4_IFINDEX
;
192 api_nh
->gate
.ipv4
= nexthop
->ip
.ipv4
;
194 api_nh
->type
= NEXTHOP_TYPE_IFINDEX
;
198 if (!IN6_IS_ADDR_LINKLOCAL(&nexthop
->ip
.ipv6
)
199 && !IN6_IS_ADDR_UNSPECIFIED(&nexthop
->ip
.ipv6
)) {
202 api_nh
->gate
.ipv6
= nexthop
->ip
.ipv6
;
203 api_nh
->type
= NEXTHOP_TYPE_IPV6_IFINDEX
;
206 flog_err(EC_LIB_DEVELOPMENT
,
207 "%s: unknown address family [%d]", __func__
,
212 api_nh
->ifindex
= nexthop
->ifindex
;
214 /* Add MPLS label(s). */
215 if (nexthop
->label_stack
) {
216 api_nh
->label_num
= nexthop
->label_stack
->num_labels
;
217 memcpy(api_nh
->labels
, nexthop
->label_stack
->label
,
218 sizeof(mpls_label_t
) * api_nh
->label_num
);
219 } else if (nexthop
->sr
.present
) {
220 api_nh
->label_num
= 1;
221 api_nh
->labels
[0] = nexthop
->sr
.label
;
222 } else if (mpls_lsp
) {
224 case ISIS_NEXTHOP_MAIN
:
226 * Do not use non-SR enabled nexthops to prevent
227 * broken LSPs from being formed.
230 case ISIS_NEXTHOP_BACKUP
:
232 * This is necessary because zebra requires
233 * the nexthops of MPLS LSPs to be labeled.
235 api_nh
->label_num
= 1;
236 api_nh
->labels
[0] = MPLS_LABEL_IMPLICIT_NULL
;
241 /* Backup nexthop handling. */
243 SET_FLAG(api_nh
->flags
, ZAPI_NEXTHOP_FLAG_HAS_BACKUP
);
245 * If the backup has multiple nexthops, all of them
246 * protect the same primary nexthop since ECMP routes
249 api_nh
->backup_num
= backup_nhs
;
250 for (int i
= 0; i
< backup_nhs
; i
++)
251 api_nh
->backup_idx
[i
] = i
;
259 void isis_zebra_route_add_route(struct isis
*isis
, struct prefix
*prefix
,
260 struct prefix_ipv6
*src_p
,
261 struct isis_route_info
*route_info
)
263 struct zapi_route api
;
266 if (zclient
->sock
< 0)
269 /* Uninstall the route if it doesn't have any valid nexthop. */
270 if (list_isempty(route_info
->nexthops
)) {
271 isis_zebra_route_del_route(isis
, prefix
, src_p
, route_info
);
275 memset(&api
, 0, sizeof(api
));
276 api
.vrf_id
= isis
->vrf_id
;
277 api
.type
= PROTO_TYPE
;
278 api
.safi
= SAFI_UNICAST
;
279 api
.prefix
= *prefix
;
280 if (src_p
&& src_p
->prefixlen
) {
281 api
.src_prefix
= *src_p
;
282 SET_FLAG(api
.message
, ZAPI_MESSAGE_SRCPFX
);
284 SET_FLAG(api
.message
, ZAPI_MESSAGE_NEXTHOP
);
285 SET_FLAG(api
.message
, ZAPI_MESSAGE_METRIC
);
286 api
.metric
= route_info
->cost
;
288 /* Add backup nexthops first. */
289 if (route_info
->backup
) {
290 count
= isis_zebra_add_nexthops(
291 isis
, route_info
->backup
->nexthops
, api
.backup_nexthops
,
292 ISIS_NEXTHOP_BACKUP
, false, 0);
294 SET_FLAG(api
.message
, ZAPI_MESSAGE_BACKUP_NEXTHOPS
);
295 api
.backup_nexthop_num
= count
;
299 /* Add primary nexthops. */
300 count
= isis_zebra_add_nexthops(isis
, route_info
->nexthops
,
301 api
.nexthops
, ISIS_NEXTHOP_MAIN
, false,
305 api
.nexthop_num
= count
;
307 zclient_route_send(ZEBRA_ROUTE_ADD
, zclient
, &api
);
310 void isis_zebra_route_del_route(struct isis
*isis
,
311 struct prefix
*prefix
,
312 struct prefix_ipv6
*src_p
,
313 struct isis_route_info
*route_info
)
315 struct zapi_route api
;
317 if (zclient
->sock
< 0)
320 memset(&api
, 0, sizeof(api
));
321 api
.vrf_id
= isis
->vrf_id
;
322 api
.type
= PROTO_TYPE
;
323 api
.safi
= SAFI_UNICAST
;
324 api
.prefix
= *prefix
;
325 if (src_p
&& src_p
->prefixlen
) {
326 api
.src_prefix
= *src_p
;
327 SET_FLAG(api
.message
, ZAPI_MESSAGE_SRCPFX
);
330 zclient_route_send(ZEBRA_ROUTE_DELETE
, zclient
, &api
);
334 * Install Prefix-SID label entry in the forwarding plane through Zebra.
336 * @param area IS-IS area
337 * @param prefix Route prefix
338 * @param rinfo Route information
339 * @param psid Prefix-SID information
341 void isis_zebra_prefix_sid_install(struct isis_area
*area
,
342 struct prefix
*prefix
,
343 struct isis_route_info
*rinfo
,
344 struct isis_sr_psid_info
*psid
)
346 struct zapi_labels zl
;
349 sr_debug("ISIS-Sr (%s): update label %u for prefix %pFX",
350 area
->area_tag
, psid
->label
, prefix
);
352 /* Prepare message. */
353 memset(&zl
, 0, sizeof(zl
));
354 zl
.type
= ZEBRA_LSP_ISIS_SR
;
355 zl
.local_label
= psid
->label
;
357 /* Local routes don't have any nexthop and require special handling. */
358 if (list_isempty(rinfo
->nexthops
)) {
359 struct zapi_nexthop
*znh
;
360 struct interface
*ifp
;
362 ifp
= if_lookup_by_name("lo", VRF_DEFAULT
);
365 "%s: couldn't install Prefix-SID %pFX: loopback interface not found",
370 znh
= &zl
.nexthops
[zl
.nexthop_num
++];
371 znh
->type
= NEXTHOP_TYPE_IFINDEX
;
372 znh
->ifindex
= ifp
->ifindex
;
374 znh
->labels
[0] = MPLS_LABEL_IMPLICIT_NULL
;
376 /* Add backup nexthops first. */
378 count
= isis_zebra_add_nexthops(
379 area
->isis
, rinfo
->backup
->nexthops
,
380 zl
.backup_nexthops
, ISIS_NEXTHOP_BACKUP
, true,
383 SET_FLAG(zl
.message
, ZAPI_LABELS_HAS_BACKUPS
);
384 zl
.backup_nexthop_num
= count
;
388 /* Add primary nexthops. */
389 count
= isis_zebra_add_nexthops(area
->isis
, rinfo
->nexthops
,
390 zl
.nexthops
, ISIS_NEXTHOP_MAIN
,
394 zl
.nexthop_num
= count
;
397 /* Send message to zebra. */
398 (void)zebra_send_mpls_labels(zclient
, ZEBRA_MPLS_LABELS_REPLACE
, &zl
);
402 * Uninstall Prefix-SID label entry from the forwarding plane through Zebra.
404 * @param area IS-IS area
405 * @param prefix Route prefix
406 * @param rinfo Route information
407 * @param psid Prefix-SID information
409 void isis_zebra_prefix_sid_uninstall(struct isis_area
*area
,
410 struct prefix
*prefix
,
411 struct isis_route_info
*rinfo
,
412 struct isis_sr_psid_info
*psid
)
414 struct zapi_labels zl
;
416 sr_debug("ISIS-Sr (%s): delete label %u for prefix %pFX",
417 area
->area_tag
, psid
->label
, prefix
);
419 /* Prepare message. */
420 memset(&zl
, 0, sizeof(zl
));
421 zl
.type
= ZEBRA_LSP_ISIS_SR
;
422 zl
.local_label
= psid
->label
;
424 /* Send message to zebra. */
425 (void)zebra_send_mpls_labels(zclient
, ZEBRA_MPLS_LABELS_DELETE
, &zl
);
429 * Send (LAN)-Adjacency-SID to ZEBRA for installation or deletion.
431 * @param cmd ZEBRA_MPLS_LABELS_ADD or ZEBRA_ROUTE_DELETE
432 * @param sra Segment Routing Adjacency-SID
434 void isis_zebra_send_adjacency_sid(int cmd
, const struct sr_adjacency
*sra
)
436 struct isis
*isis
= sra
->adj
->circuit
->area
->isis
;
437 struct zapi_labels zl
;
438 struct zapi_nexthop
*znh
;
440 if (cmd
!= ZEBRA_MPLS_LABELS_ADD
&& cmd
!= ZEBRA_MPLS_LABELS_DELETE
) {
441 flog_warn(EC_LIB_DEVELOPMENT
, "%s: wrong ZEBRA command",
446 sr_debug(" |- %s label %u for interface %s",
447 cmd
== ZEBRA_MPLS_LABELS_ADD
? "Add" : "Delete",
448 sra
->input_label
, sra
->adj
->circuit
->interface
->name
);
450 memset(&zl
, 0, sizeof(zl
));
451 zl
.type
= ZEBRA_LSP_ISIS_SR
;
452 zl
.local_label
= sra
->input_label
;
454 znh
= &zl
.nexthops
[0];
455 znh
->gate
= sra
->nexthop
.address
;
456 znh
->type
= (sra
->nexthop
.family
== AF_INET
)
457 ? NEXTHOP_TYPE_IPV4_IFINDEX
458 : NEXTHOP_TYPE_IPV6_IFINDEX
;
459 znh
->ifindex
= sra
->adj
->circuit
->interface
->ifindex
;
461 znh
->labels
[0] = MPLS_LABEL_IMPLICIT_NULL
;
463 /* Set backup nexthops. */
464 if (sra
->type
== ISIS_SR_LAN_BACKUP
) {
467 count
= isis_zebra_add_nexthops(isis
, sra
->backup_nexthops
,
469 ISIS_NEXTHOP_BACKUP
, true, 0);
471 SET_FLAG(zl
.message
, ZAPI_LABELS_HAS_BACKUPS
);
472 zl
.backup_nexthop_num
= count
;
474 SET_FLAG(znh
->flags
, ZAPI_NEXTHOP_FLAG_HAS_BACKUP
);
475 znh
->backup_num
= count
;
476 for (int i
= 0; i
< count
; i
++)
477 znh
->backup_idx
[i
] = i
;
481 (void)zebra_send_mpls_labels(zclient
, cmd
, &zl
);
484 static int isis_zebra_read(ZAPI_CALLBACK_ARGS
)
486 struct zapi_route api
;
487 struct isis
*isis
= NULL
;
489 isis
= isis_lookup_by_vrfid(vrf_id
);
494 if (zapi_route_decode(zclient
->ibuf
, &api
) < 0)
497 if (api
.prefix
.family
== AF_INET6
498 && IN6_IS_ADDR_LINKLOCAL(&api
.prefix
.u
.prefix6
))
502 * Avoid advertising a false default reachability. (A default
503 * route installed by IS-IS gets redistributed from zebra back
504 * into IS-IS causing us to start advertising default reachabity
505 * without this check)
507 if (api
.prefix
.prefixlen
== 0
508 && api
.src_prefix
.prefixlen
== 0
509 && api
.type
== PROTO_TYPE
) {
510 cmd
= ZEBRA_REDISTRIBUTE_ROUTE_DEL
;
513 if (cmd
== ZEBRA_REDISTRIBUTE_ROUTE_ADD
)
514 isis_redist_add(isis
, api
.type
, &api
.prefix
, &api
.src_prefix
,
515 api
.distance
, api
.metric
, api
.tag
);
517 isis_redist_delete(isis
, api
.type
, &api
.prefix
,
523 int isis_distribute_list_update(int routetype
)
528 void isis_zebra_redistribute_set(afi_t afi
, int type
, vrf_id_t vrf_id
)
530 if (type
== DEFAULT_ROUTE
)
531 zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_ADD
,
532 zclient
, afi
, vrf_id
);
534 zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD
, zclient
, afi
, type
,
538 void isis_zebra_redistribute_unset(afi_t afi
, int type
, vrf_id_t vrf_id
)
540 if (type
== DEFAULT_ROUTE
)
541 zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_DELETE
,
542 zclient
, afi
, vrf_id
);
544 zclient_redistribute(ZEBRA_REDISTRIBUTE_DELETE
, zclient
, afi
,
549 * Register RLFA with LDP.
551 int isis_zebra_rlfa_register(struct isis_spftree
*spftree
, struct rlfa
*rlfa
)
553 struct isis_area
*area
= spftree
->area
;
554 struct zapi_rlfa_request zr
= {};
560 zr
.igp
.vrf_id
= area
->isis
->vrf_id
;
561 zr
.igp
.protocol
= ZEBRA_ROUTE_ISIS
;
562 strlcpy(zr
.igp
.isis
.area_tag
, area
->area_tag
,
563 sizeof(zr
.igp
.isis
.area_tag
));
564 zr
.igp
.isis
.spf
.tree_id
= spftree
->tree_id
;
565 zr
.igp
.isis
.spf
.level
= spftree
->level
;
566 zr
.igp
.isis
.spf
.run_id
= spftree
->runcount
;
567 zr
.destination
= rlfa
->prefix
;
568 zr
.pq_address
= rlfa
->pq_address
;
570 zlog_debug("ISIS-LFA: registering RLFA %pFX@%pI4 with LDP",
571 &rlfa
->prefix
, &rlfa
->pq_address
);
573 ret
= zclient_send_opaque_unicast(zclient
, LDP_RLFA_REGISTER
,
574 ZEBRA_ROUTE_LDP
, 0, 0,
575 (const uint8_t *)&zr
, sizeof(zr
));
576 if (ret
== ZCLIENT_SEND_FAILURE
) {
577 zlog_warn("ISIS-LFA: failed to register RLFA with LDP");
585 * Unregister all RLFAs from the given SPF tree with LDP.
587 void isis_zebra_rlfa_unregister_all(struct isis_spftree
*spftree
)
589 struct isis_area
*area
= spftree
->area
;
590 struct zapi_rlfa_igp igp
= {};
593 if (!zclient
|| spftree
->type
!= SPF_TYPE_FORWARD
594 || CHECK_FLAG(spftree
->flags
, F_SPFTREE_NO_ADJACENCIES
))
598 zlog_debug("ISIS-LFA: unregistering all RLFAs with LDP");
600 igp
.vrf_id
= area
->isis
->vrf_id
;
601 igp
.protocol
= ZEBRA_ROUTE_ISIS
;
602 strlcpy(igp
.isis
.area_tag
, area
->area_tag
, sizeof(igp
.isis
.area_tag
));
603 igp
.isis
.spf
.tree_id
= spftree
->tree_id
;
604 igp
.isis
.spf
.level
= spftree
->level
;
605 igp
.isis
.spf
.run_id
= spftree
->runcount
;
607 ret
= zclient_send_opaque_unicast(zclient
, LDP_RLFA_UNREGISTER_ALL
,
608 ZEBRA_ROUTE_LDP
, 0, 0,
609 (const uint8_t *)&igp
, sizeof(igp
));
610 if (ret
== ZCLIENT_SEND_FAILURE
)
611 zlog_warn("ISIS-LFA: failed to unregister RLFA with LDP");
614 /* Label Manager Functions */
617 * Check if Label Manager is Ready or not.
619 * @return True if Label Manager is ready, False otherwise
621 bool isis_zebra_label_manager_ready(void)
623 return (zclient_sync
->sock
> 0);
627 * Request Label Range to the Label Manager.
629 * @param base base label of the label range to request
630 * @param chunk_size size of the label range to request
632 * @return 0 on success, -1 on failure
634 int isis_zebra_request_label_range(uint32_t base
, uint32_t chunk_size
)
639 if (zclient_sync
->sock
< 0)
642 ret
= lm_get_label_chunk(zclient_sync
, 0, base
, chunk_size
, &start
,
645 zlog_warn("%s: error getting label range!", __func__
);
653 * Release Label Range to the Label Manager.
655 * @param start start of label range to release
656 * @param end end of label range to release
658 * @return 0 on success, -1 otherwise
660 int isis_zebra_release_label_range(uint32_t start
, uint32_t end
)
664 if (zclient_sync
->sock
< 0)
667 ret
= lm_release_label_chunk(zclient_sync
, start
, end
);
669 zlog_warn("%s: error releasing label range!", __func__
);
677 * Connect to the Label Manager.
679 * @return 0 on success, -1 otherwise
681 int isis_zebra_label_manager_connect(void)
683 /* Connect to label manager. */
684 if (zclient_socket_connect(zclient_sync
) < 0) {
685 zlog_warn("%s: failed connecting synchronous zclient!",
689 /* make socket non-blocking */
690 set_nonblocking(zclient_sync
->sock
);
692 /* Send hello to notify zebra this is a synchronous client */
693 if (zclient_send_hello(zclient_sync
) == ZCLIENT_SEND_FAILURE
) {
694 zlog_warn("%s: failed sending hello for synchronous zclient!",
696 close(zclient_sync
->sock
);
697 zclient_sync
->sock
= -1;
701 /* Connect to label manager */
702 if (lm_label_manager_connect(zclient_sync
, 0) != 0) {
703 zlog_warn("%s: failed connecting to label manager!", __func__
);
704 if (zclient_sync
->sock
> 0) {
705 close(zclient_sync
->sock
);
706 zclient_sync
->sock
= -1;
711 sr_debug("ISIS-Sr: Successfully connected to the Label Manager");
716 void isis_zebra_vrf_register(struct isis
*isis
)
718 if (!zclient
|| zclient
->sock
< 0 || !isis
)
721 if (isis
->vrf_id
!= VRF_UNKNOWN
) {
723 zlog_debug("%s: Register VRF %s id %u", __func__
,
724 isis
->name
, isis
->vrf_id
);
725 zclient_send_reg_requests(zclient
, isis
->vrf_id
);
729 void isis_zebra_vrf_deregister(struct isis
*isis
)
731 if (!zclient
|| zclient
->sock
< 0 || !isis
)
734 if (isis
->vrf_id
!= VRF_UNKNOWN
) {
736 zlog_debug("%s: Deregister VRF %s id %u", __func__
,
737 isis
->name
, isis
->vrf_id
);
738 zclient_send_dereg_requests(zclient
, isis
->vrf_id
);
742 static void isis_zebra_connected(struct zclient
*zclient
)
744 zclient_send_reg_requests(zclient
, VRF_DEFAULT
);
745 zclient_register_opaque(zclient
, LDP_RLFA_LABELS
);
746 zclient_register_opaque(zclient
, LDP_IGP_SYNC_IF_STATE_UPDATE
);
747 zclient_register_opaque(zclient
, LDP_IGP_SYNC_ANNOUNCE_UPDATE
);
748 bfd_client_sendmsg(zclient
, ZEBRA_BFD_CLIENT_REGISTER
, VRF_DEFAULT
);
752 * Register / unregister Link State ZAPI Opaque Message
754 * @param up True to register, false to unregister
756 * @return 0 if success, -1 otherwise
758 int isis_zebra_ls_register(bool up
)
763 rc
= ls_register(zclient
, true);
765 rc
= ls_unregister(zclient
, true);
771 * opaque messages between processes
773 static int isis_opaque_msg_handler(ZAPI_CALLBACK_ARGS
)
776 struct zapi_opaque_msg info
;
777 struct zapi_opaque_reg_info dst
;
778 struct ldp_igp_sync_if_state state
;
779 struct ldp_igp_sync_announce announce
;
780 struct zapi_rlfa_response rlfa
;
784 if (zclient_opaque_decode(s
, &info
) != 0)
788 case LINK_STATE_SYNC
:
789 STREAM_GETC(s
, dst
.proto
);
790 STREAM_GETW(s
, dst
.instance
);
791 STREAM_GETL(s
, dst
.session_id
);
792 dst
.type
= LINK_STATE_SYNC
;
793 ret
= isis_te_sync_ted(dst
);
795 case LDP_IGP_SYNC_IF_STATE_UPDATE
:
796 STREAM_GET(&state
, s
, sizeof(state
));
797 ret
= isis_ldp_sync_state_update(state
);
799 case LDP_IGP_SYNC_ANNOUNCE_UPDATE
:
800 STREAM_GET(&announce
, s
, sizeof(announce
));
801 ret
= isis_ldp_sync_announce_update(announce
);
803 case LDP_RLFA_LABELS
:
804 STREAM_GET(&rlfa
, s
, sizeof(rlfa
));
805 isis_rlfa_process_ldp_response(&rlfa
);
816 static int isis_zebra_client_close_notify(ZAPI_CALLBACK_ARGS
)
820 struct zapi_client_close_info info
;
822 if (zapi_client_close_notify_decode(zclient
->ibuf
, &info
) < 0)
825 isis_ldp_sync_handle_client_close(&info
);
826 isis_ldp_rlfa_handle_client_close(&info
);
831 static zclient_handler
*const isis_handlers
[] = {
832 [ZEBRA_ROUTER_ID_UPDATE
] = isis_router_id_update_zebra
,
833 [ZEBRA_INTERFACE_ADDRESS_ADD
] = isis_zebra_if_address_add
,
834 [ZEBRA_INTERFACE_ADDRESS_DELETE
] = isis_zebra_if_address_del
,
835 [ZEBRA_INTERFACE_LINK_PARAMS
] = isis_zebra_link_params
,
836 [ZEBRA_REDISTRIBUTE_ROUTE_ADD
] = isis_zebra_read
,
837 [ZEBRA_REDISTRIBUTE_ROUTE_DEL
] = isis_zebra_read
,
839 [ZEBRA_OPAQUE_MESSAGE
] = isis_opaque_msg_handler
,
841 [ZEBRA_CLIENT_CLOSE_NOTIFY
] = isis_zebra_client_close_notify
,
844 void isis_zebra_init(struct thread_master
*master
, int instance
)
846 /* Initialize asynchronous zclient. */
847 zclient
= zclient_new(master
, &zclient_options_default
, isis_handlers
,
848 array_size(isis_handlers
));
849 zclient_init(zclient
, PROTO_TYPE
, 0, &isisd_privs
);
850 zclient
->zebra_connected
= isis_zebra_connected
;
852 /* Initialize special zclient for synchronous message exchanges. */
853 struct zclient_options options
= zclient_options_default
;
854 options
.synchronous
= true;
855 zclient_sync
= zclient_new(master
, &options
, NULL
, 0);
856 zclient_sync
->sock
= -1;
857 zclient_sync
->redist_default
= ZEBRA_ROUTE_ISIS
;
858 zclient_sync
->instance
= instance
;
860 * session_id must be different from default value (0) to distinguish
861 * the asynchronous socket from the synchronous one
863 zclient_sync
->session_id
= 1;
864 zclient_sync
->privs
= &isisd_privs
;
867 void isis_zebra_stop(void)
869 zclient_unregister_opaque(zclient
, LDP_RLFA_LABELS
);
870 zclient_unregister_opaque(zclient
, LDP_IGP_SYNC_IF_STATE_UPDATE
);
871 zclient_unregister_opaque(zclient
, LDP_IGP_SYNC_ANNOUNCE_UPDATE
);
872 zclient_stop(zclient_sync
);
873 zclient_free(zclient_sync
);
874 zclient_stop(zclient
);
875 zclient_free(zclient
);