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