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
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public Licenseas published by the Free
10 * Software Foundation; either version 2 of the License, or (at your option)
13 * This program is distributed in the hope that it will be useful,but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
36 #include "isisd/dict.h"
37 #include "isisd/isis_constants.h"
38 #include "isisd/isis_common.h"
39 #include "isisd/isis_flags.h"
40 #include "isisd/isis_misc.h"
41 #include "isisd/isis_circuit.h"
42 #include "isisd/isis_tlv.h"
43 #include "isisd/isisd.h"
44 #include "isisd/isis_circuit.h"
45 #include "isisd/isis_csm.h"
46 #include "isisd/isis_lsp.h"
47 #include "isisd/isis_route.h"
48 #include "isisd/isis_zebra.h"
50 struct zclient
*zclient
= NULL
;
52 /* Router-id update message from zebra. */
54 isis_router_id_update_zebra (int command
, struct zclient
*zclient
,
57 struct isis_area
*area
;
58 struct listnode
*node
;
59 struct prefix router_id
;
61 zebra_router_id_update_read (zclient
->ibuf
, &router_id
);
62 if (isis
->router_id
== router_id
.u
.prefix4
.s_addr
)
65 isis
->router_id
= router_id
.u
.prefix4
.s_addr
;
66 for (ALL_LIST_ELEMENTS_RO (isis
->area_list
, node
, area
))
67 if (listcount (area
->area_addrs
) > 0)
68 lsp_regenerate_schedule (area
, area
->is_type
, 0);
74 isis_zebra_if_add (int command
, struct zclient
*zclient
, zebra_size_t length
)
76 struct interface
*ifp
;
78 ifp
= zebra_interface_add_read (zclient
->ibuf
);
80 if (isis
->debugs
& DEBUG_ZEBRA
)
81 zlog_debug ("Zebra I/F add: %s index %d flags %ld metric %d mtu %d",
82 ifp
->name
, ifp
->ifindex
, (long)ifp
->flags
, ifp
->metric
, ifp
->mtu
);
84 if (if_is_operative (ifp
))
85 isis_csm_state_change (IF_UP_FROM_Z
, circuit_scan_by_ifp (ifp
), ifp
);
91 isis_zebra_if_del (int command
, struct zclient
*zclient
, zebra_size_t length
)
93 struct interface
*ifp
;
97 ifp
= zebra_interface_state_read (s
);
102 if (if_is_operative (ifp
))
103 zlog_warn ("Zebra: got delete of %s, but interface is still up",
106 if (isis
->debugs
& DEBUG_ZEBRA
)
107 zlog_debug ("Zebra I/F delete: %s index %d flags %ld metric %d mtu %d",
108 ifp
->name
, ifp
->ifindex
, (long)ifp
->flags
, ifp
->metric
, ifp
->mtu
);
110 isis_csm_state_change (IF_DOWN_FROM_Z
, circuit_scan_by_ifp (ifp
), ifp
);
112 /* Cannot call if_delete because we should retain the pseudo interface
113 in case there is configuration info attached to it. */
114 if_delete_retain(ifp
);
116 ifp
->ifindex
= IFINDEX_INTERNAL
;
122 isis_zebra_if_state_up (int command
, struct zclient
*zclient
,
125 struct interface
*ifp
;
127 ifp
= zebra_interface_state_read (zclient
->ibuf
);
132 isis_csm_state_change (IF_UP_FROM_Z
, circuit_scan_by_ifp (ifp
), ifp
);
138 isis_zebra_if_state_down (int command
, struct zclient
*zclient
,
141 struct interface
*ifp
;
142 struct isis_circuit
*circuit
;
144 ifp
= zebra_interface_state_read (zclient
->ibuf
);
149 circuit
= isis_csm_state_change (IF_DOWN_FROM_Z
, circuit_scan_by_ifp (ifp
),
152 SET_FLAG(circuit
->flags
, ISIS_CIRCUIT_FLAPPED_AFTER_SPF
);
158 isis_zebra_if_address_add (int command
, struct zclient
*zclient
,
165 c
= zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_ADD
,
173 prefix2str (p
, buf
, BUFSIZ
);
175 if (p
->family
== AF_INET
)
176 zlog_debug ("connected IP address %s", buf
);
178 if (p
->family
== AF_INET6
)
179 zlog_debug ("connected IPv6 address %s", buf
);
180 #endif /* HAVE_IPV6 */
181 #endif /* EXTREME_DEBUG */
182 if (if_is_operative (c
->ifp
))
183 isis_circuit_add_addr (circuit_scan_by_ifp (c
->ifp
), c
);
189 isis_zebra_if_address_del (int command
, struct zclient
*client
,
193 struct interface
*ifp
;
197 #endif /* EXTREME_DEBUG */
199 c
= zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_DELETE
,
209 prefix2str (p
, buf
, BUFSIZ
);
211 if (p
->family
== AF_INET
)
212 zlog_debug ("disconnected IP address %s", buf
);
214 if (p
->family
== AF_INET6
)
215 zlog_debug ("disconnected IPv6 address %s", buf
);
216 #endif /* HAVE_IPV6 */
217 #endif /* EXTREME_DEBUG */
219 if (if_is_operative (ifp
))
220 isis_circuit_del_addr (circuit_scan_by_ifp (ifp
), c
);
227 isis_zebra_route_add_ipv4 (struct prefix
*prefix
,
228 struct isis_route_info
*route_info
)
230 u_char message
, flags
;
232 struct stream
*stream
;
233 struct isis_nexthop
*nexthop
;
234 struct listnode
*node
;
236 if (CHECK_FLAG (route_info
->flag
, ISIS_ROUTE_FLAG_ZEBRA_SYNCED
))
239 if (zclient
->redist
[AFI_IP
][ZEBRA_ROUTE_ISIS
].enabled
)
244 SET_FLAG (message
, ZAPI_MESSAGE_NEXTHOP
);
245 SET_FLAG (message
, ZAPI_MESSAGE_METRIC
);
247 SET_FLAG (message
, ZAPI_MESSAGE_DISTANCE
);
250 stream
= zclient
->obuf
;
251 stream_reset (stream
);
252 zclient_create_header (stream
, ZEBRA_IPV4_ROUTE_ADD
);
254 stream_putc (stream
, ZEBRA_ROUTE_ISIS
);
256 stream_putw (stream
, 0);
258 stream_putc (stream
, flags
);
260 stream_putc (stream
, message
);
262 stream_putw (stream
, SAFI_UNICAST
);
263 /* prefix information */
264 psize
= PSIZE (prefix
->prefixlen
);
265 stream_putc (stream
, prefix
->prefixlen
);
266 stream_write (stream
, (u_char
*) & prefix
->u
.prefix4
, psize
);
268 stream_putc (stream
, listcount (route_info
->nexthops
));
270 /* Nexthop, ifindex, distance and metric information */
271 for (ALL_LIST_ELEMENTS_RO (route_info
->nexthops
, node
, nexthop
))
273 /* FIXME: can it be ? */
274 if (nexthop
->ip
.s_addr
!= INADDR_ANY
)
276 stream_putc (stream
, ZEBRA_NEXTHOP_IPV4
);
277 stream_put_in_addr (stream
, &nexthop
->ip
);
281 stream_putc (stream
, ZEBRA_NEXTHOP_IFINDEX
);
282 stream_putl (stream
, nexthop
->ifindex
);
286 if (CHECK_FLAG (message
, ZAPI_MESSAGE_DISTANCE
))
287 stream_putc (stream
, route_info
->depth
);
289 if (CHECK_FLAG (message
, ZAPI_MESSAGE_METRIC
))
290 stream_putl (stream
, route_info
->cost
);
292 stream_putw_at (stream
, 0, stream_get_endp (stream
));
293 zclient_send_message(zclient
);
294 SET_FLAG (route_info
->flag
, ISIS_ROUTE_FLAG_ZEBRA_SYNCED
);
295 UNSET_FLAG (route_info
->flag
, ISIS_ROUTE_FLAG_ZEBRA_RESYNC
);
300 isis_zebra_route_del_ipv4 (struct prefix
*prefix
,
301 struct isis_route_info
*route_info
)
303 struct zapi_ipv4 api
;
304 struct prefix_ipv4 prefix4
;
306 if (zclient
->redist
[AFI_IP
][ZEBRA_ROUTE_ISIS
].enabled
)
308 api
.type
= ZEBRA_ROUTE_ISIS
;
312 api
.safi
= SAFI_UNICAST
;
313 prefix4
.family
= AF_INET
;
314 prefix4
.prefixlen
= prefix
->prefixlen
;
315 prefix4
.prefix
= prefix
->u
.prefix4
;
316 zapi_ipv4_route (ZEBRA_IPV4_ROUTE_DELETE
, zclient
, &prefix4
, &api
);
318 UNSET_FLAG (route_info
->flag
, ISIS_ROUTE_FLAG_ZEBRA_SYNCED
);
325 isis_zebra_route_add_ipv6 (struct prefix
*prefix
,
326 struct isis_route_info
*route_info
)
328 struct zapi_ipv6 api
;
329 struct in6_addr
**nexthop_list
;
330 unsigned int *ifindex_list
;
331 struct isis_nexthop6
*nexthop6
;
333 struct listnode
*node
;
334 struct prefix_ipv6 prefix6
;
336 if (CHECK_FLAG (route_info
->flag
, ISIS_ROUTE_FLAG_ZEBRA_SYNCED
))
339 api
.type
= ZEBRA_ROUTE_ISIS
;
343 api
.safi
= SAFI_UNICAST
;
344 SET_FLAG (api
.message
, ZAPI_MESSAGE_NEXTHOP
);
345 SET_FLAG (api
.message
, ZAPI_MESSAGE_IFINDEX
);
346 SET_FLAG (api
.message
, ZAPI_MESSAGE_METRIC
);
347 api
.metric
= route_info
->cost
;
349 SET_FLAG (api
.message
, ZAPI_MESSAGE_DISTANCE
);
350 api
.distance
= route_info
->depth
;
352 api
.nexthop_num
= listcount (route_info
->nexthops6
);
353 api
.ifindex_num
= listcount (route_info
->nexthops6
);
355 /* allocate memory for nexthop_list */
356 size
= sizeof (struct isis_nexthop6
*) * listcount (route_info
->nexthops6
);
357 nexthop_list
= (struct in6_addr
**) XMALLOC (MTYPE_ISIS_TMP
, size
);
360 zlog_err ("isis_zebra_add_route_ipv6: out of memory!");
364 /* allocate memory for ifindex_list */
365 size
= sizeof (unsigned int) * listcount (route_info
->nexthops6
);
366 ifindex_list
= (unsigned int *) XMALLOC (MTYPE_ISIS_TMP
, size
);
369 zlog_err ("isis_zebra_add_route_ipv6: out of memory!");
370 XFREE (MTYPE_ISIS_TMP
, nexthop_list
);
374 /* for each nexthop */
376 for (ALL_LIST_ELEMENTS_RO (route_info
->nexthops6
, node
, nexthop6
))
378 if (!IN6_IS_ADDR_LINKLOCAL (&nexthop6
->ip6
) &&
379 !IN6_IS_ADDR_UNSPECIFIED (&nexthop6
->ip6
))
386 nexthop_list
[i
] = &nexthop6
->ip6
;
387 ifindex_list
[i
] = nexthop6
->ifindex
;
391 api
.nexthop
= nexthop_list
;
392 api
.ifindex
= ifindex_list
;
394 if (api
.nexthop_num
&& api
.ifindex_num
)
396 prefix6
.family
= AF_INET6
;
397 prefix6
.prefixlen
= prefix
->prefixlen
;
398 memcpy (&prefix6
.prefix
, &prefix
->u
.prefix6
, sizeof (struct in6_addr
));
399 zapi_ipv6_route (ZEBRA_IPV6_ROUTE_ADD
, zclient
, &prefix6
, &api
);
400 SET_FLAG (route_info
->flag
, ISIS_ROUTE_FLAG_ZEBRA_SYNCED
);
401 UNSET_FLAG (route_info
->flag
, ISIS_ROUTE_FLAG_ZEBRA_RESYNC
);
404 XFREE (MTYPE_ISIS_TMP
, nexthop_list
);
405 XFREE (MTYPE_ISIS_TMP
, ifindex_list
);
411 isis_zebra_route_del_ipv6 (struct prefix
*prefix
,
412 struct isis_route_info
*route_info
)
414 struct zapi_ipv6 api
;
415 struct in6_addr
**nexthop_list
;
416 unsigned int *ifindex_list
;
417 struct isis_nexthop6
*nexthop6
;
419 struct listnode
*node
;
420 struct prefix_ipv6 prefix6
;
422 if (CHECK_FLAG (route_info
->flag
, ISIS_ROUTE_FLAG_ZEBRA_SYNCED
))
425 api
.type
= ZEBRA_ROUTE_ISIS
;
429 api
.safi
= SAFI_UNICAST
;
430 SET_FLAG (api
.message
, ZAPI_MESSAGE_NEXTHOP
);
431 SET_FLAG (api
.message
, ZAPI_MESSAGE_IFINDEX
);
432 api
.nexthop_num
= listcount (route_info
->nexthops6
);
433 api
.ifindex_num
= listcount (route_info
->nexthops6
);
435 /* allocate memory for nexthop_list */
436 size
= sizeof (struct isis_nexthop6
*) * listcount (route_info
->nexthops6
);
437 nexthop_list
= (struct in6_addr
**) XMALLOC (MTYPE_ISIS_TMP
, size
);
440 zlog_err ("isis_zebra_route_del_ipv6: out of memory!");
444 /* allocate memory for ifindex_list */
445 size
= sizeof (unsigned int) * listcount (route_info
->nexthops6
);
446 ifindex_list
= (unsigned int *) XMALLOC (MTYPE_ISIS_TMP
, size
);
449 zlog_err ("isis_zebra_route_del_ipv6: out of memory!");
450 XFREE (MTYPE_ISIS_TMP
, nexthop_list
);
454 /* for each nexthop */
456 for (ALL_LIST_ELEMENTS_RO (route_info
->nexthops6
, node
, nexthop6
))
458 if (!IN6_IS_ADDR_LINKLOCAL (&nexthop6
->ip6
) &&
459 !IN6_IS_ADDR_UNSPECIFIED (&nexthop6
->ip6
))
466 nexthop_list
[i
] = &nexthop6
->ip6
;
467 ifindex_list
[i
] = nexthop6
->ifindex
;
471 api
.nexthop
= nexthop_list
;
472 api
.ifindex
= ifindex_list
;
474 if (api
.nexthop_num
&& api
.ifindex_num
)
476 prefix6
.family
= AF_INET6
;
477 prefix6
.prefixlen
= prefix
->prefixlen
;
478 memcpy (&prefix6
.prefix
, &prefix
->u
.prefix6
, sizeof (struct in6_addr
));
479 zapi_ipv6_route (ZEBRA_IPV6_ROUTE_DELETE
, zclient
, &prefix6
, &api
);
480 UNSET_FLAG (route_info
->flag
, ISIS_ROUTE_FLAG_ZEBRA_SYNCED
);
483 XFREE (MTYPE_ISIS_TMP
, nexthop_list
);
484 XFREE (MTYPE_ISIS_TMP
, ifindex_list
);
487 #endif /* HAVE_IPV6 */
490 isis_zebra_route_update (struct prefix
*prefix
,
491 struct isis_route_info
*route_info
)
493 if (zclient
->sock
< 0)
496 if ((prefix
->family
== AF_INET
&& !zclient
->redist
[AFI_IP
][ZEBRA_ROUTE_ISIS
].enabled
) ||
497 (prefix
->family
== AF_INET6
&& !zclient
->redist
[AFI_IP6
][ZEBRA_ROUTE_ISIS
].enabled
))
500 if (CHECK_FLAG (route_info
->flag
, ISIS_ROUTE_FLAG_ACTIVE
))
502 if (prefix
->family
== AF_INET
)
503 isis_zebra_route_add_ipv4 (prefix
, route_info
);
505 else if (prefix
->family
== AF_INET6
)
506 isis_zebra_route_add_ipv6 (prefix
, route_info
);
507 #endif /* HAVE_IPV6 */
511 if (prefix
->family
== AF_INET
)
512 isis_zebra_route_del_ipv4 (prefix
, route_info
);
514 else if (prefix
->family
== AF_INET6
)
515 isis_zebra_route_del_ipv6 (prefix
, route_info
);
516 #endif /* HAVE_IPV6 */
522 isis_zebra_read_ipv4 (int command
, struct zclient
*zclient
,
525 struct stream
*stream
;
526 struct zapi_ipv4 api
;
527 struct prefix_ipv4 p
;
529 stream
= zclient
->ibuf
;
530 memset (&p
, 0, sizeof (struct prefix_ipv4
));
532 api
.type
= stream_getc (stream
);
533 api
.instance
= stream_getw (stream
);
534 api
.flags
= stream_getc (stream
);
535 api
.message
= stream_getc (stream
);
538 p
.prefixlen
= stream_getc (stream
);
539 stream_get (&p
.prefix
, stream
, PSIZE (p
.prefixlen
));
541 if (CHECK_FLAG (api
.message
, ZAPI_MESSAGE_NEXTHOP
))
543 api
.nexthop_num
= stream_getc (stream
);
544 (void)stream_get_ipv4 (stream
);
546 if (CHECK_FLAG (api
.message
, ZAPI_MESSAGE_IFINDEX
))
548 api
.ifindex_num
= stream_getc (stream
);
549 stream_getl (stream
);
551 if (CHECK_FLAG (api
.message
, ZAPI_MESSAGE_DISTANCE
))
552 api
.distance
= stream_getc (stream
);
553 if (CHECK_FLAG (api
.message
, ZAPI_MESSAGE_METRIC
))
554 api
.metric
= stream_getl (stream
);
558 if (command
== ZEBRA_IPV4_ROUTE_ADD
)
560 if (isis
->debugs
& DEBUG_ZEBRA
)
561 zlog_debug ("IPv4 Route add from Z");
569 isis_zebra_read_ipv6 (int command
, struct zclient
*zclient
,
576 #define ISIS_TYPE_IS_REDISTRIBUTED(T) \
577 T == ZEBRA_ROUTE_MAX ? zclient->default_information : \
578 (zclient->redist[AFI_IP][type].enabled || client->redist[AFI_IP6][type].enabled)
581 isis_distribute_list_update (int routetype
)
588 isis_redistribute_default_set (int routetype
, int metric_type
,
598 zclient
= zclient_new ();
599 zclient_init (zclient
, ZEBRA_ROUTE_ISIS
, 0);
600 zclient
->router_id_update
= isis_router_id_update_zebra
;
601 zclient
->interface_add
= isis_zebra_if_add
;
602 zclient
->interface_delete
= isis_zebra_if_del
;
603 zclient
->interface_up
= isis_zebra_if_state_up
;
604 zclient
->interface_down
= isis_zebra_if_state_down
;
605 zclient
->interface_address_add
= isis_zebra_if_address_add
;
606 zclient
->interface_address_delete
= isis_zebra_if_address_del
;
607 zclient
->ipv4_route_add
= isis_zebra_read_ipv4
;
608 zclient
->ipv4_route_delete
= isis_zebra_read_ipv4
;
610 zclient
->ipv6_route_add
= isis_zebra_read_ipv6
;
611 zclient
->ipv6_route_delete
= isis_zebra_read_ipv6
;
612 #endif /* HAVE_IPV6 */