]> git.proxmox.com Git - mirror_frr.git/blame - isisd/isis_zebra.c
zebra: On shutdown actually delete rn's assoc w/ other_tables
[mirror_frr.git] / isisd / isis_zebra.c
CommitLineData
eb5d44eb 1/*
d62a17ae 2 * IS-IS Rout(e)ing protocol - isis_zebra.c
eb5d44eb 3 *
4 * Copyright (C) 2001,2002 Sampo Saaristo
d62a17ae 5 * Tampere University of Technology
eb5d44eb 6 * Institute of Communications Engineering
f3ccedaa 7 * Copyright (C) 2013-2015 Christian Franke <chris@opensourcerouting.org>
eb5d44eb 8 *
d62a17ae 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)
eb5d44eb 12 * any later version.
13 *
d62a17ae 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
eb5d44eb 17 * more details.
896014f4
DL
18 *
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
eb5d44eb 22 */
23
24#include <zebra.h>
eb5d44eb 25
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"
f3ccedaa 36#include "nexthop.h"
7076bb2f 37#include "vrf.h"
8879bd22 38#include "libfrr.h"
eb5d44eb 39
c89c05dd 40#include "isisd/dict.h"
eb5d44eb 41#include "isisd/isis_constants.h"
42#include "isisd/isis_common.h"
3f045a08
JB
43#include "isisd/isis_flags.h"
44#include "isisd/isis_misc.h"
45#include "isisd/isis_circuit.h"
c89c05dd 46#include "isisd/isisd.h"
eb5d44eb 47#include "isisd/isis_circuit.h"
48#include "isisd/isis_csm.h"
3f045a08 49#include "isisd/isis_lsp.h"
eb5d44eb 50#include "isisd/isis_route.h"
51#include "isisd/isis_zebra.h"
f8c06e2c 52#include "isisd/isis_te.h"
eb5d44eb 53
54struct zclient *zclient = NULL;
55
18a6dce6 56/* Router-id update message from zebra. */
d62a17ae 57static int isis_router_id_update_zebra(int command, struct zclient *zclient,
58 zebra_size_t length, vrf_id_t vrf_id)
18a6dce6 59{
d62a17ae 60 struct isis_area *area;
61 struct listnode *node;
62 struct prefix router_id;
63
64 /*
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
71 zebra_router_id_update_read(zclient->ibuf, &router_id);
72 if (isis->router_id == router_id.u.prefix4.s_addr)
73 return 0;
74
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);
79
80 return 0;
18a6dce6 81}
eb5d44eb 82
d62a17ae 83static int isis_zebra_if_add(int command, struct zclient *zclient,
84 zebra_size_t length, vrf_id_t vrf_id)
eb5d44eb 85{
d62a17ae 86 struct interface *ifp;
eb5d44eb 87
d62a17ae 88 ifp = zebra_interface_add_read(zclient->ibuf, vrf_id);
f390d2c7 89
d62a17ae 90 if (isis->debugs & DEBUG_ZEBRA)
91 zlog_debug(
92 "Zebra I/F add: %s index %d flags %ld metric %d mtu %d",
93 ifp->name, ifp->ifindex, (long)ifp->flags, ifp->metric,
94 ifp->mtu);
f390d2c7 95
d62a17ae 96 if (if_is_operative(ifp))
97 isis_csm_state_change(IF_UP_FROM_Z, circuit_scan_by_ifp(ifp),
98 ifp);
f390d2c7 99
d62a17ae 100 return 0;
eb5d44eb 101}
102
d62a17ae 103static int isis_zebra_if_del(int command, struct zclient *zclient,
104 zebra_size_t length, vrf_id_t vrf_id)
eb5d44eb 105{
d62a17ae 106 struct interface *ifp;
107 struct stream *s;
eb5d44eb 108
d62a17ae 109 s = zclient->ibuf;
110 ifp = zebra_interface_state_read(s, vrf_id);
f390d2c7 111
d62a17ae 112 if (!ifp)
113 return 0;
eb5d44eb 114
d62a17ae 115 if (if_is_operative(ifp))
116 zlog_warn("Zebra: got delete of %s, but interface is still up",
117 ifp->name);
eb5d44eb 118
d62a17ae 119 if (isis->debugs & DEBUG_ZEBRA)
120 zlog_debug(
121 "Zebra I/F delete: %s index %d flags %ld metric %d mtu %d",
122 ifp->name, ifp->ifindex, (long)ifp->flags, ifp->metric,
123 ifp->mtu);
eb5d44eb 124
d62a17ae 125 isis_csm_state_change(IF_DOWN_FROM_Z, circuit_scan_by_ifp(ifp), ifp);
d2fc8896 126
d62a17ae 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);
f390d2c7 130
ff880b78 131 if_set_index(ifp, IFINDEX_INTERNAL);
d2fc8896 132
d62a17ae 133 return 0;
eb5d44eb 134}
135
d62a17ae 136static int isis_zebra_if_state_up(int command, struct zclient *zclient,
137 zebra_size_t length, vrf_id_t vrf_id)
eb5d44eb 138{
d62a17ae 139 struct interface *ifp;
f390d2c7 140
d62a17ae 141 ifp = zebra_interface_state_read(zclient->ibuf, vrf_id);
f390d2c7 142
d62a17ae 143 if (ifp == NULL)
144 return 0;
f390d2c7 145
d62a17ae 146 isis_csm_state_change(IF_UP_FROM_Z, circuit_scan_by_ifp(ifp), ifp);
f390d2c7 147
d62a17ae 148 return 0;
eb5d44eb 149}
150
d62a17ae 151static int isis_zebra_if_state_down(int command, struct zclient *zclient,
152 zebra_size_t length, vrf_id_t vrf_id)
eb5d44eb 153{
d62a17ae 154 struct interface *ifp;
155 struct isis_circuit *circuit;
f390d2c7 156
d62a17ae 157 ifp = zebra_interface_state_read(zclient->ibuf, vrf_id);
f390d2c7 158
d62a17ae 159 if (ifp == NULL)
160 return 0;
f390d2c7 161
d62a17ae 162 circuit = isis_csm_state_change(IF_DOWN_FROM_Z,
163 circuit_scan_by_ifp(ifp), ifp);
164 if (circuit)
165 SET_FLAG(circuit->flags, ISIS_CIRCUIT_FLAPPED_AFTER_SPF);
f390d2c7 166
d62a17ae 167 return 0;
eb5d44eb 168}
169
d62a17ae 170static int isis_zebra_if_address_add(int command, struct zclient *zclient,
171 zebra_size_t length, vrf_id_t vrf_id)
eb5d44eb 172{
d62a17ae 173 struct connected *c;
174 struct prefix *p;
175 char buf[PREFIX2STR_BUFFER];
eb5d44eb 176
d62a17ae 177 c = zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_ADD,
178 zclient->ibuf, vrf_id);
f390d2c7 179
d62a17ae 180 if (c == NULL)
181 return 0;
f390d2c7 182
d62a17ae 183 p = c->address;
f390d2c7 184
d62a17ae 185 prefix2str(p, buf, sizeof(buf));
eb5d44eb 186#ifdef EXTREME_DEBUG
d62a17ae 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);
eb5d44eb 191#endif /* EXTREME_DEBUG */
d62a17ae 192 if (if_is_operative(c->ifp))
193 isis_circuit_add_addr(circuit_scan_by_ifp(c->ifp), c);
eb5d44eb 194
d62a17ae 195 return 0;
eb5d44eb 196}
197
d62a17ae 198static int isis_zebra_if_address_del(int command, struct zclient *client,
199 zebra_size_t length, vrf_id_t vrf_id)
eb5d44eb 200{
d62a17ae 201 struct connected *c;
202 struct interface *ifp;
1cd80845 203#ifdef EXTREME_DEBUG
d62a17ae 204 struct prefix *p;
205 char buf[PREFIX2STR_BUFFER];
1cd80845 206#endif /* EXTREME_DEBUG */
eb5d44eb 207
d62a17ae 208 c = zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_DELETE,
209 zclient->ibuf, vrf_id);
f390d2c7 210
d62a17ae 211 if (c == NULL)
212 return 0;
f390d2c7 213
d62a17ae 214 ifp = c->ifp;
f390d2c7 215
f891f443 216#ifdef EXTREME_DEBUG
d62a17ae 217 p = c->address;
218 prefix2str(p, buf, sizeof(buf));
f891f443 219
d62a17ae 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);
f891f443 224#endif /* EXTREME_DEBUG */
f390d2c7 225
d62a17ae 226 if (if_is_operative(ifp))
227 isis_circuit_del_addr(circuit_scan_by_ifp(ifp), c);
228 connected_free(c);
f390d2c7 229
d62a17ae 230 return 0;
eb5d44eb 231}
232
d62a17ae 233static int isis_zebra_link_params(int command, struct zclient *zclient,
234 zebra_size_t length)
f8c06e2c 235{
d62a17ae 236 struct interface *ifp;
f8c06e2c 237
d62a17ae 238 ifp = zebra_interface_link_params_read(zclient->ibuf);
f8c06e2c 239
d62a17ae 240 if (ifp == NULL)
241 return 0;
f8c06e2c 242
d62a17ae 243 /* Update TE TLV */
244 isis_mpls_te_update(ifp);
f8c06e2c 245
d62a17ae 246 return 0;
f8c06e2c
OD
247}
248
f80dd32b
RW
249static void isis_zebra_route_add_route(struct prefix *prefix,
250 struct isis_route_info *route_info)
eb5d44eb 251{
c0721de4
RW
252 struct zapi_route api;
253 struct zapi_nexthop *api_nh;
d62a17ae 254 struct isis_nexthop *nexthop;
f80dd32b 255 struct isis_nexthop6 *nexthop6;
d62a17ae 256 struct listnode *node;
c0721de4 257 int count = 0;
d62a17ae 258
259 if (CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
260 return;
261
c0721de4
RW
262 memset(&api, 0, sizeof(api));
263 api.vrf_id = VRF_DEFAULT;
d5b2119c 264 api.nh_vrf_id = VRF_DEFAULT;
c0721de4
RW
265 api.type = ZEBRA_ROUTE_ISIS;
266 api.safi = SAFI_UNICAST;
267 api.prefix = *prefix;
268 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
269 SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
270 api.metric = route_info->cost;
2097cd8a 271#if 0
c0721de4
RW
272 SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE);
273 api.distance = route_info->depth;
2097cd8a 274#endif
f390d2c7 275
f80dd32b
RW
276 /* Nexthops */
277 switch (prefix->family) {
278 case AF_INET:
279 for (ALL_LIST_ELEMENTS_RO(route_info->nexthops, node,
280 nexthop)) {
a74e593b
RW
281 if (count >= MULTIPATH_NUM)
282 break;
f80dd32b
RW
283 api_nh = &api.nexthops[count];
284 /* FIXME: can it be ? */
285 if (nexthop->ip.s_addr != INADDR_ANY) {
286 api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX;
287 api_nh->gate.ipv4 = nexthop->ip;
288 } else {
289 api_nh->type = NEXTHOP_TYPE_IFINDEX;
290 }
291 api_nh->ifindex = nexthop->ifindex;
292 count++;
d62a17ae 293 }
f80dd32b
RW
294 break;
295 case AF_INET6:
296 for (ALL_LIST_ELEMENTS_RO(route_info->nexthops6, node,
297 nexthop6)) {
a74e593b
RW
298 if (count >= MULTIPATH_NUM)
299 break;
f80dd32b
RW
300 if (!IN6_IS_ADDR_LINKLOCAL(&nexthop6->ip6)
301 && !IN6_IS_ADDR_UNSPECIFIED(&nexthop6->ip6)) {
302 continue;
303 }
304
305 api_nh = &api.nexthops[count];
306 api_nh->gate.ipv6 = nexthop6->ip6;
307 api_nh->ifindex = nexthop6->ifindex;
308 api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX;
309 count++;
d62a17ae 310 }
f80dd32b 311 break;
d62a17ae 312 }
c0721de4
RW
313 if (!count)
314 return;
f390d2c7 315
c0721de4 316 api.nexthop_num = count;
f390d2c7 317
c0721de4
RW
318 zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api);
319 SET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
320 UNSET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC);
eb5d44eb 321}
322
f80dd32b
RW
323static void isis_zebra_route_del_route(struct prefix *prefix,
324 struct isis_route_info *route_info)
eb5d44eb 325{
c0721de4 326 struct zapi_route api;
d62a17ae 327
328 if (!CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
329 return;
330
c0721de4 331 memset(&api, 0, sizeof(api));
d62a17ae 332 api.vrf_id = VRF_DEFAULT;
d5b2119c 333 api.nh_vrf_id = VRF_DEFAULT;
d62a17ae 334 api.type = ZEBRA_ROUTE_ISIS;
d62a17ae 335 api.safi = SAFI_UNICAST;
c0721de4 336 api.prefix = *prefix;
f390d2c7 337
c0721de4
RW
338 zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api);
339 UNSET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
eb5d44eb 340}
341
d62a17ae 342void isis_zebra_route_update(struct prefix *prefix,
343 struct isis_route_info *route_info)
eb5d44eb 344{
d62a17ae 345 if (zclient->sock < 0)
346 return;
347
f80dd32b
RW
348 if (CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ACTIVE))
349 isis_zebra_route_add_route(prefix, route_info);
350 else
351 isis_zebra_route_del_route(prefix, route_info);
eb5d44eb 352}
353
74489921
RW
354static int isis_zebra_read(int command, struct zclient *zclient,
355 zebra_size_t length, vrf_id_t vrf_id)
eb5d44eb 356{
74489921 357 struct zapi_route api;
d62a17ae 358
74489921
RW
359 if (zapi_route_decode(zclient->ibuf, &api) < 0)
360 return -1;
d62a17ae 361
74489921
RW
362 /* we completely ignore srcdest routes for now. */
363 if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX))
d62a17ae 364 return 0;
365
d62a17ae 366 /*
367 * Avoid advertising a false default reachability. (A default
368 * route installed by IS-IS gets redistributed from zebra back
369 * into IS-IS causing us to start advertising default reachabity
370 * without this check)
371 */
74489921
RW
372 if (api.prefix.prefixlen == 0 && api.type == ZEBRA_ROUTE_ISIS)
373 command = ZEBRA_REDISTRIBUTE_ROUTE_DEL;
d62a17ae 374
74489921
RW
375 if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD)
376 isis_redist_add(api.type, &api.prefix, api.distance,
377 api.metric);
d62a17ae 378 else
74489921 379 isis_redist_delete(api.type, &api.prefix);
d62a17ae 380
381 return 0;
eb5d44eb 382}
eb5d44eb 383
d62a17ae 384int isis_distribute_list_update(int routetype)
eb5d44eb 385{
d62a17ae 386 return 0;
eb5d44eb 387}
388
d62a17ae 389void isis_zebra_redistribute_set(afi_t afi, int type)
eb5d44eb 390{
d62a17ae 391 if (type == DEFAULT_ROUTE)
392 zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_ADD,
393 zclient, VRF_DEFAULT);
394 else
395 zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, afi, type,
396 0, VRF_DEFAULT);
f3ccedaa
CF
397}
398
d62a17ae 399void isis_zebra_redistribute_unset(afi_t afi, int type)
f3ccedaa 400{
d62a17ae 401 if (type == DEFAULT_ROUTE)
402 zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_DELETE,
403 zclient, VRF_DEFAULT);
404 else
405 zclient_redistribute(ZEBRA_REDISTRIBUTE_DELETE, zclient, afi,
406 type, 0, VRF_DEFAULT);
eb5d44eb 407}
408
d62a17ae 409static void isis_zebra_connected(struct zclient *zclient)
7076bb2f 410{
d62a17ae 411 zclient_send_reg_requests(zclient, VRF_DEFAULT);
7076bb2f
FL
412}
413
d62a17ae 414void isis_zebra_init(struct thread_master *master)
eb5d44eb 415{
e1a1880d 416 zclient = zclient_new_notify(master, &zclient_options_default);
342213ea 417 zclient_init(zclient, ZEBRA_ROUTE_ISIS, 0, &isisd_privs);
d62a17ae 418 zclient->zebra_connected = isis_zebra_connected;
419 zclient->router_id_update = isis_router_id_update_zebra;
420 zclient->interface_add = isis_zebra_if_add;
421 zclient->interface_delete = isis_zebra_if_del;
422 zclient->interface_up = isis_zebra_if_state_up;
423 zclient->interface_down = isis_zebra_if_state_down;
424 zclient->interface_address_add = isis_zebra_if_address_add;
425 zclient->interface_address_delete = isis_zebra_if_address_del;
426 zclient->interface_link_params = isis_zebra_link_params;
74489921
RW
427 zclient->redistribute_route_add = isis_zebra_read;
428 zclient->redistribute_route_del = isis_zebra_read;
d62a17ae 429
430 return;
eb5d44eb 431}
8d429559 432
d62a17ae 433void isis_zebra_stop(void)
8d429559 434{
d62a17ae 435 zclient_stop(zclient);
436 zclient_free(zclient);
8879bd22 437 frr_fini();
8d429559 438}