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 "isisd/isis_constants.h"
42 #include "isisd/isis_common.h"
43 #include "isisd/isis_flags.h"
44 #include "isisd/isis_misc.h"
45 #include "isisd/isis_circuit.h"
46 #include "isisd/isisd.h"
47 #include "isisd/isis_circuit.h"
48 #include "isisd/isis_csm.h"
49 #include "isisd/isis_lsp.h"
50 #include "isisd/isis_route.h"
51 #include "isisd/isis_zebra.h"
52 #include "isisd/isis_te.h"
54 struct zclient
*zclient
= NULL
;
56 DEFINE_HOOK(isis_if_new_hook
, (struct interface
*ifp
), (ifp
))
58 /* Router-id update message from zebra. */
59 static int isis_router_id_update_zebra(ZAPI_CALLBACK_ARGS
)
61 struct isis_area
*area
;
62 struct listnode
*node
;
63 struct prefix router_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_add(ZAPI_CALLBACK_ARGS
)
79 struct interface
*ifp
;
81 ifp
= zebra_interface_add_read(zclient
->ibuf
, vrf_id
);
83 if (if_is_operative(ifp
))
84 isis_csm_state_change(IF_UP_FROM_Z
, circuit_scan_by_ifp(ifp
),
87 hook_call(isis_if_new_hook
, ifp
);
92 static int isis_zebra_if_del(ZAPI_CALLBACK_ARGS
)
94 struct interface
*ifp
;
98 ifp
= zebra_interface_state_read(s
, vrf_id
);
103 if (if_is_operative(ifp
))
104 zlog_warn("Zebra: got delete of %s, but interface is still up",
107 isis_csm_state_change(IF_DOWN_FROM_Z
, circuit_scan_by_ifp(ifp
), ifp
);
109 /* Cannot call if_delete because we should retain the pseudo interface
110 in case there is configuration info attached to it. */
111 if_delete_retain(ifp
);
113 if_set_index(ifp
, IFINDEX_INTERNAL
);
118 static int isis_zebra_if_state_up(ZAPI_CALLBACK_ARGS
)
120 struct interface
*ifp
;
122 ifp
= zebra_interface_state_read(zclient
->ibuf
, vrf_id
);
127 isis_csm_state_change(IF_UP_FROM_Z
, circuit_scan_by_ifp(ifp
), ifp
);
132 static int isis_zebra_if_state_down(ZAPI_CALLBACK_ARGS
)
134 struct interface
*ifp
;
135 struct isis_circuit
*circuit
;
137 ifp
= zebra_interface_state_read(zclient
->ibuf
, vrf_id
);
142 circuit
= isis_csm_state_change(IF_DOWN_FROM_Z
,
143 circuit_scan_by_ifp(ifp
), ifp
);
145 SET_FLAG(circuit
->flags
, ISIS_CIRCUIT_FLAPPED_AFTER_SPF
);
150 static int isis_zebra_if_address_add(ZAPI_CALLBACK_ARGS
)
154 char buf
[PREFIX2STR_BUFFER
];
156 c
= zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_ADD
,
157 zclient
->ibuf
, vrf_id
);
164 prefix2str(p
, buf
, sizeof(buf
));
166 if (p
->family
== AF_INET
)
167 zlog_debug("connected IP address %s", buf
);
168 if (p
->family
== AF_INET6
)
169 zlog_debug("connected IPv6 address %s", buf
);
170 #endif /* EXTREME_DEBUG */
171 if (if_is_operative(c
->ifp
))
172 isis_circuit_add_addr(circuit_scan_by_ifp(c
->ifp
), c
);
177 static int isis_zebra_if_address_del(ZAPI_CALLBACK_ARGS
)
180 struct interface
*ifp
;
183 char buf
[PREFIX2STR_BUFFER
];
184 #endif /* EXTREME_DEBUG */
186 c
= zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_DELETE
,
187 zclient
->ibuf
, vrf_id
);
196 prefix2str(p
, buf
, sizeof(buf
));
198 if (p
->family
== AF_INET
)
199 zlog_debug("disconnected IP address %s", buf
);
200 if (p
->family
== AF_INET6
)
201 zlog_debug("disconnected IPv6 address %s", buf
);
202 #endif /* EXTREME_DEBUG */
204 if (if_is_operative(ifp
))
205 isis_circuit_del_addr(circuit_scan_by_ifp(ifp
), c
);
211 static int isis_zebra_link_params(ZAPI_CALLBACK_ARGS
)
213 struct interface
*ifp
;
215 ifp
= zebra_interface_link_params_read(zclient
->ibuf
, vrf_id
);
221 isis_mpls_te_update(ifp
);
226 void isis_zebra_route_add_route(struct prefix
*prefix
,
227 struct prefix_ipv6
*src_p
,
228 struct isis_route_info
*route_info
)
230 struct zapi_route api
;
231 struct zapi_nexthop
*api_nh
;
232 struct isis_nexthop
*nexthop
;
233 struct listnode
*node
;
236 if (zclient
->sock
< 0)
239 memset(&api
, 0, sizeof(api
));
240 api
.vrf_id
= VRF_DEFAULT
;
241 api
.type
= PROTO_TYPE
;
242 api
.safi
= SAFI_UNICAST
;
243 api
.prefix
= *prefix
;
244 if (src_p
&& src_p
->prefixlen
) {
245 api
.src_prefix
= *src_p
;
246 SET_FLAG(api
.message
, ZAPI_MESSAGE_SRCPFX
);
248 SET_FLAG(api
.message
, ZAPI_MESSAGE_NEXTHOP
);
249 SET_FLAG(api
.message
, ZAPI_MESSAGE_METRIC
);
250 api
.metric
= route_info
->cost
;
252 SET_FLAG(api
.message
, ZAPI_MESSAGE_DISTANCE
);
253 api
.distance
= route_info
->depth
;
257 for (ALL_LIST_ELEMENTS_RO(route_info
->nexthops
, node
, nexthop
)) {
258 if (count
>= MULTIPATH_NUM
)
260 api_nh
= &api
.nexthops
[count
];
262 api_nh
->onlink
= true;
263 api_nh
->vrf_id
= VRF_DEFAULT
;
265 switch (nexthop
->family
) {
267 /* FIXME: can it be ? */
268 if (nexthop
->ip
.ipv4
.s_addr
!= INADDR_ANY
) {
269 api_nh
->type
= NEXTHOP_TYPE_IPV4_IFINDEX
;
270 api_nh
->gate
.ipv4
= nexthop
->ip
.ipv4
;
272 api_nh
->type
= NEXTHOP_TYPE_IFINDEX
;
276 if (!IN6_IS_ADDR_LINKLOCAL(&nexthop
->ip
.ipv6
)
277 && !IN6_IS_ADDR_UNSPECIFIED(&nexthop
->ip
.ipv6
)) {
280 api_nh
->gate
.ipv6
= nexthop
->ip
.ipv6
;
281 api_nh
->type
= NEXTHOP_TYPE_IPV6_IFINDEX
;
284 flog_err(EC_LIB_DEVELOPMENT
,
285 "%s: unknown address family [%d]", __func__
,
290 api_nh
->ifindex
= nexthop
->ifindex
;
296 api
.nexthop_num
= count
;
298 zclient_route_send(ZEBRA_ROUTE_ADD
, zclient
, &api
);
301 void isis_zebra_route_del_route(struct prefix
*prefix
,
302 struct prefix_ipv6
*src_p
,
303 struct isis_route_info
*route_info
)
305 struct zapi_route api
;
307 if (zclient
->sock
< 0)
310 memset(&api
, 0, sizeof(api
));
311 api
.vrf_id
= VRF_DEFAULT
;
312 api
.type
= PROTO_TYPE
;
313 api
.safi
= SAFI_UNICAST
;
314 api
.prefix
= *prefix
;
315 if (src_p
&& src_p
->prefixlen
) {
316 api
.src_prefix
= *src_p
;
317 SET_FLAG(api
.message
, ZAPI_MESSAGE_SRCPFX
);
320 zclient_route_send(ZEBRA_ROUTE_DELETE
, zclient
, &api
);
323 static int isis_zebra_read(ZAPI_CALLBACK_ARGS
)
325 struct zapi_route api
;
327 if (zapi_route_decode(zclient
->ibuf
, &api
) < 0)
330 if (api
.prefix
.family
== AF_INET6
331 && IN6_IS_ADDR_LINKLOCAL(&api
.prefix
.u
.prefix6
))
335 * Avoid advertising a false default reachability. (A default
336 * route installed by IS-IS gets redistributed from zebra back
337 * into IS-IS causing us to start advertising default reachabity
338 * without this check)
340 if (api
.prefix
.prefixlen
== 0
341 && api
.src_prefix
.prefixlen
== 0
342 && api
.type
== PROTO_TYPE
) {
343 cmd
= ZEBRA_REDISTRIBUTE_ROUTE_DEL
;
346 if (cmd
== ZEBRA_REDISTRIBUTE_ROUTE_ADD
)
347 isis_redist_add(api
.type
, &api
.prefix
, &api
.src_prefix
,
348 api
.distance
, api
.metric
);
350 isis_redist_delete(api
.type
, &api
.prefix
, &api
.src_prefix
);
355 int isis_distribute_list_update(int routetype
)
360 void isis_zebra_redistribute_set(afi_t afi
, int type
)
362 if (type
== DEFAULT_ROUTE
)
363 zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_ADD
,
364 zclient
, afi
, VRF_DEFAULT
);
366 zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD
, zclient
, afi
, type
,
370 void isis_zebra_redistribute_unset(afi_t afi
, int type
)
372 if (type
== DEFAULT_ROUTE
)
373 zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_DELETE
,
374 zclient
, afi
, VRF_DEFAULT
);
376 zclient_redistribute(ZEBRA_REDISTRIBUTE_DELETE
, zclient
, afi
,
377 type
, 0, VRF_DEFAULT
);
380 static void isis_zebra_connected(struct zclient
*zclient
)
382 zclient_send_reg_requests(zclient
, VRF_DEFAULT
);
385 void isis_zebra_init(struct thread_master
*master
)
387 zclient
= zclient_new(master
, &zclient_options_default
);
388 zclient_init(zclient
, PROTO_TYPE
, 0, &isisd_privs
);
389 zclient
->zebra_connected
= isis_zebra_connected
;
390 zclient
->router_id_update
= isis_router_id_update_zebra
;
391 zclient
->interface_add
= isis_zebra_if_add
;
392 zclient
->interface_delete
= isis_zebra_if_del
;
393 zclient
->interface_up
= isis_zebra_if_state_up
;
394 zclient
->interface_down
= isis_zebra_if_state_down
;
395 zclient
->interface_address_add
= isis_zebra_if_address_add
;
396 zclient
->interface_address_delete
= isis_zebra_if_address_del
;
397 zclient
->interface_link_params
= isis_zebra_link_params
;
398 zclient
->redistribute_route_add
= isis_zebra_read
;
399 zclient
->redistribute_route_del
= isis_zebra_read
;
404 void isis_zebra_stop(void)
406 zclient_stop(zclient
);
407 zclient_free(zclient
);