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
40 #include "isisd/dict.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 /* Router-id update message from zebra. */
57 static int isis_router_id_update_zebra(int command
, struct zclient
*zclient
,
58 zebra_size_t length
, vrf_id_t vrf_id
)
60 struct isis_area
*area
;
61 struct listnode
*node
;
62 struct prefix router_id
;
65 * If ISIS TE is enable, TE Router ID is set through specific command.
66 * See mpls_te_router_addr() command in isis_te.c
68 if (IS_MPLS_TE(isisMplsTE
))
71 zebra_router_id_update_read(zclient
->ibuf
, &router_id
);
72 if (isis
->router_id
== router_id
.u
.prefix4
.s_addr
)
75 isis
->router_id
= router_id
.u
.prefix4
.s_addr
;
76 for (ALL_LIST_ELEMENTS_RO(isis
->area_list
, node
, area
))
77 if (listcount(area
->area_addrs
) > 0)
78 lsp_regenerate_schedule(area
, area
->is_type
, 0);
83 static int isis_zebra_if_add(int command
, struct zclient
*zclient
,
84 zebra_size_t length
, vrf_id_t vrf_id
)
86 struct interface
*ifp
;
88 ifp
= zebra_interface_add_read(zclient
->ibuf
, vrf_id
);
90 if (isis
->debugs
& DEBUG_ZEBRA
)
92 "Zebra I/F add: %s index %d flags %ld metric %d mtu %d",
93 ifp
->name
, ifp
->ifindex
, (long)ifp
->flags
, ifp
->metric
,
96 if (if_is_operative(ifp
))
97 isis_csm_state_change(IF_UP_FROM_Z
, circuit_scan_by_ifp(ifp
),
103 static int isis_zebra_if_del(int command
, struct zclient
*zclient
,
104 zebra_size_t length
, vrf_id_t vrf_id
)
106 struct interface
*ifp
;
110 ifp
= zebra_interface_state_read(s
, vrf_id
);
115 if (if_is_operative(ifp
))
116 zlog_warn("Zebra: got delete of %s, but interface is still up",
119 if (isis
->debugs
& DEBUG_ZEBRA
)
121 "Zebra I/F delete: %s index %d flags %ld metric %d mtu %d",
122 ifp
->name
, ifp
->ifindex
, (long)ifp
->flags
, ifp
->metric
,
125 isis_csm_state_change(IF_DOWN_FROM_Z
, circuit_scan_by_ifp(ifp
), ifp
);
127 /* Cannot call if_delete because we should retain the pseudo interface
128 in case there is configuration info attached to it. */
129 if_delete_retain(ifp
);
131 if_set_index(ifp
, IFINDEX_INTERNAL
);
136 static int isis_zebra_if_state_up(int command
, struct zclient
*zclient
,
137 zebra_size_t length
, vrf_id_t vrf_id
)
139 struct interface
*ifp
;
141 ifp
= zebra_interface_state_read(zclient
->ibuf
, vrf_id
);
146 isis_csm_state_change(IF_UP_FROM_Z
, circuit_scan_by_ifp(ifp
), ifp
);
151 static int isis_zebra_if_state_down(int command
, struct zclient
*zclient
,
152 zebra_size_t length
, vrf_id_t vrf_id
)
154 struct interface
*ifp
;
155 struct isis_circuit
*circuit
;
157 ifp
= zebra_interface_state_read(zclient
->ibuf
, vrf_id
);
162 circuit
= isis_csm_state_change(IF_DOWN_FROM_Z
,
163 circuit_scan_by_ifp(ifp
), ifp
);
165 SET_FLAG(circuit
->flags
, ISIS_CIRCUIT_FLAPPED_AFTER_SPF
);
170 static int isis_zebra_if_address_add(int command
, struct zclient
*zclient
,
171 zebra_size_t length
, vrf_id_t vrf_id
)
175 char buf
[PREFIX2STR_BUFFER
];
177 c
= zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_ADD
,
178 zclient
->ibuf
, vrf_id
);
185 prefix2str(p
, buf
, sizeof(buf
));
187 if (p
->family
== AF_INET
)
188 zlog_debug("connected IP address %s", buf
);
189 if (p
->family
== AF_INET6
)
190 zlog_debug("connected IPv6 address %s", buf
);
191 #endif /* EXTREME_DEBUG */
192 if (if_is_operative(c
->ifp
))
193 isis_circuit_add_addr(circuit_scan_by_ifp(c
->ifp
), c
);
198 static int isis_zebra_if_address_del(int command
, struct zclient
*client
,
199 zebra_size_t length
, vrf_id_t vrf_id
)
202 struct interface
*ifp
;
205 char buf
[PREFIX2STR_BUFFER
];
206 #endif /* EXTREME_DEBUG */
208 c
= zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_DELETE
,
209 zclient
->ibuf
, vrf_id
);
218 prefix2str(p
, buf
, sizeof(buf
));
220 if (p
->family
== AF_INET
)
221 zlog_debug("disconnected IP address %s", buf
);
222 if (p
->family
== AF_INET6
)
223 zlog_debug("disconnected IPv6 address %s", buf
);
224 #endif /* EXTREME_DEBUG */
226 if (if_is_operative(ifp
))
227 isis_circuit_del_addr(circuit_scan_by_ifp(ifp
), c
);
233 static int isis_zebra_link_params(int command
, struct zclient
*zclient
,
236 struct interface
*ifp
;
238 ifp
= zebra_interface_link_params_read(zclient
->ibuf
);
244 isis_mpls_te_update(ifp
);
249 static void isis_zebra_route_add_route(struct prefix
*prefix
,
250 struct isis_route_info
*route_info
)
252 struct zapi_route api
;
253 struct zapi_nexthop
*api_nh
;
254 struct isis_nexthop
*nexthop
;
255 struct isis_nexthop6
*nexthop6
;
256 struct listnode
*node
;
259 if (CHECK_FLAG(route_info
->flag
, ISIS_ROUTE_FLAG_ZEBRA_SYNCED
))
262 memset(&api
, 0, sizeof(api
));
263 api
.vrf_id
= VRF_DEFAULT
;
264 api
.type
= ZEBRA_ROUTE_ISIS
;
265 api
.safi
= SAFI_UNICAST
;
266 api
.prefix
= *prefix
;
267 SET_FLAG(api
.message
, ZAPI_MESSAGE_NEXTHOP
);
268 SET_FLAG(api
.message
, ZAPI_MESSAGE_METRIC
);
269 api
.metric
= route_info
->cost
;
271 SET_FLAG(api
.message
, ZAPI_MESSAGE_DISTANCE
);
272 api
.distance
= route_info
->depth
;
276 switch (prefix
->family
) {
278 for (ALL_LIST_ELEMENTS_RO(route_info
->nexthops
, node
,
280 if (count
>= MULTIPATH_NUM
)
282 api_nh
= &api
.nexthops
[count
];
283 /* FIXME: can it be ? */
284 if (nexthop
->ip
.s_addr
!= INADDR_ANY
) {
285 api_nh
->type
= NEXTHOP_TYPE_IPV4_IFINDEX
;
286 api_nh
->gate
.ipv4
= nexthop
->ip
;
288 api_nh
->type
= NEXTHOP_TYPE_IFINDEX
;
290 api_nh
->ifindex
= nexthop
->ifindex
;
295 for (ALL_LIST_ELEMENTS_RO(route_info
->nexthops6
, node
,
297 if (count
>= MULTIPATH_NUM
)
299 if (!IN6_IS_ADDR_LINKLOCAL(&nexthop6
->ip6
)
300 && !IN6_IS_ADDR_UNSPECIFIED(&nexthop6
->ip6
)) {
304 api_nh
= &api
.nexthops
[count
];
305 api_nh
->gate
.ipv6
= nexthop6
->ip6
;
306 api_nh
->ifindex
= nexthop6
->ifindex
;
307 api_nh
->type
= NEXTHOP_TYPE_IPV6_IFINDEX
;
315 api
.nexthop_num
= count
;
317 zclient_route_send(ZEBRA_ROUTE_ADD
, zclient
, &api
);
318 SET_FLAG(route_info
->flag
, ISIS_ROUTE_FLAG_ZEBRA_SYNCED
);
319 UNSET_FLAG(route_info
->flag
, ISIS_ROUTE_FLAG_ZEBRA_RESYNC
);
322 static void isis_zebra_route_del_route(struct prefix
*prefix
,
323 struct isis_route_info
*route_info
)
325 struct zapi_route api
;
327 if (!CHECK_FLAG(route_info
->flag
, ISIS_ROUTE_FLAG_ZEBRA_SYNCED
))
330 memset(&api
, 0, sizeof(api
));
331 api
.vrf_id
= VRF_DEFAULT
;
332 api
.type
= ZEBRA_ROUTE_ISIS
;
333 api
.safi
= SAFI_UNICAST
;
334 api
.prefix
= *prefix
;
336 zclient_route_send(ZEBRA_ROUTE_DELETE
, zclient
, &api
);
337 UNSET_FLAG(route_info
->flag
, ISIS_ROUTE_FLAG_ZEBRA_SYNCED
);
340 void isis_zebra_route_update(struct prefix
*prefix
,
341 struct isis_route_info
*route_info
)
343 if (zclient
->sock
< 0)
346 if (CHECK_FLAG(route_info
->flag
, ISIS_ROUTE_FLAG_ACTIVE
))
347 isis_zebra_route_add_route(prefix
, route_info
);
349 isis_zebra_route_del_route(prefix
, route_info
);
352 static int isis_zebra_read(int command
, struct zclient
*zclient
,
353 zebra_size_t length
, vrf_id_t vrf_id
)
355 struct zapi_route api
;
357 if (zapi_route_decode(zclient
->ibuf
, &api
) < 0)
360 /* we completely ignore srcdest routes for now. */
361 if (CHECK_FLAG(api
.message
, ZAPI_MESSAGE_SRCPFX
))
365 * Avoid advertising a false default reachability. (A default
366 * route installed by IS-IS gets redistributed from zebra back
367 * into IS-IS causing us to start advertising default reachabity
368 * without this check)
370 if (api
.prefix
.prefixlen
== 0 && api
.type
== ZEBRA_ROUTE_ISIS
)
371 command
= ZEBRA_REDISTRIBUTE_ROUTE_DEL
;
373 if (command
== ZEBRA_REDISTRIBUTE_ROUTE_ADD
)
374 isis_redist_add(api
.type
, &api
.prefix
, api
.distance
,
377 isis_redist_delete(api
.type
, &api
.prefix
);
382 int isis_distribute_list_update(int routetype
)
387 void isis_zebra_redistribute_set(afi_t afi
, int type
)
389 if (type
== DEFAULT_ROUTE
)
390 zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_ADD
,
391 zclient
, VRF_DEFAULT
);
393 zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD
, zclient
, afi
, type
,
397 void isis_zebra_redistribute_unset(afi_t afi
, int type
)
399 if (type
== DEFAULT_ROUTE
)
400 zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_DELETE
,
401 zclient
, VRF_DEFAULT
);
403 zclient_redistribute(ZEBRA_REDISTRIBUTE_DELETE
, zclient
, afi
,
404 type
, 0, VRF_DEFAULT
);
407 static void isis_zebra_connected(struct zclient
*zclient
)
409 zclient_send_reg_requests(zclient
, VRF_DEFAULT
);
412 void isis_zebra_init(struct thread_master
*master
)
414 zclient
= zclient_new(master
);
415 zclient_init(zclient
, ZEBRA_ROUTE_ISIS
, 0);
416 zclient
->zebra_connected
= isis_zebra_connected
;
417 zclient
->router_id_update
= isis_router_id_update_zebra
;
418 zclient
->interface_add
= isis_zebra_if_add
;
419 zclient
->interface_delete
= isis_zebra_if_del
;
420 zclient
->interface_up
= isis_zebra_if_state_up
;
421 zclient
->interface_down
= isis_zebra_if_state_down
;
422 zclient
->interface_address_add
= isis_zebra_if_address_add
;
423 zclient
->interface_address_delete
= isis_zebra_if_address_del
;
424 zclient
->interface_link_params
= isis_zebra_link_params
;
425 zclient
->redistribute_route_add
= isis_zebra_read
;
426 zclient
->redistribute_route_del
= isis_zebra_read
;
431 void isis_zebra_stop(void)
433 zclient_stop(zclient
);
434 zclient_free(zclient
);