blob: 8a78417587321dd263b0478c16a9853c58a43ddc [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
7 *
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)
11 * any later version.
12 *
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
16 * more details.
17
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.
21 */
22
23#include <zebra.h>
jardineb5d44e2003-12-23 08:09:43 +000024
25#include "thread.h"
26#include "command.h"
27#include "memory.h"
28#include "log.h"
29#include "if.h"
30#include "network.h"
31#include "prefix.h"
32#include "zclient.h"
33#include "stream.h"
34#include "linklist.h"
Feng Luc99f3482014-10-16 09:52:36 +080035#include "vrf.h"
jardineb5d44e2003-12-23 08:09:43 +000036
hassoc89c05d2005-09-04 21:36:36 +000037#include "isisd/dict.h"
jardineb5d44e2003-12-23 08:09:43 +000038#include "isisd/isis_constants.h"
39#include "isisd/isis_common.h"
Josh Bailey3f045a02012-03-24 08:35:20 -070040#include "isisd/isis_flags.h"
41#include "isisd/isis_misc.h"
42#include "isisd/isis_circuit.h"
43#include "isisd/isis_tlv.h"
hassoc89c05d2005-09-04 21:36:36 +000044#include "isisd/isisd.h"
jardineb5d44e2003-12-23 08:09:43 +000045#include "isisd/isis_circuit.h"
46#include "isisd/isis_csm.h"
Josh Bailey3f045a02012-03-24 08:35:20 -070047#include "isisd/isis_lsp.h"
jardineb5d44e2003-12-23 08:09:43 +000048#include "isisd/isis_route.h"
49#include "isisd/isis_zebra.h"
50
51struct zclient *zclient = NULL;
52
hasso18a6dce2004-10-03 18:18:34 +000053/* Router-id update message from zebra. */
hasso92365882005-01-18 13:53:33 +000054static int
hasso18a6dce2004-10-03 18:18:34 +000055isis_router_id_update_zebra (int command, struct zclient *zclient,
Feng Luc99f3482014-10-16 09:52:36 +080056 zebra_size_t length, vrf_id_t vrf_id)
hasso18a6dce2004-10-03 18:18:34 +000057{
Josh Bailey3f045a02012-03-24 08:35:20 -070058 struct isis_area *area;
59 struct listnode *node;
hasso18a6dce2004-10-03 18:18:34 +000060 struct prefix router_id;
hasso18a6dce2004-10-03 18:18:34 +000061
Josh Bailey3f045a02012-03-24 08:35:20 -070062 zebra_router_id_update_read (zclient->ibuf, &router_id);
63 if (isis->router_id == router_id.u.prefix4.s_addr)
64 return 0;
hasso18a6dce2004-10-03 18:18:34 +000065
Josh Bailey3f045a02012-03-24 08:35:20 -070066 isis->router_id = router_id.u.prefix4.s_addr;
67 for (ALL_LIST_ELEMENTS_RO (isis->area_list, node, area))
68 if (listcount (area->area_addrs) > 0)
69 lsp_regenerate_schedule (area, area->is_type, 0);
70
hasso18a6dce2004-10-03 18:18:34 +000071 return 0;
72}
jardineb5d44e2003-12-23 08:09:43 +000073
hasso92365882005-01-18 13:53:33 +000074static int
Feng Luc99f3482014-10-16 09:52:36 +080075isis_zebra_if_add (int command, struct zclient *zclient, zebra_size_t length,
76 vrf_id_t vrf_id)
jardineb5d44e2003-12-23 08:09:43 +000077{
78 struct interface *ifp;
79
Feng Luc99f3482014-10-16 09:52:36 +080080 ifp = zebra_interface_add_read (zclient->ibuf, vrf_id);
hassof390d2c2004-09-10 20:48:21 +000081
hassoc89c05d2005-09-04 21:36:36 +000082 if (isis->debugs & DEBUG_ZEBRA)
83 zlog_debug ("Zebra I/F add: %s index %d flags %ld metric %d mtu %d",
Paul Jakma41b36e92006-12-08 01:09:50 +000084 ifp->name, ifp->ifindex, (long)ifp->flags, ifp->metric, ifp->mtu);
hassof390d2c2004-09-10 20:48:21 +000085
hassob30c5e62004-12-29 20:06:41 +000086 if (if_is_operative (ifp))
jardineb5d44e2003-12-23 08:09:43 +000087 isis_csm_state_change (IF_UP_FROM_Z, circuit_scan_by_ifp (ifp), ifp);
hassof390d2c2004-09-10 20:48:21 +000088
jardineb5d44e2003-12-23 08:09:43 +000089 return 0;
90}
91
hasso92365882005-01-18 13:53:33 +000092static int
Feng Luc99f3482014-10-16 09:52:36 +080093isis_zebra_if_del (int command, struct zclient *zclient, zebra_size_t length,
94 vrf_id_t vrf_id)
jardineb5d44e2003-12-23 08:09:43 +000095{
96 struct interface *ifp;
97 struct stream *s;
98
99 s = zclient->ibuf;
Feng Luc99f3482014-10-16 09:52:36 +0800100 ifp = zebra_interface_state_read (s, vrf_id);
hassof390d2c2004-09-10 20:48:21 +0000101
jardineb5d44e2003-12-23 08:09:43 +0000102 if (!ifp)
103 return 0;
104
hassob30c5e62004-12-29 20:06:41 +0000105 if (if_is_operative (ifp))
jardineb5d44e2003-12-23 08:09:43 +0000106 zlog_warn ("Zebra: got delete of %s, but interface is still up",
hassof390d2c2004-09-10 20:48:21 +0000107 ifp->name);
jardineb5d44e2003-12-23 08:09:43 +0000108
hassoc89c05d2005-09-04 21:36:36 +0000109 if (isis->debugs & DEBUG_ZEBRA)
110 zlog_debug ("Zebra I/F delete: %s index %d flags %ld metric %d mtu %d",
Paul Jakma41b36e92006-12-08 01:09:50 +0000111 ifp->name, ifp->ifindex, (long)ifp->flags, ifp->metric, ifp->mtu);
jardineb5d44e2003-12-23 08:09:43 +0000112
Josh Bailey3f045a02012-03-24 08:35:20 -0700113 isis_csm_state_change (IF_DOWN_FROM_Z, circuit_scan_by_ifp (ifp), ifp);
ajsd2fc8892005-04-02 18:38:43 +0000114
115 /* Cannot call if_delete because we should retain the pseudo interface
116 in case there is configuration info attached to it. */
117 if_delete_retain(ifp);
hassof390d2c2004-09-10 20:48:21 +0000118
ajsd2fc8892005-04-02 18:38:43 +0000119 ifp->ifindex = IFINDEX_INTERNAL;
120
jardineb5d44e2003-12-23 08:09:43 +0000121 return 0;
122}
123
hasso92365882005-01-18 13:53:33 +0000124static int
hassof390d2c2004-09-10 20:48:21 +0000125isis_zebra_if_state_up (int command, struct zclient *zclient,
Feng Luc99f3482014-10-16 09:52:36 +0800126 zebra_size_t length, vrf_id_t vrf_id)
jardineb5d44e2003-12-23 08:09:43 +0000127{
128 struct interface *ifp;
hassof390d2c2004-09-10 20:48:21 +0000129
Feng Luc99f3482014-10-16 09:52:36 +0800130 ifp = zebra_interface_state_read (zclient->ibuf, vrf_id);
hassof390d2c2004-09-10 20:48:21 +0000131
Josh Bailey3f045a02012-03-24 08:35:20 -0700132 if (ifp == NULL)
jardineb5d44e2003-12-23 08:09:43 +0000133 return 0;
hassof390d2c2004-09-10 20:48:21 +0000134
jardineb5d44e2003-12-23 08:09:43 +0000135 isis_csm_state_change (IF_UP_FROM_Z, circuit_scan_by_ifp (ifp), ifp);
hassof390d2c2004-09-10 20:48:21 +0000136
jardineb5d44e2003-12-23 08:09:43 +0000137 return 0;
138}
139
hasso92365882005-01-18 13:53:33 +0000140static int
hassof390d2c2004-09-10 20:48:21 +0000141isis_zebra_if_state_down (int command, struct zclient *zclient,
Feng Luc99f3482014-10-16 09:52:36 +0800142 zebra_size_t length, vrf_id_t vrf_id)
jardineb5d44e2003-12-23 08:09:43 +0000143{
144 struct interface *ifp;
Josh Bailey3f045a02012-03-24 08:35:20 -0700145 struct isis_circuit *circuit;
hassof390d2c2004-09-10 20:48:21 +0000146
Feng Luc99f3482014-10-16 09:52:36 +0800147 ifp = zebra_interface_state_read (zclient->ibuf, vrf_id);
hassof390d2c2004-09-10 20:48:21 +0000148
jardineb5d44e2003-12-23 08:09:43 +0000149 if (ifp == NULL)
150 return 0;
hassof390d2c2004-09-10 20:48:21 +0000151
Josh Bailey3f045a02012-03-24 08:35:20 -0700152 circuit = isis_csm_state_change (IF_DOWN_FROM_Z, circuit_scan_by_ifp (ifp),
153 ifp);
154 if (circuit)
155 SET_FLAG(circuit->flags, ISIS_CIRCUIT_FLAPPED_AFTER_SPF);
hassof390d2c2004-09-10 20:48:21 +0000156
jardineb5d44e2003-12-23 08:09:43 +0000157 return 0;
158}
159
hasso92365882005-01-18 13:53:33 +0000160static int
hassof390d2c2004-09-10 20:48:21 +0000161isis_zebra_if_address_add (int command, struct zclient *zclient,
Feng Luc99f3482014-10-16 09:52:36 +0800162 zebra_size_t length, vrf_id_t vrf_id)
jardineb5d44e2003-12-23 08:09:43 +0000163{
164 struct connected *c;
165 struct prefix *p;
hassof7c43dc2004-09-26 16:24:14 +0000166 char buf[BUFSIZ];
jardineb5d44e2003-12-23 08:09:43 +0000167
hassof390d2c2004-09-10 20:48:21 +0000168 c = zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_ADD,
Feng Luc99f3482014-10-16 09:52:36 +0800169 zclient->ibuf, vrf_id);
hassof390d2c2004-09-10 20:48:21 +0000170
jardineb5d44e2003-12-23 08:09:43 +0000171 if (c == NULL)
172 return 0;
hassof390d2c2004-09-10 20:48:21 +0000173
jardineb5d44e2003-12-23 08:09:43 +0000174 p = c->address;
hassof390d2c2004-09-10 20:48:21 +0000175
jardineb5d44e2003-12-23 08:09:43 +0000176 prefix2str (p, buf, BUFSIZ);
177#ifdef EXTREME_DEBUG
hassof390d2c2004-09-10 20:48:21 +0000178 if (p->family == AF_INET)
hasso529d65b2004-12-24 00:14:50 +0000179 zlog_debug ("connected IP address %s", buf);
jardineb5d44e2003-12-23 08:09:43 +0000180#ifdef HAVE_IPV6
181 if (p->family == AF_INET6)
hasso529d65b2004-12-24 00:14:50 +0000182 zlog_debug ("connected IPv6 address %s", buf);
jardineb5d44e2003-12-23 08:09:43 +0000183#endif /* HAVE_IPV6 */
184#endif /* EXTREME_DEBUG */
hassob30c5e62004-12-29 20:06:41 +0000185 if (if_is_operative (c->ifp))
186 isis_circuit_add_addr (circuit_scan_by_ifp (c->ifp), c);
jardineb5d44e2003-12-23 08:09:43 +0000187
188 return 0;
189}
190
hasso92365882005-01-18 13:53:33 +0000191static int
hassof390d2c2004-09-10 20:48:21 +0000192isis_zebra_if_address_del (int command, struct zclient *client,
Feng Luc99f3482014-10-16 09:52:36 +0800193 zebra_size_t length, vrf_id_t vrf_id)
jardineb5d44e2003-12-23 08:09:43 +0000194{
195 struct connected *c;
196 struct interface *ifp;
hasso1cd80842004-10-07 20:07:40 +0000197#ifdef EXTREME_DEBUG
hassof891f442004-09-14 13:54:30 +0000198 struct prefix *p;
199 u_char buf[BUFSIZ];
hasso1cd80842004-10-07 20:07:40 +0000200#endif /* EXTREME_DEBUG */
jardineb5d44e2003-12-23 08:09:43 +0000201
hassof390d2c2004-09-10 20:48:21 +0000202 c = zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_DELETE,
Feng Luc99f3482014-10-16 09:52:36 +0800203 zclient->ibuf, vrf_id);
hassof390d2c2004-09-10 20:48:21 +0000204
jardineb5d44e2003-12-23 08:09:43 +0000205 if (c == NULL)
206 return 0;
hassof390d2c2004-09-10 20:48:21 +0000207
jardineb5d44e2003-12-23 08:09:43 +0000208 ifp = c->ifp;
hassof390d2c2004-09-10 20:48:21 +0000209
hassof891f442004-09-14 13:54:30 +0000210#ifdef EXTREME_DEBUG
211 p = c->address;
212 prefix2str (p, buf, BUFSIZ);
213
214 if (p->family == AF_INET)
hasso529d65b2004-12-24 00:14:50 +0000215 zlog_debug ("disconnected IP address %s", buf);
hassof891f442004-09-14 13:54:30 +0000216#ifdef HAVE_IPV6
217 if (p->family == AF_INET6)
hasso529d65b2004-12-24 00:14:50 +0000218 zlog_debug ("disconnected IPv6 address %s", buf);
hassof891f442004-09-14 13:54:30 +0000219#endif /* HAVE_IPV6 */
220#endif /* EXTREME_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000221
hassob30c5e62004-12-29 20:06:41 +0000222 if (if_is_operative (ifp))
223 isis_circuit_del_addr (circuit_scan_by_ifp (ifp), c);
hassof891f442004-09-14 13:54:30 +0000224 connected_free (c);
hassof390d2c2004-09-10 20:48:21 +0000225
jardineb5d44e2003-12-23 08:09:43 +0000226 return 0;
227}
228
hasso92365882005-01-18 13:53:33 +0000229static void
hassof390d2c2004-09-10 20:48:21 +0000230isis_zebra_route_add_ipv4 (struct prefix *prefix,
231 struct isis_route_info *route_info)
jardineb5d44e2003-12-23 08:09:43 +0000232{
233 u_char message, flags;
234 int psize;
235 struct stream *stream;
236 struct isis_nexthop *nexthop;
237 struct listnode *node;
238
Josh Bailey3f045a02012-03-24 08:35:20 -0700239 if (CHECK_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
jardineb5d44e2003-12-23 08:09:43 +0000240 return;
241
Feng Luc99f3482014-10-16 09:52:36 +0800242 if (vrf_bitmap_check (zclient->redist[ZEBRA_ROUTE_ISIS], VRF_DEFAULT))
hassof390d2c2004-09-10 20:48:21 +0000243 {
244 message = 0;
245 flags = 0;
jardineb5d44e2003-12-23 08:09:43 +0000246
hassof390d2c2004-09-10 20:48:21 +0000247 SET_FLAG (message, ZAPI_MESSAGE_NEXTHOP);
248 SET_FLAG (message, ZAPI_MESSAGE_METRIC);
hasso2097cd82003-12-23 11:51:08 +0000249#if 0
hassof390d2c2004-09-10 20:48:21 +0000250 SET_FLAG (message, ZAPI_MESSAGE_DISTANCE);
hasso2097cd82003-12-23 11:51:08 +0000251#endif
hassof390d2c2004-09-10 20:48:21 +0000252
253 stream = zclient->obuf;
254 stream_reset (stream);
Feng Luc99f3482014-10-16 09:52:36 +0800255 zclient_create_header (stream, ZEBRA_IPV4_ROUTE_ADD, VRF_DEFAULT);
hassof390d2c2004-09-10 20:48:21 +0000256 /* type */
257 stream_putc (stream, ZEBRA_ROUTE_ISIS);
258 /* flags */
259 stream_putc (stream, flags);
260 /* message */
261 stream_putc (stream, message);
Avneesh Sachdevaa3b2642012-04-11 23:56:03 -0700262 /* SAFI */
263 stream_putw (stream, SAFI_UNICAST);
hassof390d2c2004-09-10 20:48:21 +0000264 /* prefix information */
265 psize = PSIZE (prefix->prefixlen);
266 stream_putc (stream, prefix->prefixlen);
267 stream_write (stream, (u_char *) & prefix->u.prefix4, psize);
268
269 stream_putc (stream, listcount (route_info->nexthops));
270
271 /* Nexthop, ifindex, distance and metric information */
paul1eb8ef22005-04-07 07:30:20 +0000272 for (ALL_LIST_ELEMENTS_RO (route_info->nexthops, node, nexthop))
hassof390d2c2004-09-10 20:48:21 +0000273 {
hassof390d2c2004-09-10 20:48:21 +0000274 /* FIXME: can it be ? */
275 if (nexthop->ip.s_addr != INADDR_ANY)
276 {
277 stream_putc (stream, ZEBRA_NEXTHOP_IPV4);
278 stream_put_in_addr (stream, &nexthop->ip);
279 }
280 else
281 {
282 stream_putc (stream, ZEBRA_NEXTHOP_IFINDEX);
283 stream_putl (stream, nexthop->ifindex);
284 }
285 }
286#if 0
287 if (CHECK_FLAG (message, ZAPI_MESSAGE_DISTANCE))
288 stream_putc (stream, route_info->depth);
289#endif
290 if (CHECK_FLAG (message, ZAPI_MESSAGE_METRIC))
291 stream_putl (stream, route_info->cost);
292
293 stream_putw_at (stream, 0, stream_get_endp (stream));
ajs634f9ea2005-04-11 15:51:40 +0000294 zclient_send_message(zclient);
Josh Bailey3f045a02012-03-24 08:35:20 -0700295 SET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
296 UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC);
hassof390d2c2004-09-10 20:48:21 +0000297 }
jardineb5d44e2003-12-23 08:09:43 +0000298}
299
hasso92365882005-01-18 13:53:33 +0000300static void
hassof390d2c2004-09-10 20:48:21 +0000301isis_zebra_route_del_ipv4 (struct prefix *prefix,
302 struct isis_route_info *route_info)
jardineb5d44e2003-12-23 08:09:43 +0000303{
304 struct zapi_ipv4 api;
305 struct prefix_ipv4 prefix4;
hassof390d2c2004-09-10 20:48:21 +0000306
Feng Luc99f3482014-10-16 09:52:36 +0800307 if (vrf_bitmap_check (zclient->redist[ZEBRA_ROUTE_ISIS], VRF_DEFAULT))
hassof390d2c2004-09-10 20:48:21 +0000308 {
Feng Luc99f3482014-10-16 09:52:36 +0800309 api.vrf_id = VRF_DEFAULT;
hassof390d2c2004-09-10 20:48:21 +0000310 api.type = ZEBRA_ROUTE_ISIS;
311 api.flags = 0;
312 api.message = 0;
Avneesh Sachdevaa3b2642012-04-11 23:56:03 -0700313 api.safi = SAFI_UNICAST;
hassof390d2c2004-09-10 20:48:21 +0000314 prefix4.family = AF_INET;
315 prefix4.prefixlen = prefix->prefixlen;
316 prefix4.prefix = prefix->u.prefix4;
317 zapi_ipv4_route (ZEBRA_IPV4_ROUTE_DELETE, zclient, &prefix4, &api);
318 }
Josh Bailey3f045a02012-03-24 08:35:20 -0700319 UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
hassof390d2c2004-09-10 20:48:21 +0000320
jardineb5d44e2003-12-23 08:09:43 +0000321 return;
322}
323
324#ifdef HAVE_IPV6
David Lamparterf50ee932015-03-04 07:13:38 +0100325static void
jardineb5d44e2003-12-23 08:09:43 +0000326isis_zebra_route_add_ipv6 (struct prefix *prefix,
hassof390d2c2004-09-10 20:48:21 +0000327 struct isis_route_info *route_info)
jardineb5d44e2003-12-23 08:09:43 +0000328{
329 struct zapi_ipv6 api;
330 struct in6_addr **nexthop_list;
331 unsigned int *ifindex_list;
332 struct isis_nexthop6 *nexthop6;
333 int i, size;
334 struct listnode *node;
335 struct prefix_ipv6 prefix6;
336
Josh Bailey3f045a02012-03-24 08:35:20 -0700337 if (CHECK_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
jardineb5d44e2003-12-23 08:09:43 +0000338 return;
hassof390d2c2004-09-10 20:48:21 +0000339
Feng Luc99f3482014-10-16 09:52:36 +0800340 api.vrf_id = VRF_DEFAULT;
jardineb5d44e2003-12-23 08:09:43 +0000341 api.type = ZEBRA_ROUTE_ISIS;
342 api.flags = 0;
343 api.message = 0;
Avneesh Sachdevaa3b2642012-04-11 23:56:03 -0700344 api.safi = SAFI_UNICAST;
jardineb5d44e2003-12-23 08:09:43 +0000345 SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
346 SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX);
347 SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
348 api.metric = route_info->cost;
349#if 0
350 SET_FLAG (api.message, ZAPI_MESSAGE_DISTANCE);
351 api.distance = route_info->depth;
352#endif
353 api.nexthop_num = listcount (route_info->nexthops6);
354 api.ifindex_num = listcount (route_info->nexthops6);
hassof390d2c2004-09-10 20:48:21 +0000355
jardineb5d44e2003-12-23 08:09:43 +0000356 /* allocate memory for nexthop_list */
357 size = sizeof (struct isis_nexthop6 *) * listcount (route_info->nexthops6);
358 nexthop_list = (struct in6_addr **) XMALLOC (MTYPE_ISIS_TMP, size);
hassof390d2c2004-09-10 20:48:21 +0000359 if (!nexthop_list)
360 {
361 zlog_err ("isis_zebra_add_route_ipv6: out of memory!");
362 return;
363 }
364
jardineb5d44e2003-12-23 08:09:43 +0000365 /* allocate memory for ifindex_list */
366 size = sizeof (unsigned int) * listcount (route_info->nexthops6);
367 ifindex_list = (unsigned int *) XMALLOC (MTYPE_ISIS_TMP, size);
hassof390d2c2004-09-10 20:48:21 +0000368 if (!ifindex_list)
369 {
370 zlog_err ("isis_zebra_add_route_ipv6: out of memory!");
371 XFREE (MTYPE_ISIS_TMP, nexthop_list);
372 return;
373 }
374
jardineb5d44e2003-12-23 08:09:43 +0000375 /* for each nexthop */
376 i = 0;
paul1eb8ef22005-04-07 07:30:20 +0000377 for (ALL_LIST_ELEMENTS_RO (route_info->nexthops6, node, nexthop6))
hassof390d2c2004-09-10 20:48:21 +0000378 {
hassof390d2c2004-09-10 20:48:21 +0000379 if (!IN6_IS_ADDR_LINKLOCAL (&nexthop6->ip6) &&
380 !IN6_IS_ADDR_UNSPECIFIED (&nexthop6->ip6))
381 {
382 api.nexthop_num--;
383 api.ifindex_num--;
384 continue;
385 }
386
387 nexthop_list[i] = &nexthop6->ip6;
388 ifindex_list[i] = nexthop6->ifindex;
389 i++;
jardineb5d44e2003-12-23 08:09:43 +0000390 }
hassof390d2c2004-09-10 20:48:21 +0000391
jardineb5d44e2003-12-23 08:09:43 +0000392 api.nexthop = nexthop_list;
393 api.ifindex = ifindex_list;
hassof390d2c2004-09-10 20:48:21 +0000394
395 if (api.nexthop_num && api.ifindex_num)
396 {
397 prefix6.family = AF_INET6;
398 prefix6.prefixlen = prefix->prefixlen;
399 memcpy (&prefix6.prefix, &prefix->u.prefix6, sizeof (struct in6_addr));
400 zapi_ipv6_route (ZEBRA_IPV6_ROUTE_ADD, zclient, &prefix6, &api);
Josh Bailey3f045a02012-03-24 08:35:20 -0700401 SET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
402 UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC);
hassof390d2c2004-09-10 20:48:21 +0000403 }
404
jardineb5d44e2003-12-23 08:09:43 +0000405 XFREE (MTYPE_ISIS_TMP, nexthop_list);
406 XFREE (MTYPE_ISIS_TMP, ifindex_list);
hassof390d2c2004-09-10 20:48:21 +0000407
jardineb5d44e2003-12-23 08:09:43 +0000408 return;
409}
410
hasso92365882005-01-18 13:53:33 +0000411static void
hassof390d2c2004-09-10 20:48:21 +0000412isis_zebra_route_del_ipv6 (struct prefix *prefix,
413 struct isis_route_info *route_info)
jardineb5d44e2003-12-23 08:09:43 +0000414{
415 struct zapi_ipv6 api;
416 struct in6_addr **nexthop_list;
417 unsigned int *ifindex_list;
418 struct isis_nexthop6 *nexthop6;
419 int i, size;
420 struct listnode *node;
421 struct prefix_ipv6 prefix6;
422
Josh Bailey3f045a02012-03-24 08:35:20 -0700423 if (CHECK_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
jardineb5d44e2003-12-23 08:09:43 +0000424 return;
hassof390d2c2004-09-10 20:48:21 +0000425
Feng Luc99f3482014-10-16 09:52:36 +0800426 api.vrf_id = VRF_DEFAULT;
jardineb5d44e2003-12-23 08:09:43 +0000427 api.type = ZEBRA_ROUTE_ISIS;
428 api.flags = 0;
429 api.message = 0;
Avneesh Sachdevaa3b2642012-04-11 23:56:03 -0700430 api.safi = SAFI_UNICAST;
jardineb5d44e2003-12-23 08:09:43 +0000431 SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
432 SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX);
433 api.nexthop_num = listcount (route_info->nexthops6);
434 api.ifindex_num = listcount (route_info->nexthops6);
hassof390d2c2004-09-10 20:48:21 +0000435
jardineb5d44e2003-12-23 08:09:43 +0000436 /* allocate memory for nexthop_list */
437 size = sizeof (struct isis_nexthop6 *) * listcount (route_info->nexthops6);
438 nexthop_list = (struct in6_addr **) XMALLOC (MTYPE_ISIS_TMP, size);
hassof390d2c2004-09-10 20:48:21 +0000439 if (!nexthop_list)
440 {
441 zlog_err ("isis_zebra_route_del_ipv6: out of memory!");
442 return;
443 }
444
jardineb5d44e2003-12-23 08:09:43 +0000445 /* allocate memory for ifindex_list */
446 size = sizeof (unsigned int) * listcount (route_info->nexthops6);
447 ifindex_list = (unsigned int *) XMALLOC (MTYPE_ISIS_TMP, size);
hassof390d2c2004-09-10 20:48:21 +0000448 if (!ifindex_list)
449 {
450 zlog_err ("isis_zebra_route_del_ipv6: out of memory!");
451 XFREE (MTYPE_ISIS_TMP, nexthop_list);
452 return;
453 }
454
jardineb5d44e2003-12-23 08:09:43 +0000455 /* for each nexthop */
456 i = 0;
paul1eb8ef22005-04-07 07:30:20 +0000457 for (ALL_LIST_ELEMENTS_RO (route_info->nexthops6, node, nexthop6))
hassof390d2c2004-09-10 20:48:21 +0000458 {
hassof390d2c2004-09-10 20:48:21 +0000459 if (!IN6_IS_ADDR_LINKLOCAL (&nexthop6->ip6) &&
460 !IN6_IS_ADDR_UNSPECIFIED (&nexthop6->ip6))
461 {
462 api.nexthop_num--;
463 api.ifindex_num--;
464 continue;
465 }
466
467 nexthop_list[i] = &nexthop6->ip6;
468 ifindex_list[i] = nexthop6->ifindex;
469 i++;
jardineb5d44e2003-12-23 08:09:43 +0000470 }
hassof390d2c2004-09-10 20:48:21 +0000471
jardineb5d44e2003-12-23 08:09:43 +0000472 api.nexthop = nexthop_list;
473 api.ifindex = ifindex_list;
jardineb5d44e2003-12-23 08:09:43 +0000474
hassof390d2c2004-09-10 20:48:21 +0000475 if (api.nexthop_num && api.ifindex_num)
476 {
477 prefix6.family = AF_INET6;
478 prefix6.prefixlen = prefix->prefixlen;
479 memcpy (&prefix6.prefix, &prefix->u.prefix6, sizeof (struct in6_addr));
480 zapi_ipv6_route (ZEBRA_IPV6_ROUTE_DELETE, zclient, &prefix6, &api);
Josh Bailey3f045a02012-03-24 08:35:20 -0700481 UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
hassof390d2c2004-09-10 20:48:21 +0000482 }
483
484 XFREE (MTYPE_ISIS_TMP, nexthop_list);
485 XFREE (MTYPE_ISIS_TMP, ifindex_list);
486}
jardineb5d44e2003-12-23 08:09:43 +0000487
488#endif /* HAVE_IPV6 */
489
jardineb5d44e2003-12-23 08:09:43 +0000490void
491isis_zebra_route_update (struct prefix *prefix,
hassof390d2c2004-09-10 20:48:21 +0000492 struct isis_route_info *route_info)
jardineb5d44e2003-12-23 08:09:43 +0000493{
494 if (zclient->sock < 0)
495 return;
496
Feng Luc99f3482014-10-16 09:52:36 +0800497 if (!vrf_bitmap_check (zclient->redist[ZEBRA_ROUTE_ISIS], VRF_DEFAULT))
jardineb5d44e2003-12-23 08:09:43 +0000498 return;
499
hassof390d2c2004-09-10 20:48:21 +0000500 if (CHECK_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ACTIVE))
501 {
502 if (prefix->family == AF_INET)
503 isis_zebra_route_add_ipv4 (prefix, route_info);
jardineb5d44e2003-12-23 08:09:43 +0000504#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000505 else if (prefix->family == AF_INET6)
506 isis_zebra_route_add_ipv6 (prefix, route_info);
jardineb5d44e2003-12-23 08:09:43 +0000507#endif /* HAVE_IPV6 */
hassof390d2c2004-09-10 20:48:21 +0000508 }
509 else
510 {
511 if (prefix->family == AF_INET)
512 isis_zebra_route_del_ipv4 (prefix, route_info);
jardineb5d44e2003-12-23 08:09:43 +0000513#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000514 else if (prefix->family == AF_INET6)
515 isis_zebra_route_del_ipv6 (prefix, route_info);
jardineb5d44e2003-12-23 08:09:43 +0000516#endif /* HAVE_IPV6 */
hassof390d2c2004-09-10 20:48:21 +0000517 }
jardineb5d44e2003-12-23 08:09:43 +0000518 return;
519}
520
hasso92365882005-01-18 13:53:33 +0000521static int
hassof390d2c2004-09-10 20:48:21 +0000522isis_zebra_read_ipv4 (int command, struct zclient *zclient,
Feng Luc99f3482014-10-16 09:52:36 +0800523 zebra_size_t length, vrf_id_t vrf_id)
jardineb5d44e2003-12-23 08:09:43 +0000524{
525 struct stream *stream;
526 struct zapi_ipv4 api;
527 struct prefix_ipv4 p;
David Lamparterf50ee932015-03-04 07:13:38 +0100528 unsigned long ifindex __attribute__ ((unused));
529 struct in_addr nexthop __attribute__ ((unused));
jardineb5d44e2003-12-23 08:09:43 +0000530
531 stream = zclient->ibuf;
532 memset (&p, 0, sizeof (struct prefix_ipv4));
533 ifindex = 0;
534
hassof390d2c2004-09-10 20:48:21 +0000535 api.type = stream_getc (stream);
536 api.flags = stream_getc (stream);
jardineb5d44e2003-12-23 08:09:43 +0000537 api.message = stream_getc (stream);
538
539 p.family = AF_INET;
540 p.prefixlen = stream_getc (stream);
541 stream_get (&p.prefix, stream, PSIZE (p.prefixlen));
hassof390d2c2004-09-10 20:48:21 +0000542
543 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
544 {
jardineb5d44e2003-12-23 08:09:43 +0000545 api.nexthop_num = stream_getc (stream);
546 nexthop.s_addr = stream_get_ipv4 (stream);
hassof390d2c2004-09-10 20:48:21 +0000547 }
548 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX))
549 {
550 api.ifindex_num = stream_getc (stream);
551 ifindex = stream_getl (stream);
552 }
jardineb5d44e2003-12-23 08:09:43 +0000553 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
554 api.distance = stream_getc (stream);
555 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
556 api.metric = stream_getl (stream);
557 else
558 api.metric = 0;
hassof390d2c2004-09-10 20:48:21 +0000559
560 if (command == ZEBRA_IPV4_ROUTE_ADD)
561 {
hassoc89c05d2005-09-04 21:36:36 +0000562 if (isis->debugs & DEBUG_ZEBRA)
563 zlog_debug ("IPv4 Route add from Z");
hassof390d2c2004-09-10 20:48:21 +0000564 }
jardineb5d44e2003-12-23 08:09:43 +0000565
566 return 0;
567}
568
Paul Jakma41b36e92006-12-08 01:09:50 +0000569#ifdef HAVE_IPV6
hasso92365882005-01-18 13:53:33 +0000570static int
hassof390d2c2004-09-10 20:48:21 +0000571isis_zebra_read_ipv6 (int command, struct zclient *zclient,
Feng Luc99f3482014-10-16 09:52:36 +0800572 zebra_size_t length, vrf_id_t vrf_id)
jardineb5d44e2003-12-23 08:09:43 +0000573{
jardineb5d44e2003-12-23 08:09:43 +0000574 return 0;
575}
Paul Jakma41b36e92006-12-08 01:09:50 +0000576#endif
jardineb5d44e2003-12-23 08:09:43 +0000577
578#define ISIS_TYPE_IS_REDISTRIBUTED(T) \
Feng Luc99f3482014-10-16 09:52:36 +0800579T == ZEBRA_ROUTE_MAX ? \
580 vrf_bitmap_check (zclient->default_information, VRF_DEFAULT) : \
581 vrf_bitmap_check (zclient->redist[type], VRF_DEFAULT)
jardineb5d44e2003-12-23 08:09:43 +0000582
583int
584isis_distribute_list_update (int routetype)
585{
586 return 0;
587}
588
hasso92365882005-01-18 13:53:33 +0000589#if 0 /* Not yet. */
590static int
hassof390d2c2004-09-10 20:48:21 +0000591isis_redistribute_default_set (int routetype, int metric_type,
592 int metric_value)
jardineb5d44e2003-12-23 08:09:43 +0000593{
594 return 0;
595}
hasso92365882005-01-18 13:53:33 +0000596#endif /* 0 */
jardineb5d44e2003-12-23 08:09:43 +0000597
Feng Luc99f3482014-10-16 09:52:36 +0800598static void
599isis_zebra_connected (struct zclient *zclient)
600{
601 zclient_send_requests (zclient, VRF_DEFAULT);
602}
603
jardineb5d44e2003-12-23 08:09:43 +0000604void
Donald Sharp71252932015-09-24 09:25:19 -0400605isis_zebra_init (struct thread_master *master)
jardineb5d44e2003-12-23 08:09:43 +0000606{
Donald Sharp71252932015-09-24 09:25:19 -0400607 zclient = zclient_new (master);
jardineb5d44e2003-12-23 08:09:43 +0000608 zclient_init (zclient, ZEBRA_ROUTE_ISIS);
Feng Luc99f3482014-10-16 09:52:36 +0800609 zclient->zebra_connected = isis_zebra_connected;
hasso18a6dce2004-10-03 18:18:34 +0000610 zclient->router_id_update = isis_router_id_update_zebra;
jardineb5d44e2003-12-23 08:09:43 +0000611 zclient->interface_add = isis_zebra_if_add;
612 zclient->interface_delete = isis_zebra_if_del;
613 zclient->interface_up = isis_zebra_if_state_up;
614 zclient->interface_down = isis_zebra_if_state_down;
615 zclient->interface_address_add = isis_zebra_if_address_add;
616 zclient->interface_address_delete = isis_zebra_if_address_del;
617 zclient->ipv4_route_add = isis_zebra_read_ipv4;
618 zclient->ipv4_route_delete = isis_zebra_read_ipv4;
619#ifdef HAVE_IPV6
620 zclient->ipv6_route_add = isis_zebra_read_ipv6;
621 zclient->ipv6_route_delete = isis_zebra_read_ipv6;
622#endif /* HAVE_IPV6 */
623
624 return;
625}