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