]> git.proxmox.com Git - mirror_frr.git/blob - isisd/isis_zebra.c
Merge remote-tracking branch 'frr/master' into warnings
[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 "if.h"
31 #include "network.h"
32 #include "prefix.h"
33 #include "zclient.h"
34 #include "stream.h"
35 #include "linklist.h"
36 #include "nexthop.h"
37 #include "vrf.h"
38 #include "libfrr.h"
39
40 #include "isisd/dict.h"
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 /* Router-id update message from zebra. */
57 static int isis_router_id_update_zebra(int command, struct zclient *zclient,
58 zebra_size_t length, vrf_id_t vrf_id)
59 {
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;
81 }
82
83 static int isis_zebra_if_add(int command, struct zclient *zclient,
84 zebra_size_t length, vrf_id_t vrf_id)
85 {
86 struct interface *ifp;
87
88 ifp = zebra_interface_add_read(zclient->ibuf, vrf_id);
89
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);
95
96 if (if_is_operative(ifp))
97 isis_csm_state_change(IF_UP_FROM_Z, circuit_scan_by_ifp(ifp),
98 ifp);
99
100 return 0;
101 }
102
103 static int isis_zebra_if_del(int command, struct zclient *zclient,
104 zebra_size_t length, vrf_id_t vrf_id)
105 {
106 struct interface *ifp;
107 struct stream *s;
108
109 s = zclient->ibuf;
110 ifp = zebra_interface_state_read(s, vrf_id);
111
112 if (!ifp)
113 return 0;
114
115 if (if_is_operative(ifp))
116 zlog_warn("Zebra: got delete of %s, but interface is still up",
117 ifp->name);
118
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);
124
125 isis_csm_state_change(IF_DOWN_FROM_Z, circuit_scan_by_ifp(ifp), ifp);
126
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);
130
131 if_set_index(ifp, IFINDEX_INTERNAL);
132
133 return 0;
134 }
135
136 static int isis_zebra_if_state_up(int command, struct zclient *zclient,
137 zebra_size_t length, vrf_id_t vrf_id)
138 {
139 struct interface *ifp;
140
141 ifp = zebra_interface_state_read(zclient->ibuf, vrf_id);
142
143 if (ifp == NULL)
144 return 0;
145
146 isis_csm_state_change(IF_UP_FROM_Z, circuit_scan_by_ifp(ifp), ifp);
147
148 return 0;
149 }
150
151 static int isis_zebra_if_state_down(int command, struct zclient *zclient,
152 zebra_size_t length, vrf_id_t vrf_id)
153 {
154 struct interface *ifp;
155 struct isis_circuit *circuit;
156
157 ifp = zebra_interface_state_read(zclient->ibuf, vrf_id);
158
159 if (ifp == NULL)
160 return 0;
161
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);
166
167 return 0;
168 }
169
170 static int isis_zebra_if_address_add(int command, struct zclient *zclient,
171 zebra_size_t length, vrf_id_t vrf_id)
172 {
173 struct connected *c;
174 struct prefix *p;
175 char buf[PREFIX2STR_BUFFER];
176
177 c = zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_ADD,
178 zclient->ibuf, vrf_id);
179
180 if (c == NULL)
181 return 0;
182
183 p = c->address;
184
185 prefix2str(p, buf, sizeof(buf));
186 #ifdef EXTREME_DEBUG
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);
191 #endif /* EXTREME_DEBUG */
192 if (if_is_operative(c->ifp))
193 isis_circuit_add_addr(circuit_scan_by_ifp(c->ifp), c);
194
195 return 0;
196 }
197
198 static int isis_zebra_if_address_del(int command, struct zclient *client,
199 zebra_size_t length, vrf_id_t vrf_id)
200 {
201 struct connected *c;
202 struct interface *ifp;
203 #ifdef EXTREME_DEBUG
204 struct prefix *p;
205 char buf[PREFIX2STR_BUFFER];
206 #endif /* EXTREME_DEBUG */
207
208 c = zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_DELETE,
209 zclient->ibuf, vrf_id);
210
211 if (c == NULL)
212 return 0;
213
214 ifp = c->ifp;
215
216 #ifdef EXTREME_DEBUG
217 p = c->address;
218 prefix2str(p, buf, sizeof(buf));
219
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);
224 #endif /* EXTREME_DEBUG */
225
226 if (if_is_operative(ifp))
227 isis_circuit_del_addr(circuit_scan_by_ifp(ifp), c);
228 connected_free(c);
229
230 return 0;
231 }
232
233 static int isis_zebra_link_params(int command, struct zclient *zclient,
234 zebra_size_t length)
235 {
236 struct interface *ifp;
237
238 ifp = zebra_interface_link_params_read(zclient->ibuf);
239
240 if (ifp == NULL)
241 return 0;
242
243 /* Update TE TLV */
244 isis_mpls_te_update(ifp);
245
246 return 0;
247 }
248
249 static void isis_zebra_route_add_route(struct prefix *prefix,
250 struct prefix_ipv6 *src_p,
251 struct isis_route_info *route_info)
252 {
253 struct zapi_route api;
254 struct zapi_nexthop *api_nh;
255 struct isis_nexthop *nexthop;
256 struct isis_nexthop6 *nexthop6;
257 struct listnode *node;
258 int count = 0;
259
260 if (CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
261 return;
262
263 memset(&api, 0, sizeof(api));
264 if (fabricd)
265 api.flags |= ZEBRA_FLAG_ONLINK;
266 api.vrf_id = VRF_DEFAULT;
267 api.type = PROTO_TYPE;
268 api.safi = SAFI_UNICAST;
269 api.prefix = *prefix;
270 if (src_p && src_p->prefixlen) {
271 api.src_prefix = *src_p;
272 SET_FLAG(api.message, ZAPI_MESSAGE_SRCPFX);
273 }
274 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
275 SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
276 api.metric = route_info->cost;
277 #if 0
278 SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE);
279 api.distance = route_info->depth;
280 #endif
281
282 /* Nexthops */
283 switch (prefix->family) {
284 case AF_INET:
285 for (ALL_LIST_ELEMENTS_RO(route_info->nexthops, node,
286 nexthop)) {
287 if (count >= MULTIPATH_NUM)
288 break;
289 api_nh = &api.nexthops[count];
290 api_nh->vrf_id = VRF_DEFAULT;
291 /* FIXME: can it be ? */
292 if (nexthop->ip.s_addr != INADDR_ANY) {
293 api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX;
294 api_nh->gate.ipv4 = nexthop->ip;
295 } else {
296 api_nh->type = NEXTHOP_TYPE_IFINDEX;
297 }
298 api_nh->ifindex = nexthop->ifindex;
299 count++;
300 }
301 break;
302 case AF_INET6:
303 for (ALL_LIST_ELEMENTS_RO(route_info->nexthops6, node,
304 nexthop6)) {
305 if (count >= MULTIPATH_NUM)
306 break;
307 if (!IN6_IS_ADDR_LINKLOCAL(&nexthop6->ip6)
308 && !IN6_IS_ADDR_UNSPECIFIED(&nexthop6->ip6)) {
309 continue;
310 }
311
312 api_nh = &api.nexthops[count];
313 api_nh->vrf_id = VRF_DEFAULT;
314 api_nh->gate.ipv6 = nexthop6->ip6;
315 api_nh->ifindex = nexthop6->ifindex;
316 api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX;
317 count++;
318 }
319 break;
320 }
321 if (!count)
322 return;
323
324 api.nexthop_num = count;
325
326 zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api);
327 SET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
328 UNSET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC);
329 }
330
331 static void isis_zebra_route_del_route(struct prefix *prefix,
332 struct prefix_ipv6 *src_p,
333 struct isis_route_info *route_info)
334 {
335 struct zapi_route api;
336
337 if (!CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
338 return;
339
340 memset(&api, 0, sizeof(api));
341 api.vrf_id = VRF_DEFAULT;
342 api.type = PROTO_TYPE;
343 api.safi = SAFI_UNICAST;
344 api.prefix = *prefix;
345 if (src_p && src_p->prefixlen) {
346 api.src_prefix = *src_p;
347 SET_FLAG(api.message, ZAPI_MESSAGE_SRCPFX);
348 }
349
350 zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api);
351 UNSET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
352 }
353
354 void isis_zebra_route_update(struct prefix *prefix,
355 struct prefix_ipv6 *src_p,
356 struct isis_route_info *route_info)
357 {
358 if (zclient->sock < 0)
359 return;
360
361 if (CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ACTIVE))
362 isis_zebra_route_add_route(prefix, src_p, route_info);
363 else
364 isis_zebra_route_del_route(prefix, src_p, route_info);
365 }
366
367 static int isis_zebra_read(int command, struct zclient *zclient,
368 zebra_size_t length, vrf_id_t vrf_id)
369 {
370 struct zapi_route api;
371
372 if (zapi_route_decode(zclient->ibuf, &api) < 0)
373 return -1;
374
375 /*
376 * Avoid advertising a false default reachability. (A default
377 * route installed by IS-IS gets redistributed from zebra back
378 * into IS-IS causing us to start advertising default reachabity
379 * without this check)
380 */
381 if (api.prefix.prefixlen == 0
382 && api.src_prefix.prefixlen == 0
383 && api.type == PROTO_TYPE) {
384 command = ZEBRA_REDISTRIBUTE_ROUTE_DEL;
385 }
386
387 if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD)
388 isis_redist_add(api.type, &api.prefix, &api.src_prefix,
389 api.distance, api.metric);
390 else
391 isis_redist_delete(api.type, &api.prefix, &api.src_prefix);
392
393 return 0;
394 }
395
396 int isis_distribute_list_update(int routetype)
397 {
398 return 0;
399 }
400
401 void isis_zebra_redistribute_set(afi_t afi, int type)
402 {
403 if (type == DEFAULT_ROUTE)
404 zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_ADD,
405 zclient, VRF_DEFAULT);
406 else
407 zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, afi, type,
408 0, VRF_DEFAULT);
409 }
410
411 void isis_zebra_redistribute_unset(afi_t afi, int type)
412 {
413 if (type == DEFAULT_ROUTE)
414 zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_DELETE,
415 zclient, VRF_DEFAULT);
416 else
417 zclient_redistribute(ZEBRA_REDISTRIBUTE_DELETE, zclient, afi,
418 type, 0, VRF_DEFAULT);
419 }
420
421 static void isis_zebra_connected(struct zclient *zclient)
422 {
423 zclient_send_reg_requests(zclient, VRF_DEFAULT);
424 }
425
426 void isis_zebra_init(struct thread_master *master)
427 {
428 zclient = zclient_new_notify(master, &zclient_options_default);
429 zclient_init(zclient, PROTO_TYPE, 0, &isisd_privs);
430 zclient->zebra_connected = isis_zebra_connected;
431 zclient->router_id_update = isis_router_id_update_zebra;
432 zclient->interface_add = isis_zebra_if_add;
433 zclient->interface_delete = isis_zebra_if_del;
434 zclient->interface_up = isis_zebra_if_state_up;
435 zclient->interface_down = isis_zebra_if_state_down;
436 zclient->interface_address_add = isis_zebra_if_address_add;
437 zclient->interface_address_delete = isis_zebra_if_address_del;
438 zclient->interface_link_params = isis_zebra_link_params;
439 zclient->redistribute_route_add = isis_zebra_read;
440 zclient->redistribute_route_del = isis_zebra_read;
441
442 return;
443 }
444
445 void isis_zebra_stop(void)
446 {
447 zclient_stop(zclient);
448 zclient_free(zclient);
449 frr_fini();
450 }