blob: 40157b59acdc06bc22c017a3c3b063c61657244a [file] [log] [blame]
jardineb5d44e2003-12-23 08:09:43 +00001/*
2 * IS-IS Rout(e)ing protocol - isis_zebra.c
3 *
4 * Copyright (C) 2001,2002 Sampo Saaristo
5 * Tampere University of Technology
6 * Institute of Communications Engineering
Christian Frankeacf98652015-11-12 14:24:22 +01007 * Copyright (C) 2013-2015 Christian Franke <chris@opensourcerouting.org>
jardineb5d44e2003-12-23 08:09:43 +00008 *
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)
12 * any later version.
13 *
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
17 * more details.
18
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 */
23
24#include <zebra.h>
jardineb5d44e2003-12-23 08:09:43 +000025
26#include "thread.h"
27#include "command.h"
28#include "memory.h"
29#include "log.h"
30#include "if.h"
31#include "network.h"
32#include "prefix.h"
33#include "zclient.h"
34#include "stream.h"
35#include "linklist.h"
Feng Luc99f3482014-10-16 09:52:36 +080036#include "vrf.h"
jardineb5d44e2003-12-23 08:09:43 +000037
hassoc89c05d2005-09-04 21:36:36 +000038#include "isisd/dict.h"
jardineb5d44e2003-12-23 08:09:43 +000039#include "isisd/isis_constants.h"
40#include "isisd/isis_common.h"
Josh Bailey3f045a02012-03-24 08:35:20 -070041#include "isisd/isis_flags.h"
42#include "isisd/isis_misc.h"
43#include "isisd/isis_circuit.h"
44#include "isisd/isis_tlv.h"
hassoc89c05d2005-09-04 21:36:36 +000045#include "isisd/isisd.h"
jardineb5d44e2003-12-23 08:09:43 +000046#include "isisd/isis_circuit.h"
47#include "isisd/isis_csm.h"
Josh Bailey3f045a02012-03-24 08:35:20 -070048#include "isisd/isis_lsp.h"
jardineb5d44e2003-12-23 08:09:43 +000049#include "isisd/isis_route.h"
50#include "isisd/isis_zebra.h"
Olivier Dugeon4f593572016-04-19 19:03:05 +020051#include "isisd/isis_te.h"
jardineb5d44e2003-12-23 08:09:43 +000052
53struct zclient *zclient = NULL;
54
hasso18a6dce2004-10-03 18:18:34 +000055/* Router-id update message from zebra. */
hasso92365882005-01-18 13:53:33 +000056static int
hasso18a6dce2004-10-03 18:18:34 +000057isis_router_id_update_zebra (int command, struct zclient *zclient,
Feng Luc99f3482014-10-16 09:52:36 +080058 zebra_size_t length, vrf_id_t vrf_id)
hasso18a6dce2004-10-03 18:18:34 +000059{
Josh Bailey3f045a02012-03-24 08:35:20 -070060 struct isis_area *area;
61 struct listnode *node;
hasso18a6dce2004-10-03 18:18:34 +000062 struct prefix router_id;
hasso18a6dce2004-10-03 18:18:34 +000063
Olivier Dugeon4f593572016-04-19 19:03:05 +020064 /*
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
67 */
68 if (IS_MPLS_TE(isisMplsTE))
69 return 0;
70
Josh Bailey3f045a02012-03-24 08:35:20 -070071 zebra_router_id_update_read (zclient->ibuf, &router_id);
72 if (isis->router_id == router_id.u.prefix4.s_addr)
73 return 0;
hasso18a6dce2004-10-03 18:18:34 +000074
Josh Bailey3f045a02012-03-24 08:35:20 -070075 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);
79
hasso18a6dce2004-10-03 18:18:34 +000080 return 0;
81}
jardineb5d44e2003-12-23 08:09:43 +000082
hasso92365882005-01-18 13:53:33 +000083static int
Feng Luc99f3482014-10-16 09:52:36 +080084isis_zebra_if_add (int command, struct zclient *zclient, zebra_size_t length,
85 vrf_id_t vrf_id)
jardineb5d44e2003-12-23 08:09:43 +000086{
87 struct interface *ifp;
88
Feng Luc99f3482014-10-16 09:52:36 +080089 ifp = zebra_interface_add_read (zclient->ibuf, vrf_id);
hassof390d2c2004-09-10 20:48:21 +000090
hassoc89c05d2005-09-04 21:36:36 +000091 if (isis->debugs & DEBUG_ZEBRA)
92 zlog_debug ("Zebra I/F add: %s index %d flags %ld metric %d mtu %d",
Paul Jakma41b36e92006-12-08 01:09:50 +000093 ifp->name, ifp->ifindex, (long)ifp->flags, ifp->metric, ifp->mtu);
hassof390d2c2004-09-10 20:48:21 +000094
hassob30c5e62004-12-29 20:06:41 +000095 if (if_is_operative (ifp))
jardineb5d44e2003-12-23 08:09:43 +000096 isis_csm_state_change (IF_UP_FROM_Z, circuit_scan_by_ifp (ifp), ifp);
hassof390d2c2004-09-10 20:48:21 +000097
jardineb5d44e2003-12-23 08:09:43 +000098 return 0;
99}
100
hasso92365882005-01-18 13:53:33 +0000101static int
Feng Luc99f3482014-10-16 09:52:36 +0800102isis_zebra_if_del (int command, struct zclient *zclient, zebra_size_t length,
103 vrf_id_t vrf_id)
jardineb5d44e2003-12-23 08:09:43 +0000104{
105 struct interface *ifp;
106 struct stream *s;
107
108 s = zclient->ibuf;
Feng Luc99f3482014-10-16 09:52:36 +0800109 ifp = zebra_interface_state_read (s, vrf_id);
hassof390d2c2004-09-10 20:48:21 +0000110
jardineb5d44e2003-12-23 08:09:43 +0000111 if (!ifp)
112 return 0;
113
hassob30c5e62004-12-29 20:06:41 +0000114 if (if_is_operative (ifp))
jardineb5d44e2003-12-23 08:09:43 +0000115 zlog_warn ("Zebra: got delete of %s, but interface is still up",
hassof390d2c2004-09-10 20:48:21 +0000116 ifp->name);
jardineb5d44e2003-12-23 08:09:43 +0000117
hassoc89c05d2005-09-04 21:36:36 +0000118 if (isis->debugs & DEBUG_ZEBRA)
119 zlog_debug ("Zebra I/F delete: %s index %d flags %ld metric %d mtu %d",
Paul Jakma41b36e92006-12-08 01:09:50 +0000120 ifp->name, ifp->ifindex, (long)ifp->flags, ifp->metric, ifp->mtu);
jardineb5d44e2003-12-23 08:09:43 +0000121
Josh Bailey3f045a02012-03-24 08:35:20 -0700122 isis_csm_state_change (IF_DOWN_FROM_Z, circuit_scan_by_ifp (ifp), ifp);
ajsd2fc8892005-04-02 18:38:43 +0000123
124 /* Cannot call if_delete because we should retain the pseudo interface
125 in case there is configuration info attached to it. */
126 if_delete_retain(ifp);
hassof390d2c2004-09-10 20:48:21 +0000127
ajsd2fc8892005-04-02 18:38:43 +0000128 ifp->ifindex = IFINDEX_INTERNAL;
129
jardineb5d44e2003-12-23 08:09:43 +0000130 return 0;
131}
132
hasso92365882005-01-18 13:53:33 +0000133static int
hassof390d2c2004-09-10 20:48:21 +0000134isis_zebra_if_state_up (int command, struct zclient *zclient,
Feng Luc99f3482014-10-16 09:52:36 +0800135 zebra_size_t length, vrf_id_t vrf_id)
jardineb5d44e2003-12-23 08:09:43 +0000136{
137 struct interface *ifp;
hassof390d2c2004-09-10 20:48:21 +0000138
Feng Luc99f3482014-10-16 09:52:36 +0800139 ifp = zebra_interface_state_read (zclient->ibuf, vrf_id);
hassof390d2c2004-09-10 20:48:21 +0000140
Josh Bailey3f045a02012-03-24 08:35:20 -0700141 if (ifp == NULL)
jardineb5d44e2003-12-23 08:09:43 +0000142 return 0;
hassof390d2c2004-09-10 20:48:21 +0000143
jardineb5d44e2003-12-23 08:09:43 +0000144 isis_csm_state_change (IF_UP_FROM_Z, circuit_scan_by_ifp (ifp), ifp);
hassof390d2c2004-09-10 20:48:21 +0000145
jardineb5d44e2003-12-23 08:09:43 +0000146 return 0;
147}
148
hasso92365882005-01-18 13:53:33 +0000149static int
hassof390d2c2004-09-10 20:48:21 +0000150isis_zebra_if_state_down (int command, struct zclient *zclient,
Feng Luc99f3482014-10-16 09:52:36 +0800151 zebra_size_t length, vrf_id_t vrf_id)
jardineb5d44e2003-12-23 08:09:43 +0000152{
153 struct interface *ifp;
Josh Bailey3f045a02012-03-24 08:35:20 -0700154 struct isis_circuit *circuit;
hassof390d2c2004-09-10 20:48:21 +0000155
Feng Luc99f3482014-10-16 09:52:36 +0800156 ifp = zebra_interface_state_read (zclient->ibuf, vrf_id);
hassof390d2c2004-09-10 20:48:21 +0000157
jardineb5d44e2003-12-23 08:09:43 +0000158 if (ifp == NULL)
159 return 0;
hassof390d2c2004-09-10 20:48:21 +0000160
Josh Bailey3f045a02012-03-24 08:35:20 -0700161 circuit = isis_csm_state_change (IF_DOWN_FROM_Z, circuit_scan_by_ifp (ifp),
162 ifp);
163 if (circuit)
164 SET_FLAG(circuit->flags, ISIS_CIRCUIT_FLAPPED_AFTER_SPF);
hassof390d2c2004-09-10 20:48:21 +0000165
jardineb5d44e2003-12-23 08:09:43 +0000166 return 0;
167}
168
hasso92365882005-01-18 13:53:33 +0000169static int
hassof390d2c2004-09-10 20:48:21 +0000170isis_zebra_if_address_add (int command, struct zclient *zclient,
Feng Luc99f3482014-10-16 09:52:36 +0800171 zebra_size_t length, vrf_id_t vrf_id)
jardineb5d44e2003-12-23 08:09:43 +0000172{
173 struct connected *c;
174 struct prefix *p;
hassof7c43dc2004-09-26 16:24:14 +0000175 char buf[BUFSIZ];
jardineb5d44e2003-12-23 08:09:43 +0000176
hassof390d2c2004-09-10 20:48:21 +0000177 c = zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_ADD,
Feng Luc99f3482014-10-16 09:52:36 +0800178 zclient->ibuf, vrf_id);
hassof390d2c2004-09-10 20:48:21 +0000179
jardineb5d44e2003-12-23 08:09:43 +0000180 if (c == NULL)
181 return 0;
hassof390d2c2004-09-10 20:48:21 +0000182
jardineb5d44e2003-12-23 08:09:43 +0000183 p = c->address;
hassof390d2c2004-09-10 20:48:21 +0000184
jardineb5d44e2003-12-23 08:09:43 +0000185 prefix2str (p, buf, BUFSIZ);
186#ifdef EXTREME_DEBUG
hassof390d2c2004-09-10 20:48:21 +0000187 if (p->family == AF_INET)
hasso529d65b2004-12-24 00:14:50 +0000188 zlog_debug ("connected IP address %s", buf);
jardineb5d44e2003-12-23 08:09:43 +0000189#ifdef HAVE_IPV6
190 if (p->family == AF_INET6)
hasso529d65b2004-12-24 00:14:50 +0000191 zlog_debug ("connected IPv6 address %s", buf);
jardineb5d44e2003-12-23 08:09:43 +0000192#endif /* HAVE_IPV6 */
193#endif /* EXTREME_DEBUG */
hassob30c5e62004-12-29 20:06:41 +0000194 if (if_is_operative (c->ifp))
195 isis_circuit_add_addr (circuit_scan_by_ifp (c->ifp), c);
jardineb5d44e2003-12-23 08:09:43 +0000196
197 return 0;
198}
199
hasso92365882005-01-18 13:53:33 +0000200static int
hassof390d2c2004-09-10 20:48:21 +0000201isis_zebra_if_address_del (int command, struct zclient *client,
Feng Luc99f3482014-10-16 09:52:36 +0800202 zebra_size_t length, vrf_id_t vrf_id)
jardineb5d44e2003-12-23 08:09:43 +0000203{
204 struct connected *c;
205 struct interface *ifp;
hasso1cd80842004-10-07 20:07:40 +0000206#ifdef EXTREME_DEBUG
hassof891f442004-09-14 13:54:30 +0000207 struct prefix *p;
208 u_char buf[BUFSIZ];
hasso1cd80842004-10-07 20:07:40 +0000209#endif /* EXTREME_DEBUG */
jardineb5d44e2003-12-23 08:09:43 +0000210
hassof390d2c2004-09-10 20:48:21 +0000211 c = zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_DELETE,
Feng Luc99f3482014-10-16 09:52:36 +0800212 zclient->ibuf, vrf_id);
hassof390d2c2004-09-10 20:48:21 +0000213
jardineb5d44e2003-12-23 08:09:43 +0000214 if (c == NULL)
215 return 0;
hassof390d2c2004-09-10 20:48:21 +0000216
jardineb5d44e2003-12-23 08:09:43 +0000217 ifp = c->ifp;
hassof390d2c2004-09-10 20:48:21 +0000218
hassof891f442004-09-14 13:54:30 +0000219#ifdef EXTREME_DEBUG
220 p = c->address;
221 prefix2str (p, buf, BUFSIZ);
222
223 if (p->family == AF_INET)
hasso529d65b2004-12-24 00:14:50 +0000224 zlog_debug ("disconnected IP address %s", buf);
hassof891f442004-09-14 13:54:30 +0000225#ifdef HAVE_IPV6
226 if (p->family == AF_INET6)
hasso529d65b2004-12-24 00:14:50 +0000227 zlog_debug ("disconnected IPv6 address %s", buf);
hassof891f442004-09-14 13:54:30 +0000228#endif /* HAVE_IPV6 */
229#endif /* EXTREME_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000230
hassob30c5e62004-12-29 20:06:41 +0000231 if (if_is_operative (ifp))
232 isis_circuit_del_addr (circuit_scan_by_ifp (ifp), c);
hassof891f442004-09-14 13:54:30 +0000233 connected_free (c);
hassof390d2c2004-09-10 20:48:21 +0000234
jardineb5d44e2003-12-23 08:09:43 +0000235 return 0;
236}
237
Olivier Dugeon4f593572016-04-19 19:03:05 +0200238static int
239isis_zebra_link_params (int command, struct zclient *zclient,
240 zebra_size_t length)
241{
242 struct interface *ifp;
243
244 ifp = zebra_interface_link_params_read (zclient->ibuf);
245
246 if (ifp == NULL)
247 return 0;
248
249 /* Update TE TLV */
250 isis_mpls_te_update(ifp);
251
252 return 0;
253}
254
hasso92365882005-01-18 13:53:33 +0000255static void
hassof390d2c2004-09-10 20:48:21 +0000256isis_zebra_route_add_ipv4 (struct prefix *prefix,
257 struct isis_route_info *route_info)
jardineb5d44e2003-12-23 08:09:43 +0000258{
259 u_char message, flags;
260 int psize;
261 struct stream *stream;
262 struct isis_nexthop *nexthop;
263 struct listnode *node;
264
Josh Bailey3f045a02012-03-24 08:35:20 -0700265 if (CHECK_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
jardineb5d44e2003-12-23 08:09:43 +0000266 return;
267
Feng Luc99f3482014-10-16 09:52:36 +0800268 if (vrf_bitmap_check (zclient->redist[ZEBRA_ROUTE_ISIS], VRF_DEFAULT))
hassof390d2c2004-09-10 20:48:21 +0000269 {
270 message = 0;
271 flags = 0;
jardineb5d44e2003-12-23 08:09:43 +0000272
hassof390d2c2004-09-10 20:48:21 +0000273 SET_FLAG (message, ZAPI_MESSAGE_NEXTHOP);
274 SET_FLAG (message, ZAPI_MESSAGE_METRIC);
hasso2097cd82003-12-23 11:51:08 +0000275#if 0
hassof390d2c2004-09-10 20:48:21 +0000276 SET_FLAG (message, ZAPI_MESSAGE_DISTANCE);
hasso2097cd82003-12-23 11:51:08 +0000277#endif
hassof390d2c2004-09-10 20:48:21 +0000278
279 stream = zclient->obuf;
280 stream_reset (stream);
Feng Luc99f3482014-10-16 09:52:36 +0800281 zclient_create_header (stream, ZEBRA_IPV4_ROUTE_ADD, VRF_DEFAULT);
hassof390d2c2004-09-10 20:48:21 +0000282 /* type */
283 stream_putc (stream, ZEBRA_ROUTE_ISIS);
284 /* flags */
285 stream_putc (stream, flags);
286 /* message */
287 stream_putc (stream, message);
Avneesh Sachdevaa3b2642012-04-11 23:56:03 -0700288 /* SAFI */
289 stream_putw (stream, SAFI_UNICAST);
hassof390d2c2004-09-10 20:48:21 +0000290 /* prefix information */
291 psize = PSIZE (prefix->prefixlen);
292 stream_putc (stream, prefix->prefixlen);
293 stream_write (stream, (u_char *) & prefix->u.prefix4, psize);
294
295 stream_putc (stream, listcount (route_info->nexthops));
296
297 /* Nexthop, ifindex, distance and metric information */
paul1eb8ef22005-04-07 07:30:20 +0000298 for (ALL_LIST_ELEMENTS_RO (route_info->nexthops, node, nexthop))
hassof390d2c2004-09-10 20:48:21 +0000299 {
hassof390d2c2004-09-10 20:48:21 +0000300 /* FIXME: can it be ? */
301 if (nexthop->ip.s_addr != INADDR_ANY)
302 {
303 stream_putc (stream, ZEBRA_NEXTHOP_IPV4);
304 stream_put_in_addr (stream, &nexthop->ip);
305 }
306 else
307 {
308 stream_putc (stream, ZEBRA_NEXTHOP_IFINDEX);
309 stream_putl (stream, nexthop->ifindex);
310 }
311 }
312#if 0
313 if (CHECK_FLAG (message, ZAPI_MESSAGE_DISTANCE))
314 stream_putc (stream, route_info->depth);
315#endif
316 if (CHECK_FLAG (message, ZAPI_MESSAGE_METRIC))
317 stream_putl (stream, route_info->cost);
318
319 stream_putw_at (stream, 0, stream_get_endp (stream));
ajs634f9ea2005-04-11 15:51:40 +0000320 zclient_send_message(zclient);
Josh Bailey3f045a02012-03-24 08:35:20 -0700321 SET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
322 UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC);
hassof390d2c2004-09-10 20:48:21 +0000323 }
jardineb5d44e2003-12-23 08:09:43 +0000324}
325
hasso92365882005-01-18 13:53:33 +0000326static void
hassof390d2c2004-09-10 20:48:21 +0000327isis_zebra_route_del_ipv4 (struct prefix *prefix,
328 struct isis_route_info *route_info)
jardineb5d44e2003-12-23 08:09:43 +0000329{
330 struct zapi_ipv4 api;
331 struct prefix_ipv4 prefix4;
hassof390d2c2004-09-10 20:48:21 +0000332
Feng Luc99f3482014-10-16 09:52:36 +0800333 if (vrf_bitmap_check (zclient->redist[ZEBRA_ROUTE_ISIS], VRF_DEFAULT))
hassof390d2c2004-09-10 20:48:21 +0000334 {
Feng Luc99f3482014-10-16 09:52:36 +0800335 api.vrf_id = VRF_DEFAULT;
hassof390d2c2004-09-10 20:48:21 +0000336 api.type = ZEBRA_ROUTE_ISIS;
337 api.flags = 0;
338 api.message = 0;
Avneesh Sachdevaa3b2642012-04-11 23:56:03 -0700339 api.safi = SAFI_UNICAST;
hassof390d2c2004-09-10 20:48:21 +0000340 prefix4.family = AF_INET;
341 prefix4.prefixlen = prefix->prefixlen;
342 prefix4.prefix = prefix->u.prefix4;
343 zapi_ipv4_route (ZEBRA_IPV4_ROUTE_DELETE, zclient, &prefix4, &api);
344 }
Josh Bailey3f045a02012-03-24 08:35:20 -0700345 UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
hassof390d2c2004-09-10 20:48:21 +0000346
jardineb5d44e2003-12-23 08:09:43 +0000347 return;
348}
349
350#ifdef HAVE_IPV6
David Lamparterf50ee932015-03-04 07:13:38 +0100351static void
jardineb5d44e2003-12-23 08:09:43 +0000352isis_zebra_route_add_ipv6 (struct prefix *prefix,
hassof390d2c2004-09-10 20:48:21 +0000353 struct isis_route_info *route_info)
jardineb5d44e2003-12-23 08:09:43 +0000354{
355 struct zapi_ipv6 api;
356 struct in6_addr **nexthop_list;
Paul Jakma9099f9b2016-01-18 10:12:10 +0000357 ifindex_t *ifindex_list;
jardineb5d44e2003-12-23 08:09:43 +0000358 struct isis_nexthop6 *nexthop6;
359 int i, size;
360 struct listnode *node;
361 struct prefix_ipv6 prefix6;
362
Josh Bailey3f045a02012-03-24 08:35:20 -0700363 if (CHECK_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
jardineb5d44e2003-12-23 08:09:43 +0000364 return;
hassof390d2c2004-09-10 20:48:21 +0000365
Feng Luc99f3482014-10-16 09:52:36 +0800366 api.vrf_id = VRF_DEFAULT;
jardineb5d44e2003-12-23 08:09:43 +0000367 api.type = ZEBRA_ROUTE_ISIS;
368 api.flags = 0;
369 api.message = 0;
Avneesh Sachdevaa3b2642012-04-11 23:56:03 -0700370 api.safi = SAFI_UNICAST;
jardineb5d44e2003-12-23 08:09:43 +0000371 SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
372 SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX);
373 SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
374 api.metric = route_info->cost;
375#if 0
376 SET_FLAG (api.message, ZAPI_MESSAGE_DISTANCE);
377 api.distance = route_info->depth;
378#endif
379 api.nexthop_num = listcount (route_info->nexthops6);
380 api.ifindex_num = listcount (route_info->nexthops6);
hassof390d2c2004-09-10 20:48:21 +0000381
jardineb5d44e2003-12-23 08:09:43 +0000382 /* allocate memory for nexthop_list */
383 size = sizeof (struct isis_nexthop6 *) * listcount (route_info->nexthops6);
384 nexthop_list = (struct in6_addr **) XMALLOC (MTYPE_ISIS_TMP, size);
hassof390d2c2004-09-10 20:48:21 +0000385 if (!nexthop_list)
386 {
387 zlog_err ("isis_zebra_add_route_ipv6: out of memory!");
388 return;
389 }
390
jardineb5d44e2003-12-23 08:09:43 +0000391 /* allocate memory for ifindex_list */
392 size = sizeof (unsigned int) * listcount (route_info->nexthops6);
Paul Jakma9099f9b2016-01-18 10:12:10 +0000393 ifindex_list = (ifindex_t *) XMALLOC (MTYPE_ISIS_TMP, size);
hassof390d2c2004-09-10 20:48:21 +0000394 if (!ifindex_list)
395 {
396 zlog_err ("isis_zebra_add_route_ipv6: out of memory!");
397 XFREE (MTYPE_ISIS_TMP, nexthop_list);
398 return;
399 }
400
jardineb5d44e2003-12-23 08:09:43 +0000401 /* for each nexthop */
402 i = 0;
paul1eb8ef22005-04-07 07:30:20 +0000403 for (ALL_LIST_ELEMENTS_RO (route_info->nexthops6, node, nexthop6))
hassof390d2c2004-09-10 20:48:21 +0000404 {
hassof390d2c2004-09-10 20:48:21 +0000405 if (!IN6_IS_ADDR_LINKLOCAL (&nexthop6->ip6) &&
406 !IN6_IS_ADDR_UNSPECIFIED (&nexthop6->ip6))
407 {
408 api.nexthop_num--;
409 api.ifindex_num--;
410 continue;
411 }
412
413 nexthop_list[i] = &nexthop6->ip6;
414 ifindex_list[i] = nexthop6->ifindex;
415 i++;
jardineb5d44e2003-12-23 08:09:43 +0000416 }
hassof390d2c2004-09-10 20:48:21 +0000417
jardineb5d44e2003-12-23 08:09:43 +0000418 api.nexthop = nexthop_list;
419 api.ifindex = ifindex_list;
hassof390d2c2004-09-10 20:48:21 +0000420
421 if (api.nexthop_num && api.ifindex_num)
422 {
423 prefix6.family = AF_INET6;
424 prefix6.prefixlen = prefix->prefixlen;
425 memcpy (&prefix6.prefix, &prefix->u.prefix6, sizeof (struct in6_addr));
426 zapi_ipv6_route (ZEBRA_IPV6_ROUTE_ADD, zclient, &prefix6, &api);
Josh Bailey3f045a02012-03-24 08:35:20 -0700427 SET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
428 UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC);
hassof390d2c2004-09-10 20:48:21 +0000429 }
430
jardineb5d44e2003-12-23 08:09:43 +0000431 XFREE (MTYPE_ISIS_TMP, nexthop_list);
432 XFREE (MTYPE_ISIS_TMP, ifindex_list);
hassof390d2c2004-09-10 20:48:21 +0000433
jardineb5d44e2003-12-23 08:09:43 +0000434 return;
435}
436
hasso92365882005-01-18 13:53:33 +0000437static void
hassof390d2c2004-09-10 20:48:21 +0000438isis_zebra_route_del_ipv6 (struct prefix *prefix,
439 struct isis_route_info *route_info)
jardineb5d44e2003-12-23 08:09:43 +0000440{
441 struct zapi_ipv6 api;
442 struct in6_addr **nexthop_list;
Paul Jakma9099f9b2016-01-18 10:12:10 +0000443 ifindex_t *ifindex_list;
jardineb5d44e2003-12-23 08:09:43 +0000444 struct isis_nexthop6 *nexthop6;
445 int i, size;
446 struct listnode *node;
447 struct prefix_ipv6 prefix6;
448
Christian Franke912aac42015-11-10 18:04:47 +0100449 if (!CHECK_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
jardineb5d44e2003-12-23 08:09:43 +0000450 return;
hassof390d2c2004-09-10 20:48:21 +0000451
Feng Luc99f3482014-10-16 09:52:36 +0800452 api.vrf_id = VRF_DEFAULT;
jardineb5d44e2003-12-23 08:09:43 +0000453 api.type = ZEBRA_ROUTE_ISIS;
454 api.flags = 0;
455 api.message = 0;
Avneesh Sachdevaa3b2642012-04-11 23:56:03 -0700456 api.safi = SAFI_UNICAST;
jardineb5d44e2003-12-23 08:09:43 +0000457 SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
458 SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX);
459 api.nexthop_num = listcount (route_info->nexthops6);
460 api.ifindex_num = listcount (route_info->nexthops6);
hassof390d2c2004-09-10 20:48:21 +0000461
jardineb5d44e2003-12-23 08:09:43 +0000462 /* allocate memory for nexthop_list */
463 size = sizeof (struct isis_nexthop6 *) * listcount (route_info->nexthops6);
464 nexthop_list = (struct in6_addr **) XMALLOC (MTYPE_ISIS_TMP, size);
hassof390d2c2004-09-10 20:48:21 +0000465 if (!nexthop_list)
466 {
467 zlog_err ("isis_zebra_route_del_ipv6: out of memory!");
468 return;
469 }
470
jardineb5d44e2003-12-23 08:09:43 +0000471 /* allocate memory for ifindex_list */
472 size = sizeof (unsigned int) * listcount (route_info->nexthops6);
Paul Jakma9099f9b2016-01-18 10:12:10 +0000473 ifindex_list = (ifindex_t *) XMALLOC (MTYPE_ISIS_TMP, size);
hassof390d2c2004-09-10 20:48:21 +0000474 if (!ifindex_list)
475 {
476 zlog_err ("isis_zebra_route_del_ipv6: out of memory!");
477 XFREE (MTYPE_ISIS_TMP, nexthop_list);
478 return;
479 }
480
jardineb5d44e2003-12-23 08:09:43 +0000481 /* for each nexthop */
482 i = 0;
paul1eb8ef22005-04-07 07:30:20 +0000483 for (ALL_LIST_ELEMENTS_RO (route_info->nexthops6, node, nexthop6))
hassof390d2c2004-09-10 20:48:21 +0000484 {
hassof390d2c2004-09-10 20:48:21 +0000485 if (!IN6_IS_ADDR_LINKLOCAL (&nexthop6->ip6) &&
486 !IN6_IS_ADDR_UNSPECIFIED (&nexthop6->ip6))
487 {
488 api.nexthop_num--;
489 api.ifindex_num--;
490 continue;
491 }
492
493 nexthop_list[i] = &nexthop6->ip6;
494 ifindex_list[i] = nexthop6->ifindex;
495 i++;
jardineb5d44e2003-12-23 08:09:43 +0000496 }
hassof390d2c2004-09-10 20:48:21 +0000497
jardineb5d44e2003-12-23 08:09:43 +0000498 api.nexthop = nexthop_list;
499 api.ifindex = ifindex_list;
jardineb5d44e2003-12-23 08:09:43 +0000500
hassof390d2c2004-09-10 20:48:21 +0000501 if (api.nexthop_num && api.ifindex_num)
502 {
503 prefix6.family = AF_INET6;
504 prefix6.prefixlen = prefix->prefixlen;
505 memcpy (&prefix6.prefix, &prefix->u.prefix6, sizeof (struct in6_addr));
506 zapi_ipv6_route (ZEBRA_IPV6_ROUTE_DELETE, zclient, &prefix6, &api);
Josh Bailey3f045a02012-03-24 08:35:20 -0700507 UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
hassof390d2c2004-09-10 20:48:21 +0000508 }
509
510 XFREE (MTYPE_ISIS_TMP, nexthop_list);
511 XFREE (MTYPE_ISIS_TMP, ifindex_list);
512}
jardineb5d44e2003-12-23 08:09:43 +0000513
514#endif /* HAVE_IPV6 */
515
jardineb5d44e2003-12-23 08:09:43 +0000516void
517isis_zebra_route_update (struct prefix *prefix,
hassof390d2c2004-09-10 20:48:21 +0000518 struct isis_route_info *route_info)
jardineb5d44e2003-12-23 08:09:43 +0000519{
520 if (zclient->sock < 0)
521 return;
522
Feng Luc99f3482014-10-16 09:52:36 +0800523 if (!vrf_bitmap_check (zclient->redist[ZEBRA_ROUTE_ISIS], VRF_DEFAULT))
jardineb5d44e2003-12-23 08:09:43 +0000524 return;
525
hassof390d2c2004-09-10 20:48:21 +0000526 if (CHECK_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ACTIVE))
527 {
528 if (prefix->family == AF_INET)
529 isis_zebra_route_add_ipv4 (prefix, route_info);
jardineb5d44e2003-12-23 08:09:43 +0000530#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000531 else if (prefix->family == AF_INET6)
532 isis_zebra_route_add_ipv6 (prefix, route_info);
jardineb5d44e2003-12-23 08:09:43 +0000533#endif /* HAVE_IPV6 */
hassof390d2c2004-09-10 20:48:21 +0000534 }
535 else
536 {
537 if (prefix->family == AF_INET)
538 isis_zebra_route_del_ipv4 (prefix, route_info);
jardineb5d44e2003-12-23 08:09:43 +0000539#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000540 else if (prefix->family == AF_INET6)
541 isis_zebra_route_del_ipv6 (prefix, route_info);
jardineb5d44e2003-12-23 08:09:43 +0000542#endif /* HAVE_IPV6 */
hassof390d2c2004-09-10 20:48:21 +0000543 }
jardineb5d44e2003-12-23 08:09:43 +0000544 return;
545}
546
hasso92365882005-01-18 13:53:33 +0000547static int
hassof390d2c2004-09-10 20:48:21 +0000548isis_zebra_read_ipv4 (int command, struct zclient *zclient,
Feng Luc99f3482014-10-16 09:52:36 +0800549 zebra_size_t length, vrf_id_t vrf_id)
jardineb5d44e2003-12-23 08:09:43 +0000550{
551 struct stream *stream;
552 struct zapi_ipv4 api;
553 struct prefix_ipv4 p;
Christian Frankeacf98652015-11-12 14:24:22 +0100554 struct prefix *p_generic = (struct prefix*)&p;
David Lamparterf50ee932015-03-04 07:13:38 +0100555 unsigned long ifindex __attribute__ ((unused));
556 struct in_addr nexthop __attribute__ ((unused));
Donald Sharp5e57b5f2016-03-11 16:28:34 -0500557 unsigned char plength = 0;
jardineb5d44e2003-12-23 08:09:43 +0000558
559 stream = zclient->ibuf;
Christian Frankeacf98652015-11-12 14:24:22 +0100560 memset(&api, 0, sizeof(api));
jardineb5d44e2003-12-23 08:09:43 +0000561 memset (&p, 0, sizeof (struct prefix_ipv4));
Christian Frankeacf98652015-11-12 14:24:22 +0100562 memset(&nexthop, 0, sizeof(nexthop));
jardineb5d44e2003-12-23 08:09:43 +0000563 ifindex = 0;
564
hassof390d2c2004-09-10 20:48:21 +0000565 api.type = stream_getc (stream);
566 api.flags = stream_getc (stream);
jardineb5d44e2003-12-23 08:09:43 +0000567 api.message = stream_getc (stream);
568
569 p.family = AF_INET;
Donald Sharp5e57b5f2016-03-11 16:28:34 -0500570 plength = stream_getc (stream);
571 p.prefixlen = MIN(IPV4_MAX_PREFIXLEN, plength);
jardineb5d44e2003-12-23 08:09:43 +0000572 stream_get (&p.prefix, stream, PSIZE (p.prefixlen));
hassof390d2c2004-09-10 20:48:21 +0000573
574 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
575 {
jardineb5d44e2003-12-23 08:09:43 +0000576 api.nexthop_num = stream_getc (stream);
577 nexthop.s_addr = stream_get_ipv4 (stream);
hassof390d2c2004-09-10 20:48:21 +0000578 }
579 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX))
580 {
581 api.ifindex_num = stream_getc (stream);
582 ifindex = stream_getl (stream);
583 }
jardineb5d44e2003-12-23 08:09:43 +0000584 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
585 api.distance = stream_getc (stream);
586 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
587 api.metric = stream_getl (stream);
Christian Frankeacf98652015-11-12 14:24:22 +0100588
589 /*
590 * Avoid advertising a false default reachability. (A default
591 * route installed by IS-IS gets redistributed from zebra back
592 * into IS-IS causing us to start advertising default reachabity
593 * without this check)
594 */
595 if (p.prefixlen == 0 && api.type == ZEBRA_ROUTE_ISIS)
596 command = ZEBRA_IPV4_ROUTE_DELETE;
hassof390d2c2004-09-10 20:48:21 +0000597
598 if (command == ZEBRA_IPV4_ROUTE_ADD)
Christian Frankeacf98652015-11-12 14:24:22 +0100599 isis_redist_add(api.type, p_generic, api.distance, api.metric);
600 else
601 isis_redist_delete(api.type, p_generic);
jardineb5d44e2003-12-23 08:09:43 +0000602
603 return 0;
604}
605
hasso92365882005-01-18 13:53:33 +0000606static int
hassof390d2c2004-09-10 20:48:21 +0000607isis_zebra_read_ipv6 (int command, struct zclient *zclient,
Feng Luc99f3482014-10-16 09:52:36 +0800608 zebra_size_t length, vrf_id_t vrf_id)
jardineb5d44e2003-12-23 08:09:43 +0000609{
Christian Frankeacf98652015-11-12 14:24:22 +0100610 struct stream *stream;
611 struct zapi_ipv6 api;
612 struct prefix_ipv6 p;
613 struct prefix *p_generic = (struct prefix*)&p;
614 struct in6_addr nexthop;
615 unsigned long ifindex __attribute__((unused));
616
617 stream = zclient->ibuf;
618 memset(&api, 0, sizeof(api));
619 memset(&p, 0, sizeof(struct prefix_ipv6));
620 memset(&nexthop, 0, sizeof(nexthop));
621 ifindex = 0;
622
623 api.type = stream_getc(stream);
624 api.flags = stream_getc(stream);
625 api.message = stream_getc(stream);
626
627 p.family = AF_INET6;
628 p.prefixlen = stream_getc(stream);
629 stream_get(&p.prefix, stream, PSIZE(p.prefixlen));
630
631 if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP))
632 {
633 api.nexthop_num = stream_getc(stream); /* this is always 1 */
634 stream_get(&nexthop, stream, sizeof(nexthop));
635 }
636 if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX))
637 {
638 api.ifindex_num = stream_getc(stream);
639 ifindex = stream_getl(stream);
640 }
641 if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE))
642 api.distance = stream_getc(stream);
643 if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC))
644 api.metric = stream_getl(stream);
645
646 /*
647 * Avoid advertising a false default reachability. (A default
648 * route installed by IS-IS gets redistributed from zebra back
649 * into IS-IS causing us to start advertising default reachabity
650 * without this check)
651 */
652 if (p.prefixlen == 0 && api.type == ZEBRA_ROUTE_ISIS)
653 command = ZEBRA_IPV6_ROUTE_DELETE;
654
655 if (command == ZEBRA_IPV6_ROUTE_ADD)
656 isis_redist_add(api.type, p_generic, api.distance, api.metric);
657 else
658 isis_redist_delete(api.type, p_generic);
659
jardineb5d44e2003-12-23 08:09:43 +0000660 return 0;
661}
jardineb5d44e2003-12-23 08:09:43 +0000662
663int
664isis_distribute_list_update (int routetype)
665{
666 return 0;
667}
668
Christian Frankeacf98652015-11-12 14:24:22 +0100669void
670isis_zebra_redistribute_set(int type)
jardineb5d44e2003-12-23 08:09:43 +0000671{
Christian Frankeacf98652015-11-12 14:24:22 +0100672 if (type == DEFAULT_ROUTE)
673 zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_ADD, zclient, VRF_DEFAULT);
674 else
675 zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, type, VRF_DEFAULT);
jardineb5d44e2003-12-23 08:09:43 +0000676}
Christian Frankeacf98652015-11-12 14:24:22 +0100677
678void
679isis_zebra_redistribute_unset(int type)
680{
681 if (type == DEFAULT_ROUTE)
682 zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_DELETE, zclient, VRF_DEFAULT);
683 else
684 zclient_redistribute(ZEBRA_REDISTRIBUTE_DELETE, zclient, type, VRF_DEFAULT);
685}
jardineb5d44e2003-12-23 08:09:43 +0000686
Feng Luc99f3482014-10-16 09:52:36 +0800687static void
688isis_zebra_connected (struct zclient *zclient)
689{
690 zclient_send_requests (zclient, VRF_DEFAULT);
691}
692
jardineb5d44e2003-12-23 08:09:43 +0000693void
Donald Sharp71252932015-09-24 09:25:19 -0400694isis_zebra_init (struct thread_master *master)
jardineb5d44e2003-12-23 08:09:43 +0000695{
Donald Sharp71252932015-09-24 09:25:19 -0400696 zclient = zclient_new (master);
jardineb5d44e2003-12-23 08:09:43 +0000697 zclient_init (zclient, ZEBRA_ROUTE_ISIS);
Feng Luc99f3482014-10-16 09:52:36 +0800698 zclient->zebra_connected = isis_zebra_connected;
hasso18a6dce2004-10-03 18:18:34 +0000699 zclient->router_id_update = isis_router_id_update_zebra;
jardineb5d44e2003-12-23 08:09:43 +0000700 zclient->interface_add = isis_zebra_if_add;
701 zclient->interface_delete = isis_zebra_if_del;
702 zclient->interface_up = isis_zebra_if_state_up;
703 zclient->interface_down = isis_zebra_if_state_down;
704 zclient->interface_address_add = isis_zebra_if_address_add;
705 zclient->interface_address_delete = isis_zebra_if_address_del;
Olivier Dugeon4f593572016-04-19 19:03:05 +0200706 zclient->interface_link_params = isis_zebra_link_params;
jardineb5d44e2003-12-23 08:09:43 +0000707 zclient->ipv4_route_add = isis_zebra_read_ipv4;
708 zclient->ipv4_route_delete = isis_zebra_read_ipv4;
709#ifdef HAVE_IPV6
710 zclient->ipv6_route_add = isis_zebra_read_ipv6;
711 zclient->ipv6_route_delete = isis_zebra_read_ipv6;
712#endif /* HAVE_IPV6 */
713
714 return;
715}