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